From 4b08fa133e852af2d5057b7a6596c41ea7dec190 Mon Sep 17 00:00:00 2001 From: serso Date: Mon, 24 Sep 2012 17:20:16 +0400 Subject: [PATCH] Conversion --- .../android/calculator/Calculator.java | 126 +-- .../CalculatorConversionEventData.java | 26 + .../CalculatorConversionEventDataImpl.java | 98 ++ .../calculator/CalculatorDisplayImpl.java | 318 +++---- .../CalculatorEvaluationEventData.java | 36 +- .../CalculatorEvaluationEventDataImpl.java | 134 +-- .../calculator/CalculatorEventData.java | 34 +- .../calculator/CalculatorEventDataId.java | 24 - .../calculator/CalculatorEventDataIdImpl.java | 75 -- .../calculator/CalculatorEventDataImpl.java | 141 +-- .../calculator/CalculatorEventType.java | 173 ++-- .../android/calculator/CalculatorImpl.java | 838 +++++++++--------- .../android/calculator/CalculatorUtils.java | 44 +- .../android/calculator/ConversionFailure.java | 14 + .../calculator/ConversionFailureImpl.java | 24 + .../history/CalculatorHistoryImpl.java | 432 ++++----- .../units/CalculatorNumeralBase.java | 99 +++ .../math/units/ConversionException.java | 15 + .../solovyev/math/units/ConversionUtils.java | 38 + .../android/calculator/AndroidCalculator.java | 267 +++--- .../calculator/AndroidNumeralBase.java | 72 +- .../calculator/ConversionMenuItem.java | 109 ++- .../view/NumeralBaseConverterDialog.java | 189 ++-- .../view/UnitConverterViewBuilder.java | 445 +++++----- .../android/AndroidNumeralBaseTest.java | 48 +- 25 files changed, 2036 insertions(+), 1783 deletions(-) create mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorConversionEventData.java create mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorConversionEventDataImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java create mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/ConversionFailure.java create mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/ConversionFailureImpl.java create mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/units/CalculatorNumeralBase.java create mode 100644 calculatorpp-core/src/main/java/org/solovyev/math/units/ConversionException.java create mode 100644 calculatorpp-core/src/main/java/org/solovyev/math/units/ConversionUtils.java diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java index 14380adf..13efe6e9 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java @@ -1,58 +1,68 @@ -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.history.CalculatorHistoryState; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.common.history.HistoryControl; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:38 - */ -public interface Calculator extends CalculatorEventContainer, HistoryControl { - - void init(); - - /* - ********************************************************************** - * - * CALCULATIONS - * - ********************************************************************** - */ - - void evaluate(); - - void evaluate(@NotNull Long sequenceId); - - void simplify(); - - @NotNull - CalculatorEventDataId evaluate(@NotNull JsclOperation operation, - @NotNull String expression); - - @NotNull - CalculatorEventDataId evaluate(@NotNull JsclOperation operation, - @NotNull String expression, - @NotNull Long sequenceId); - - @NotNull - CalculatorEventDataId convert(@NotNull Generic generic, @NotNull NumeralBase to); - - /* - ********************************************************************** - * - * EVENTS - * - ********************************************************************** - */ - @NotNull - CalculatorEventDataId fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data); - - @NotNull - CalculatorEventDataId fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data, @NotNull Long sequenceId); -} +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.history.CalculatorHistoryState; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.common.history.HistoryControl; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 16:38 + */ +public interface Calculator extends CalculatorEventContainer, HistoryControl { + + void init(); + + /* + ********************************************************************** + * + * CALCULATIONS + * + ********************************************************************** + */ + + void evaluate(); + + void evaluate(@NotNull Long sequenceId); + + void simplify(); + + @NotNull + CalculatorEventData evaluate(@NotNull JsclOperation operation, + @NotNull String expression); + + @NotNull + CalculatorEventData evaluate(@NotNull JsclOperation operation, + @NotNull String expression, + @NotNull Long sequenceId); + + /* + ********************************************************************** + * + * CONVERSION + * + ********************************************************************** + */ + + boolean isConversionPossible(@NotNull Generic generic, @NotNull NumeralBase from, @NotNull NumeralBase to); + + @NotNull + CalculatorEventData convert(@NotNull Generic generic, @NotNull NumeralBase to); + + /* + ********************************************************************** + * + * EVENTS + * + ********************************************************************** + */ + @NotNull + CalculatorEventData fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data); + + @NotNull + CalculatorEventData fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data, @NotNull Long sequenceId); +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorConversionEventData.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorConversionEventData.java new file mode 100644 index 00000000..ffab77e0 --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorConversionEventData.java @@ -0,0 +1,26 @@ +package org.solovyev.android.calculator; + +import jscl.NumeralBase; +import jscl.math.Generic; +import org.jetbrains.annotations.NotNull; + +/** + * User: Solovyev_S + * Date: 24.09.12 + * Time: 16:45 + */ +public interface CalculatorConversionEventData extends CalculatorEventData { + + // display state on the moment of conversion + @NotNull + CalculatorDisplayViewState getDisplayState(); + + @NotNull + NumeralBase getFromNumeralBase(); + + @NotNull + NumeralBase getToNumeralBase(); + + @NotNull + Generic getValue(); +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorConversionEventDataImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorConversionEventDataImpl.java new file mode 100644 index 00000000..b121b4cf --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorConversionEventDataImpl.java @@ -0,0 +1,98 @@ +package org.solovyev.android.calculator; + +import jscl.NumeralBase; +import jscl.math.Generic; +import org.jetbrains.annotations.NotNull; + +/** + * User: Solovyev_S + * Date: 24.09.12 + * Time: 16:48 + */ +public class CalculatorConversionEventDataImpl implements CalculatorConversionEventData { + + @NotNull + private CalculatorEventData calculatorEventData; + + @NotNull + private NumeralBase fromNumeralBase; + + @NotNull + private NumeralBase toNumeralBase; + + @NotNull + private Generic value; + + @NotNull + private CalculatorDisplayViewState displayState; + + private CalculatorConversionEventDataImpl() { + } + + @NotNull + public static CalculatorConversionEventData newInstance(@NotNull CalculatorEventData calculatorEventData, + @NotNull Generic value, + @NotNull NumeralBase from, + @NotNull NumeralBase to, + @NotNull CalculatorDisplayViewState displayViewState) { + final CalculatorConversionEventDataImpl result = new CalculatorConversionEventDataImpl(); + + result.calculatorEventData = calculatorEventData; + result.value = value; + result.displayState = displayViewState; + result.fromNumeralBase = from; + result.toNumeralBase = to; + + return result; + } + + @Override + public long getEventId() { + return calculatorEventData.getEventId(); + } + + @Override + @NotNull + public Long getSequenceId() { + return calculatorEventData.getSequenceId(); + } + + @Override + public boolean isAfter(@NotNull CalculatorEventData that) { + return calculatorEventData.isAfter(that); + } + + @Override + public boolean isSameSequence(@NotNull CalculatorEventData that) { + return calculatorEventData.isSameSequence(that); + } + + @Override + public boolean isAfterSequence(@NotNull CalculatorEventData that) { + return calculatorEventData.isAfterSequence(that); + } + + @NotNull + @Override + public CalculatorDisplayViewState getDisplayState() { + return this.displayState; + } + + @Override + @NotNull + public NumeralBase getFromNumeralBase() { + return fromNumeralBase; + } + + @Override + @NotNull + public NumeralBase getToNumeralBase() { + return toNumeralBase; + } + + @Override + @NotNull + public Generic getValue() { + return value; + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayImpl.java index fe524be4..0bb47562 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayImpl.java @@ -1,148 +1,170 @@ -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; - - @Nullable - private CalculatorDisplayView view; - - @NotNull - private final Object viewLock = new Object(); - - @NotNull - private CalculatorDisplayViewState viewState = CalculatorDisplayViewStateImpl.newDefaultInstance(); - - @NotNull - private final Calculator calculator; - - public CalculatorDisplayImpl(@NotNull Calculator calculator) { - this.calculator = calculator; - this.lastCalculatorEventData = CalculatorEventDataImpl.newInstance(CalculatorUtils.createFirstEventDataId()); - this.calculator.addCalculatorEventListener(this); - } - - @Override - public void setView(@Nullable CalculatorDisplayView view) { - synchronized (viewLock) { - this.view = view; - - if (view != null) { - this.view.setState(viewState); - } - } - } - - @Nullable - @Override - public CalculatorDisplayView getView() { - return this.view; - } - - @NotNull - @Override - public CalculatorDisplayViewState getViewState() { - return this.viewState; - } - - @Override - public void setViewState(@NotNull CalculatorDisplayViewState newViewState) { - synchronized (viewLock) { - final CalculatorDisplayViewState oldViewState = setViewState0(newViewState); - - this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState)); - } - } - - private void setViewStateForSequence(@NotNull CalculatorDisplayViewState newViewState, @NotNull Long sequenceId) { - synchronized (viewLock) { - final CalculatorDisplayViewState oldViewState = setViewState0(newViewState); - - this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState), sequenceId); - } - } - - // must be synchronized with viewLock - @NotNull - private CalculatorDisplayViewState setViewState0(@NotNull CalculatorDisplayViewState newViewState) { - final CalculatorDisplayViewState oldViewState = this.viewState; - - this.viewState = newViewState; - if (this.view != null) { - this.view.setState(newViewState); - } - return oldViewState; - } - - @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.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId()); - } - - private void processCalculationCancelled(@NotNull CalculatorEvaluationEventData calculatorEventData) { - final String errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error); - - this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId()); - } - - private void processCalculationResult(@NotNull CalculatorEvaluationEventData calculatorEventData, @NotNull CalculatorOutput data) { - final String stringResult = data.getStringResult(); - this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newValidState(calculatorEventData.getOperation(), data.getResult(), stringResult, 0), calculatorEventData.getSequenceId()); - } -} +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; + + @Nullable + private CalculatorDisplayView view; + + @NotNull + private final Object viewLock = new Object(); + + @NotNull + private CalculatorDisplayViewState viewState = CalculatorDisplayViewStateImpl.newDefaultInstance(); + + @NotNull + private final Calculator calculator; + + public CalculatorDisplayImpl(@NotNull Calculator calculator) { + this.calculator = calculator; + this.lastCalculatorEventData = CalculatorUtils.createFirstEventDataId(); + this.calculator.addCalculatorEventListener(this); + } + + @Override + public void setView(@Nullable CalculatorDisplayView view) { + synchronized (viewLock) { + this.view = view; + + if (view != null) { + this.view.setState(viewState); + } + } + } + + @Nullable + @Override + public CalculatorDisplayView getView() { + return this.view; + } + + @NotNull + @Override + public CalculatorDisplayViewState getViewState() { + return this.viewState; + } + + @Override + public void setViewState(@NotNull CalculatorDisplayViewState newViewState) { + synchronized (viewLock) { + final CalculatorDisplayViewState oldViewState = setViewState0(newViewState); + + this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState)); + } + } + + private void setViewStateForSequence(@NotNull CalculatorDisplayViewState newViewState, @NotNull Long sequenceId) { + synchronized (viewLock) { + final CalculatorDisplayViewState oldViewState = setViewState0(newViewState); + + this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState), sequenceId); + } + } + + // must be synchronized with viewLock + @NotNull + private CalculatorDisplayViewState setViewState0(@NotNull CalculatorDisplayViewState newViewState) { + final CalculatorDisplayViewState oldViewState = this.viewState; + + this.viewState = newViewState; + if (this.view != null) { + this.view.setState(newViewState); + } + return oldViewState; + } + + @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, conversion_result, conversion_failed)) { + + if (calculatorEventData.isAfter(lastCalculatorEventData)) { + lastCalculatorEventData = calculatorEventData; + } + + switch (calculatorEventType) { + case conversion_failed: + processConversationFailed((CalculatorConversionEventData) calculatorEventData, (ConversionFailure) data); + break; + case conversion_result: + processConversationResult((CalculatorConversionEventData)calculatorEventData, (String)data); + break; + 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 processConversationFailed(@NotNull CalculatorConversionEventData calculatorEventData, + @NotNull ConversionFailure data) { + this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getDisplayState().getOperation(), CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error)), calculatorEventData.getSequenceId()); + + } + + 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.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId()); + } + + private void processCalculationCancelled(@NotNull CalculatorEvaluationEventData calculatorEventData) { + final String errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error); + + this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId()); + } + + private void processCalculationResult(@NotNull CalculatorEvaluationEventData calculatorEventData, @NotNull CalculatorOutput data) { + final String stringResult = data.getStringResult(); + this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newValidState(calculatorEventData.getOperation(), data.getResult(), stringResult, 0), calculatorEventData.getSequenceId()); + } + + private void processConversationResult(@NotNull CalculatorConversionEventData calculatorEventData, @NotNull String result) { + // add prefix + if (calculatorEventData.getFromNumeralBase() != calculatorEventData.getToNumeralBase()) { + result = calculatorEventData.getToNumeralBase().getJsclPrefix() + result; + } + + final CalculatorDisplayViewState displayState = calculatorEventData.getDisplayState(); + this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newValidState(displayState.getOperation(), displayState.getResult(), result, 0), calculatorEventData.getSequenceId()); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventData.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventData.java index 45c74178..f9c1ba10 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventData.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventData.java @@ -1,18 +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(); -} +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(); +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java index 3609dd34..f4e449ba 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java @@ -1,67 +1,67 @@ -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: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(); - } - - @NotNull - @Override - public Long getSequenceId() { - return calculatorEventData.getSequenceId(); - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId that) { - return calculatorEventData.isAfter(that); - } - - @Override - public boolean isSameSequence(@NotNull CalculatorEventDataId that) { - return this.calculatorEventData.isSameSequence(that); - } - - @Override - public boolean isAfterSequence(@NotNull CalculatorEventDataId that) { - return this.calculatorEventData.isAfterSequence(that); - } -} +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: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(); + } + + @NotNull + @Override + public Long getSequenceId() { + return calculatorEventData.getSequenceId(); + } + + @Override + public boolean isAfter(@NotNull CalculatorEventData that) { + return calculatorEventData.isAfter(that); + } + + @Override + public boolean isSameSequence(@NotNull CalculatorEventData that) { + return this.calculatorEventData.isSameSequence(that); + } + + @Override + public boolean isAfterSequence(@NotNull CalculatorEventData that) { + return this.calculatorEventData.isAfterSequence(that); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventData.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventData.java index 567808a7..5121be19 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventData.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventData.java @@ -1,10 +1,24 @@ -package org.solovyev.android.calculator; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:51 - */ -public interface CalculatorEventData extends CalculatorEventDataId { - -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 18:18 + */ +public interface CalculatorEventData { + + // the higher id => the later event + long getEventId(); + + // the higher id => the later event + @NotNull + Long getSequenceId(); + + boolean isAfter(@NotNull CalculatorEventData that); + + boolean isSameSequence(@NotNull CalculatorEventData that); + + boolean isAfterSequence(@NotNull CalculatorEventData that); +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java deleted file mode 100644 index c6f1db63..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * 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 - @NotNull - Long getSequenceId(); - - boolean isAfter(@NotNull CalculatorEventDataId that); - - boolean isSameSequence(@NotNull CalculatorEventDataId that); - - boolean isAfterSequence(@NotNull CalculatorEventDataId that); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java deleted file mode 100644 index 7d207bdf..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 18:18 - */ -class CalculatorEventDataIdImpl implements CalculatorEventDataId { - - private static final long NO_SEQUENCE = -1L; - - private final long eventId; - - @NotNull - private Long sequenceId = NO_SEQUENCE; - - private CalculatorEventDataIdImpl(long id, @NotNull Long sequenceId) { - this.eventId = id; - this.sequenceId = sequenceId; - } - - @NotNull - static CalculatorEventDataId newInstance(long id, @NotNull Long sequenceId) { - return new CalculatorEventDataIdImpl(id, sequenceId); - } - - @Override - public long getEventId() { - return this.eventId; - } - - @NotNull - @Override - public Long getSequenceId() { - return this.sequenceId; - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId that) { - return this.eventId > that.getEventId(); - } - - @Override - public boolean isSameSequence(@NotNull CalculatorEventDataId that) { - return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId.equals(that.getSequenceId()); - } - - @Override - public boolean isAfterSequence(@NotNull CalculatorEventDataId that) { - return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId > that.getSequenceId(); - } - - @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.equals(that.sequenceId)) - return false; - - return true; - } - - @Override - public int hashCode() { - int result = (int) (eventId ^ (eventId >>> 32)); - result = 31 * result + (sequenceId.hashCode()); - return result; - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java index 2d76a296..23ec547e 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java @@ -1,66 +1,75 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * 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(); - } - - @NotNull - @Override - public Long getSequenceId() { - return calculatorEventDataId.getSequenceId(); - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId that) { - return this.calculatorEventDataId.isAfter(that); - } - - @Override - public boolean isSameSequence(@NotNull CalculatorEventDataId that) { - return this.calculatorEventDataId.isSameSequence(that); - } - - @Override - public boolean isAfterSequence(@NotNull CalculatorEventDataId that) { - return this.calculatorEventDataId.isAfterSequence(that); - } - - @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(); - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 18:18 + */ +class CalculatorEventDataImpl implements CalculatorEventData { + + private static final long NO_SEQUENCE = -1L; + + private final long eventId; + + @NotNull + private Long sequenceId = NO_SEQUENCE; + + private CalculatorEventDataImpl(long id, @NotNull Long sequenceId) { + this.eventId = id; + this.sequenceId = sequenceId; + } + + @NotNull + static CalculatorEventData newInstance(long id, @NotNull Long sequenceId) { + return new CalculatorEventDataImpl(id, sequenceId); + } + + @Override + public long getEventId() { + return this.eventId; + } + + @NotNull + @Override + public Long getSequenceId() { + return this.sequenceId; + } + + @Override + public boolean isAfter(@NotNull CalculatorEventData that) { + return this.eventId > that.getEventId(); + } + + @Override + public boolean isSameSequence(@NotNull CalculatorEventData that) { + return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId.equals(that.getSequenceId()); + } + + @Override + public boolean isAfterSequence(@NotNull CalculatorEventData that) { + return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId > that.getSequenceId(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CalculatorEventDataImpl)) return false; + + CalculatorEventDataImpl that = (CalculatorEventDataImpl) o; + + if (eventId != that.eventId) return false; + if (!sequenceId.equals(that.sequenceId)) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (eventId ^ (eventId >>> 32)); + result = 31 * result + (sequenceId.hashCode()); + return result; + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java index d157afc3..0822abeb 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java @@ -1,83 +1,90 @@ -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 CalculatorEditorViewState - manual_calculation_requested, - - // @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, - - /* - ********************************************************************** - * - * EDITOR - * - ********************************************************************** - */ - - // @NotNull org.solovyev.android.calculator.CalculatorEditorChangeEventData - editor_state_changed, - - // @NotNull CalculatorDisplayChangeEventData - display_state_changed, - - /* - ********************************************************************** - * - * ENGINE - * - ********************************************************************** - */ - - engine_preferences_changed; - - public boolean isOfType(@NotNull CalculatorEventType... types) { - for (CalculatorEventType type : types) { - if ( this == type ) { - return true; - } - } - - return false; - } - -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 16:40 + */ +public enum CalculatorEventType { + + /* + ********************************************************************** + * + * CALCULATION + * org.solovyev.android.calculator.CalculatorEvaluationEventData + * + ********************************************************************** + */ + + + // @NotNull CalculatorEditorViewState + manual_calculation_requested, + + // @NotNull org.solovyev.android.calculator.CalculatorInput + calculation_started, + + // @NotNull org.solovyev.android.calculator.CalculatorOutput + calculation_result, + + calculation_cancelled, + + // @NotNull org.solovyev.android.calculator.CalculatorFailure + calculation_failed, + + calculation_finished, + + /* + ********************************************************************** + * + * CONVERSION + * CalculatorConversionEventData + * + ********************************************************************** + */ + conversion_started, + + // @NotNull String conversion result + conversion_result, + + // @NotNull ConversionFailure + conversion_failed, + + conversion_finished, + + /* + ********************************************************************** + * + * EDITOR + * + ********************************************************************** + */ + + // @NotNull org.solovyev.android.calculator.CalculatorEditorChangeEventData + editor_state_changed, + + // @NotNull CalculatorDisplayChangeEventData + display_state_changed, + + /* + ********************************************************************** + * + * ENGINE + * + ********************************************************************** + */ + + engine_preferences_changed; + + public boolean isOfType(@NotNull CalculatorEventType... types) { + for (CalculatorEventType type : types) { + if ( this == type ) { + return true; + } + } + + return false; + } + +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java index bba408d4..fadd3a33 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java @@ -1,405 +1,433 @@ -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.history.CalculatorHistory; -import org.solovyev.android.calculator.history.CalculatorHistoryState; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.text.TextProcessor; -import org.solovyev.common.history.HistoryAction; -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, CalculatorEventListener { - - @NotNull - private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer(); - - @NotNull - private final AtomicLong counter = new AtomicLong(CalculatorUtils.FIRST_ID); - - @NotNull - private final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); - - @NotNull - private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10); - - public CalculatorImpl() { - this.addCalculatorEventListener(this); - } - - @NotNull - public static String doConversion(@NotNull UnitConverter converter, - @Nullable String from, - @NotNull UnitType fromUnitType, - @NotNull UnitType 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 nextEventDataId() { - 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 - * - ********************************************************************** - */ - - @Override - public void evaluate() { - final CalculatorEditorViewState viewState = getEditor().getViewState(); - fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); - this.evaluate(JsclOperation.numeric, viewState.getText()); - } - - @Override - public void evaluate(@NotNull Long sequenceId) { - final CalculatorEditorViewState viewState = getEditor().getViewState(); - fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId); - this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId); - } - - @Override - public void simplify() { - final CalculatorEditorViewState viewState = getEditor().getViewState(); - fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); - this.evaluate(JsclOperation.simplify, viewState.getText()); - } - - @NotNull - @Override - public CalculatorEventDataId evaluate(@NotNull final JsclOperation operation, - @NotNull final String expression) { - - final CalculatorEventDataId eventDataId = nextEventDataId(); - - threadPoolExecutor.execute(new Runnable() { - @Override - public void run() { - CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null); - } - }); - - return eventDataId; - } - - @NotNull - @Override - public CalculatorEventDataId evaluate(@NotNull final JsclOperation operation, @NotNull final String expression, @NotNull Long sequenceId) { - final CalculatorEventDataId eventDataId = nextEventDataId(sequenceId); - - threadPoolExecutor.execute(new Runnable() { - @Override - public void run() { - CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null); - } - }); - - return eventDataId; - } - - @NotNull - @Override - public CalculatorEventDataId convert(@NotNull final Generic generic, - @NotNull final NumeralBase to) { - final CalculatorEventDataId eventDataId = nextEventDataId(); - - threadPoolExecutor.execute(new Runnable() { - @Override - public void run() { - final Long sequenceId = eventDataId.getSequenceId(); - - fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_started, null); - - final NumeralBase from = CalculatorLocatorImpl.getInstance().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 - @Override - public CalculatorEventDataId fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data) { - final CalculatorEventDataId eventDataId = nextEventDataId(); - - threadPoolExecutor.execute(new Runnable() { - @Override - public void run() { - fireCalculatorEvent(CalculatorEventDataImpl.newInstance(eventDataId), calculatorEventType, data); - } - }); - - return eventDataId; - } - - @NotNull - @Override - public CalculatorEventDataId fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data, @NotNull Long sequenceId) { - final CalculatorEventDataId eventDataId = nextEventDataId(sequenceId); - - threadPoolExecutor.execute(new Runnable() { - @Override - public void run() { - fireCalculatorEvent(CalculatorEventDataImpl.newInstance(eventDataId), calculatorEventType, data); - } - }); - - return eventDataId; - } - - @Override - public void init() { - CalculatorLocatorImpl.getInstance().getEngine().init(); - CalculatorLocatorImpl.getInstance().getHistory().load(); - } - - @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) { - - PreparedExpression preparedExpression = null; - - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation)); - - try { - - expression = expression.trim(); - - if (StringUtils.isEmpty(expression)) { - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, CalculatorOutputImpl.newEmptyOutput(operation)); - } else { - preparedExpression = preprocessor.process(expression); - - final String jsclExpression = preparedExpression.toString(); - - try { - - final Generic result = operation.evaluateGeneric(jsclExpression, CalculatorLocatorImpl.getInstance().getEngine().getMathEngine()); - - // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) - result.toString(); - - final CalculatorOutput data = CalculatorOutputImpl.newOutput(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 sequenceId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr, - @Nullable PreparedExpression preparedExpression, - @NotNull CalculatorParseException parseException) { - - if (operation == JsclOperation.numeric - && preparedExpression != null - && preparedExpression.isExistsUndefinedVar()) { - - evaluate(sequenceId, JsclOperation.simplify, expression, mr); - } else { - - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), 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 calculatorEvents) { - calculatorEventContainer.fireCalculatorEvents(calculatorEvents); - } - - @Override - public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { - - switch (calculatorEventType) { - case editor_state_changed: - final CalculatorEditorChangeEventData changeEventData = (CalculatorEditorChangeEventData) data; - - final String newText = changeEventData.getNewState().getText(); - final String oldText = changeEventData.getOldState().getText(); - - if (!newText.equals(oldText)) { - evaluate(JsclOperation.numeric, changeEventData.getNewState().getText(), calculatorEventData.getSequenceId()); - } - break; - case engine_preferences_changed: - evaluate(calculatorEventData.getSequenceId()); - break; - } - } - - @Override - public void doHistoryAction(@NotNull HistoryAction historyAction) { - final CalculatorHistory history = CalculatorLocatorImpl.getInstance().getHistory(); - if (history.isActionAvailable(historyAction)) { - final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState()); - if (newState != null) { - setCurrentHistoryState(newState); - } - } - } - - @Override - public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { - editorHistoryState.setValuesFromHistory(getEditor(), getDisplay()); - } - - @NotNull - private CalculatorEditor getEditor() { - return CalculatorLocatorImpl.getInstance().getEditor(); - } - - @NotNull - @Override - public CalculatorHistoryState getCurrentHistoryState() { - return CalculatorHistoryState.newInstance(getEditor(), getDisplay()); - } - - @NotNull - private CalculatorDisplay getDisplay() { - return CalculatorLocatorImpl.getInstance().getDisplay(); - } - - public static final class ConversionException extends Exception { - private ConversionException() { - } - - private ConversionException(Throwable throwable) { - super(throwable); - } - } -} +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.history.CalculatorHistory; +import org.solovyev.android.calculator.history.CalculatorHistoryState; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.android.calculator.units.CalculatorNumeralBase; +import org.solovyev.common.history.HistoryAction; +import org.solovyev.common.msg.MessageRegistry; +import org.solovyev.common.msg.MessageType; +import org.solovyev.common.text.StringUtils; +import org.solovyev.math.units.*; + +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, CalculatorEventListener { + + @NotNull + private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer(); + + @NotNull + private final AtomicLong counter = new AtomicLong(CalculatorUtils.FIRST_ID); + + @NotNull + private final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); + + @NotNull + private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10); + + public CalculatorImpl() { + this.addCalculatorEventListener(this); + } + + @NotNull + private CalculatorEventData nextEventData() { + long eventId = counter.incrementAndGet(); + return CalculatorEventDataImpl.newInstance(eventId, eventId); + } + + @NotNull + private CalculatorEventData nextEventData(@NotNull Long sequenceId) { + long eventId = counter.incrementAndGet(); + return CalculatorEventDataImpl.newInstance(eventId, sequenceId); + } + + /* + ********************************************************************** + * + * CALCULATION + * + ********************************************************************** + */ + + @Override + public void evaluate() { + final CalculatorEditorViewState viewState = getEditor().getViewState(); + fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); + this.evaluate(JsclOperation.numeric, viewState.getText()); + } + + @Override + public void evaluate(@NotNull Long sequenceId) { + final CalculatorEditorViewState viewState = getEditor().getViewState(); + fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId); + this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId); + } + + @Override + public void simplify() { + final CalculatorEditorViewState viewState = getEditor().getViewState(); + fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); + this.evaluate(JsclOperation.simplify, viewState.getText()); + } + + @NotNull + @Override + public CalculatorEventData evaluate(@NotNull final JsclOperation operation, + @NotNull final String expression) { + + final CalculatorEventData eventDataId = nextEventData(); + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null); + } + }); + + return eventDataId; + } + + @NotNull + @Override + public CalculatorEventData evaluate(@NotNull final JsclOperation operation, @NotNull final String expression, @NotNull Long sequenceId) { + final CalculatorEventData eventDataId = nextEventData(sequenceId); + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null); + } + }); + + return eventDataId; + } + + @Override + public void init() { + CalculatorLocatorImpl.getInstance().getEngine().init(); + CalculatorLocatorImpl.getInstance().getHistory().load(); + } + + @NotNull + private CalculatorConversionEventData newConversionEventData(@NotNull Long sequenceId, + @NotNull Generic value, + @NotNull NumeralBase from, + @NotNull NumeralBase to, + @NotNull CalculatorDisplayViewState displayViewState) { + return CalculatorConversionEventDataImpl.newInstance(nextEventData(sequenceId), value, from, to, displayViewState); + } + + private void evaluate(@NotNull Long sequenceId, + @NotNull JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr) { + + PreparedExpression preparedExpression = null; + + fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation)); + + try { + + expression = expression.trim(); + + if (StringUtils.isEmpty(expression)) { + fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, CalculatorOutputImpl.newEmptyOutput(operation)); + } else { + preparedExpression = preprocessor.process(expression); + + final String jsclExpression = preparedExpression.toString(); + + try { + + final Generic result = operation.evaluateGeneric(jsclExpression, CalculatorLocatorImpl.getInstance().getEngine().getMathEngine()); + + // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) + result.toString(); + + final CalculatorOutput data = CalculatorOutputImpl.newOutput(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(nextEventData(calculationId), operation, expression); + } + + private void handleException(@NotNull Long sequenceId, + @NotNull JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr, + @Nullable PreparedExpression preparedExpression, + @NotNull CalculatorParseException parseException) { + + if (operation == JsclOperation.numeric + && preparedExpression != null + && preparedExpression.isExistsUndefinedVar()) { + + evaluate(sequenceId, JsclOperation.simplify, expression, mr); + } else { + + fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), 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)); + } + + /* + ********************************************************************** + * + * CONVERSION + * + ********************************************************************** + */ + + @NotNull + @Override + public CalculatorEventData convert(@NotNull final Generic value, + @NotNull final NumeralBase to) { + final CalculatorEventData eventDataId = nextEventData(); + + final CalculatorDisplayViewState displayViewState = CalculatorLocatorImpl.getInstance().getDisplay().getViewState(); + final NumeralBase from = CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase(); + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + final Long sequenceId = eventDataId.getSequenceId(); + + fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_started, null); + try { + + final String result = doConversion(value, from, to); + + fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_result, result); + + } catch (ConversionException e) { + fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_failed, new ConversionFailureImpl(e)); + } + } + }); + + return eventDataId; + } + + @NotNull + private static String doConversion(@NotNull Generic generic, + @NotNull NumeralBase from, + @NotNull NumeralBase to) throws ConversionException { + final String result; + + 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 + } + } + + result = ConversionUtils.doConversion(CalculatorNumeralBase.getConverter(), fromString, CalculatorNumeralBase.valueOf(from), CalculatorNumeralBase.valueOf(to)); + } else { + result = generic.toString(); + } + + return result; + } + + @Override + public boolean isConversionPossible(@NotNull Generic generic, NumeralBase from, @NotNull NumeralBase to) { + try { + doConversion(generic, from, to); + return true; + } catch (ConversionException e) { + return false; + } + } + + /* + ********************************************************************** + * + * 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 calculatorEvents) { + calculatorEventContainer.fireCalculatorEvents(calculatorEvents); + } + + @NotNull + @Override + public CalculatorEventData fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data) { + final CalculatorEventData eventData = nextEventData(); + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + fireCalculatorEvent(eventData, calculatorEventType, data); + } + }); + + return eventData; + } + + @NotNull + @Override + public CalculatorEventData fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data, @NotNull Long sequenceId) { + final CalculatorEventData eventData = nextEventData(sequenceId); + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + fireCalculatorEvent(eventData, calculatorEventType, data); + } + }); + + return eventData; + } + + /* + ********************************************************************** + * + * EVENTS HANDLER + * + ********************************************************************** + */ + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + + switch (calculatorEventType) { + case editor_state_changed: + final CalculatorEditorChangeEventData changeEventData = (CalculatorEditorChangeEventData) data; + + final String newText = changeEventData.getNewState().getText(); + final String oldText = changeEventData.getOldState().getText(); + + if (!newText.equals(oldText)) { + evaluate(JsclOperation.numeric, changeEventData.getNewState().getText(), calculatorEventData.getSequenceId()); + } + break; + case engine_preferences_changed: + evaluate(calculatorEventData.getSequenceId()); + break; + } + } + + /* + ********************************************************************** + * + * HISTORY + * + ********************************************************************** + */ + + @Override + public void doHistoryAction(@NotNull HistoryAction historyAction) { + final CalculatorHistory history = CalculatorLocatorImpl.getInstance().getHistory(); + if (history.isActionAvailable(historyAction)) { + final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState()); + if (newState != null) { + setCurrentHistoryState(newState); + } + } + } + + @Override + public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { + editorHistoryState.setValuesFromHistory(getEditor(), getDisplay()); + } + + @NotNull + @Override + public CalculatorHistoryState getCurrentHistoryState() { + return CalculatorHistoryState.newInstance(getEditor(), getDisplay()); + } + + /* + ********************************************************************** + * + * OTHER + * + ********************************************************************** + */ + + @NotNull + private CalculatorEditor getEditor() { + return CalculatorLocatorImpl.getInstance().getEditor(); + } + + @NotNull + private CalculatorDisplay getDisplay() { + return CalculatorLocatorImpl.getInstance().getDisplay(); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorUtils.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorUtils.java index 85e874cf..39ae520b 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorUtils.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorUtils.java @@ -1,22 +1,22 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: serso - * Date: 9/22/12 - * Time: 7:13 PM - */ -public final class CalculatorUtils { - - static final long FIRST_ID = 0; - - private CalculatorUtils() { - throw new AssertionError(); - } - - @NotNull - public static CalculatorEventDataId createFirstEventDataId() { - return CalculatorEventDataIdImpl.newInstance(FIRST_ID, FIRST_ID); - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; + +/** + * User: serso + * Date: 9/22/12 + * Time: 7:13 PM + */ +public final class CalculatorUtils { + + static final long FIRST_ID = 0; + + private CalculatorUtils() { + throw new AssertionError(); + } + + @NotNull + public static CalculatorEventData createFirstEventDataId() { + return CalculatorEventDataImpl.newInstance(FIRST_ID, FIRST_ID); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ConversionFailure.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ConversionFailure.java new file mode 100644 index 00000000..973dbfe7 --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ConversionFailure.java @@ -0,0 +1,14 @@ +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; + +/** + * User: Solovyev_S + * Date: 24.09.12 + * Time: 16:12 + */ +public interface ConversionFailure { + + @NotNull + Exception getException(); +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ConversionFailureImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ConversionFailureImpl.java new file mode 100644 index 00000000..633f55a6 --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ConversionFailureImpl.java @@ -0,0 +1,24 @@ +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; + +/** + * User: Solovyev_S + * Date: 24.09.12 + * Time: 16:12 + */ +public class ConversionFailureImpl implements ConversionFailure { + + @NotNull + private Exception exception; + + public ConversionFailureImpl(@NotNull Exception exception) { + this.exception = exception; + } + + @NotNull + @Override + public Exception getException() { + return this.exception; + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java index 8975d7fc..85d2ff8d 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java @@ -1,216 +1,216 @@ -package org.solovyev.android.calculator.history; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.*; -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; - -import static org.solovyev.android.calculator.CalculatorEventType.display_state_changed; -import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed; -import static org.solovyev.android.calculator.CalculatorEventType.manual_calculation_requested; - -/** - * 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 history = new SimpleHistoryHelper(); - - @NotNull - private final List savedHistory = new ArrayList(); - - @NotNull - private volatile CalculatorEventDataId lastEventDataId = CalculatorUtils.createFirstEventDataId(); - - @Nullable - private volatile CalculatorEditorViewState lastEditorViewState; - - public CalculatorHistoryImpl(@NotNull Calculator calculator) { - calculator.addCalculatorEventListener(this); - } - - @Override - public boolean isEmpty() { - synchronized (history) { - return this.history.isEmpty(); - } - } - - @Override - public CalculatorHistoryState getLastHistoryState() { - synchronized (history) { - return this.history.getLastHistoryState(); - } - } - - @Override - public boolean isUndoAvailable() { - synchronized (history) { - return history.isUndoAvailable(); - } - } - - @Override - public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { - synchronized (history) { - return history.undo(currentState); - } - } - - @Override - public boolean isRedoAvailable() { - return history.isRedoAvailable(); - } - - @Override - public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { - synchronized (history) { - return history.redo(currentState); - } - } - - @Override - public boolean isActionAvailable(@NotNull HistoryAction historyAction) { - synchronized (history) { - return history.isActionAvailable(historyAction); - } - } - - @Override - public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { - synchronized (history) { - return history.doAction(historyAction, currentState); - } - } - - @Override - public void addState(@Nullable CalculatorHistoryState currentState) { - synchronized (history) { - history.addState(currentState); - } - } - - @NotNull - @Override - public List getStates() { - synchronized (history) { - return history.getStates(); - } - } - - @Override - public void clear() { - synchronized (history) { - this.history.clear(); - } - } - - @Override - @NotNull - public List getSavedHistory() { - return Collections.unmodifiableList(savedHistory); - } - - @Override - @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 load() { - // todo serso: create saved/loader class - } - - @Override - public void save() { - // todo serso: create saved/loader class - } - - @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); - } - - @Override - public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, - @NotNull CalculatorEventType calculatorEventType, - @Nullable Object data) { - if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) { - - if (calculatorEventData.isAfter(this.lastEventDataId)) { - final boolean sameSequence = calculatorEventData.isSameSequence(this.lastEventDataId); - - if (sameSequence || calculatorEventData.isAfterSequence(this.lastEventDataId)) { - this.lastEventDataId = calculatorEventData; - - switch (calculatorEventType) { - case manual_calculation_requested: - lastEditorViewState = (CalculatorEditorViewState) data; - break; - case editor_state_changed: - final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data; - lastEditorViewState = editorChangeData.getNewState(); - break; - case display_state_changed: - if (sameSequence) { - if (lastEditorViewState != null) { - final CalculatorEditorViewState editorViewState = lastEditorViewState; - final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data; - final CalculatorDisplayViewState displayViewState = displayChangeData.getNewState(); - addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState)); - } - } else { - lastEditorViewState = null; - } - break; - } - } - } - } - } -} +package org.solovyev.android.calculator.history; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.*; +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; + +import static org.solovyev.android.calculator.CalculatorEventType.display_state_changed; +import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed; +import static org.solovyev.android.calculator.CalculatorEventType.manual_calculation_requested; + +/** + * 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 history = new SimpleHistoryHelper(); + + @NotNull + private final List savedHistory = new ArrayList(); + + @NotNull + private volatile CalculatorEventData lastEventDataId = CalculatorUtils.createFirstEventDataId(); + + @Nullable + private volatile CalculatorEditorViewState lastEditorViewState; + + public CalculatorHistoryImpl(@NotNull Calculator calculator) { + calculator.addCalculatorEventListener(this); + } + + @Override + public boolean isEmpty() { + synchronized (history) { + return this.history.isEmpty(); + } + } + + @Override + public CalculatorHistoryState getLastHistoryState() { + synchronized (history) { + return this.history.getLastHistoryState(); + } + } + + @Override + public boolean isUndoAvailable() { + synchronized (history) { + return history.isUndoAvailable(); + } + } + + @Override + public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { + synchronized (history) { + return history.undo(currentState); + } + } + + @Override + public boolean isRedoAvailable() { + return history.isRedoAvailable(); + } + + @Override + public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { + synchronized (history) { + return history.redo(currentState); + } + } + + @Override + public boolean isActionAvailable(@NotNull HistoryAction historyAction) { + synchronized (history) { + return history.isActionAvailable(historyAction); + } + } + + @Override + public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { + synchronized (history) { + return history.doAction(historyAction, currentState); + } + } + + @Override + public void addState(@Nullable CalculatorHistoryState currentState) { + synchronized (history) { + history.addState(currentState); + } + } + + @NotNull + @Override + public List getStates() { + synchronized (history) { + return history.getStates(); + } + } + + @Override + public void clear() { + synchronized (history) { + this.history.clear(); + } + } + + @Override + @NotNull + public List getSavedHistory() { + return Collections.unmodifiableList(savedHistory); + } + + @Override + @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 load() { + // todo serso: create saved/loader class + } + + @Override + public void save() { + // todo serso: create saved/loader class + } + + @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); + } + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, + @NotNull CalculatorEventType calculatorEventType, + @Nullable Object data) { + if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) { + + if (calculatorEventData.isAfter(this.lastEventDataId)) { + final boolean sameSequence = calculatorEventData.isSameSequence(this.lastEventDataId); + + if (sameSequence || calculatorEventData.isAfterSequence(this.lastEventDataId)) { + this.lastEventDataId = calculatorEventData; + + switch (calculatorEventType) { + case manual_calculation_requested: + lastEditorViewState = (CalculatorEditorViewState) data; + break; + case editor_state_changed: + final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data; + lastEditorViewState = editorChangeData.getNewState(); + break; + case display_state_changed: + if (sameSequence) { + if (lastEditorViewState != null) { + final CalculatorEditorViewState editorViewState = lastEditorViewState; + final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data; + final CalculatorDisplayViewState displayViewState = displayChangeData.getNewState(); + addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState)); + } + } else { + lastEditorViewState = null; + } + break; + } + } + } + } + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/units/CalculatorNumeralBase.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/units/CalculatorNumeralBase.java new file mode 100644 index 00000000..e4993a7f --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/units/CalculatorNumeralBase.java @@ -0,0 +1,99 @@ +package org.solovyev.android.calculator.units; + +import jscl.NumeralBase; +import org.jetbrains.annotations.NotNull; +import org.solovyev.math.units.Unit; +import org.solovyev.math.units.UnitConverter; +import org.solovyev.math.units.UnitImpl; +import org.solovyev.math.units.UnitType; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * User: Solovyev_S + * Date: 24.09.12 + * Time: 16:05 + */ +public enum CalculatorNumeralBase implements UnitType { + + + bin(NumeralBase.bin), + + oct(NumeralBase.oct), + + dec(NumeralBase.dec), + + hex(NumeralBase.hex); + + @NotNull + private final NumeralBase numeralBase; + + private CalculatorNumeralBase(@NotNull NumeralBase numeralBase) { + this.numeralBase = numeralBase; + } + + @NotNull + public NumeralBase getNumeralBase() { + return numeralBase; + } + + @NotNull + private static final CalculatorNumeralBase.Converter converter = new CalculatorNumeralBase.Converter(); + + @NotNull + public static CalculatorNumeralBase.Converter getConverter() { + return converter; + } + + @NotNull + @Override + public Class getUnitValueClass() { + return String.class; + } + + @NotNull + public Unit createUnit(@NotNull String value) { + return UnitImpl.newInstance(value, this); + } + + public static class Converter implements UnitConverter { + + private Converter() { + } + + @Override + public boolean isSupported(@NotNull UnitType from, @NotNull UnitType to) { + return CalculatorNumeralBase.class.isAssignableFrom(from.getClass()) && CalculatorNumeralBase.class.isAssignableFrom(to.getClass()); + } + + @NotNull + @Override + public Unit convert(@NotNull Unit from, @NotNull UnitType toType) { + if (!isSupported(from.getUnitType(), toType)) { + throw new IllegalArgumentException("Types are not supported!"); + } + + final CalculatorNumeralBase fromTypeAndroid = (CalculatorNumeralBase) from.getUnitType(); + final NumeralBase fromNumeralBase = fromTypeAndroid.numeralBase; + final NumeralBase toNumeralBase = ((CalculatorNumeralBase) toType).numeralBase; + final String fromValue = (String) from.getValue(); + + final BigInteger decBigInteger = fromNumeralBase.toBigInteger(fromValue); + return UnitImpl.newInstance(toNumeralBase.toString(decBigInteger), toType); + } + } + + @NotNull + public static CalculatorNumeralBase valueOf(@NotNull NumeralBase nb) { + for (CalculatorNumeralBase calculatorNumeralBase : values()) { + if (calculatorNumeralBase.numeralBase == nb) { + return calculatorNumeralBase; + } + } + + throw new IllegalArgumentException(nb + " is not supported numeral base!"); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/math/units/ConversionException.java b/calculatorpp-core/src/main/java/org/solovyev/math/units/ConversionException.java new file mode 100644 index 00000000..5384ee2a --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/math/units/ConversionException.java @@ -0,0 +1,15 @@ +package org.solovyev.math.units; + +/** +* User: Solovyev_S +* Date: 24.09.12 +* Time: 16:01 +*/ +public final class ConversionException extends Exception { + public ConversionException() { + } + + public ConversionException(Throwable throwable) { + super(throwable); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/math/units/ConversionUtils.java b/calculatorpp-core/src/main/java/org/solovyev/math/units/ConversionUtils.java new file mode 100644 index 00000000..db0896c1 --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/math/units/ConversionUtils.java @@ -0,0 +1,38 @@ +package org.solovyev.math.units; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.common.text.StringUtils; + +/** + * User: Solovyev_S + * Date: 24.09.12 + * Time: 16:01 + */ +public class ConversionUtils { + @NotNull + public static String doConversion(@NotNull UnitConverter converter, + @Nullable String from, + @NotNull UnitType fromUnitType, + @NotNull UnitType 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; + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculator.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculator.java index 24f582e5..dc44f00e 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculator.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculator.java @@ -1,131 +1,136 @@ -package org.solovyev.android.calculator; - -import android.app.Activity; -import android.content.SharedPreferences; -import jscl.NumeralBase; -import jscl.math.Generic; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.history.CalculatorHistoryState; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.common.history.HistoryAction; - -import java.util.List; - -/** - * User: serso - * Date: 9/22/12 - * Time: 5:42 PM - */ -public class AndroidCalculator implements Calculator { - - @NotNull - private final Calculator calculator = new CalculatorImpl(); - - public void init(@NotNull final Activity activity, @NotNull SharedPreferences preferences) { - final AndroidCalculatorEditorView editorView = (AndroidCalculatorEditorView) activity.findViewById(R.id.calculatorEditor); - editorView.init(preferences); - preferences.registerOnSharedPreferenceChangeListener(editorView); - CalculatorLocatorImpl.getInstance().getEditor().setView(editorView); - - final AndroidCalculatorDisplayView displayView = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay); - displayView.setOnClickListener(new CalculatorDisplayOnClickListener(activity)); - CalculatorLocatorImpl.getInstance().getDisplay().setView(displayView); - } - - - /* - ********************************************************************** - * - * DELEGATED TO CALCULATOR - * - ********************************************************************** - */ - - @Override - @NotNull - public CalculatorEventDataId evaluate(@NotNull JsclOperation operation, @NotNull String expression) { - return calculator.evaluate(operation, expression); - } - - @Override - @NotNull - public CalculatorEventDataId evaluate(@NotNull JsclOperation operation, @NotNull String expression, @NotNull Long sequenceId) { - return calculator.evaluate(operation, expression, sequenceId); - } - - @Override - @NotNull - public CalculatorEventDataId convert(@NotNull Generic generic, @NotNull NumeralBase to) { - return calculator.convert(generic, to); - } - - @Override - @NotNull - public CalculatorEventDataId fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { - return calculator.fireCalculatorEvent(calculatorEventType, data); - } - - @Override - @NotNull - public CalculatorEventDataId fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data, @NotNull Long sequenceId) { - return calculator.fireCalculatorEvent(calculatorEventType, data, sequenceId); - } - - @Override - public void init() { - this.calculator.init(); - } - - @Override - public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { - calculator.addCalculatorEventListener(calculatorEventListener); - } - - @Override - public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { - calculator.removeCalculatorEventListener(calculatorEventListener); - } - - @Override - public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { - calculator.fireCalculatorEvent(calculatorEventData, calculatorEventType, data); - } - - @Override - public void fireCalculatorEvents(@NotNull List calculatorEvents) { - calculator.fireCalculatorEvents(calculatorEvents); - } - - @Override - public void doHistoryAction(@NotNull HistoryAction historyAction) { - calculator.doHistoryAction(historyAction); - } - - @Override - public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { - calculator.setCurrentHistoryState(editorHistoryState); - } - - @Override - @NotNull - public CalculatorHistoryState getCurrentHistoryState() { - return calculator.getCurrentHistoryState(); - } - - @Override - public void evaluate() { - calculator.evaluate(); - } - - @Override - public void evaluate(@NotNull Long sequenceId) { - calculator.evaluate(sequenceId); - } - - @Override - public void simplify() { - calculator.simplify(); - } - -} +package org.solovyev.android.calculator; + +import android.app.Activity; +import android.content.SharedPreferences; +import jscl.NumeralBase; +import jscl.math.Generic; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.history.CalculatorHistoryState; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.common.history.HistoryAction; + +import java.util.List; + +/** + * User: serso + * Date: 9/22/12 + * Time: 5:42 PM + */ +public class AndroidCalculator implements Calculator { + + @NotNull + private final Calculator calculator = new CalculatorImpl(); + + public void init(@NotNull final Activity activity, @NotNull SharedPreferences preferences) { + final AndroidCalculatorEditorView editorView = (AndroidCalculatorEditorView) activity.findViewById(R.id.calculatorEditor); + editorView.init(preferences); + preferences.registerOnSharedPreferenceChangeListener(editorView); + CalculatorLocatorImpl.getInstance().getEditor().setView(editorView); + + final AndroidCalculatorDisplayView displayView = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay); + displayView.setOnClickListener(new CalculatorDisplayOnClickListener(activity)); + CalculatorLocatorImpl.getInstance().getDisplay().setView(displayView); + } + + + /* + ********************************************************************** + * + * DELEGATED TO CALCULATOR + * + ********************************************************************** + */ + + @Override + @NotNull + public CalculatorEventData evaluate(@NotNull JsclOperation operation, @NotNull String expression) { + return calculator.evaluate(operation, expression); + } + + @Override + @NotNull + public CalculatorEventData evaluate(@NotNull JsclOperation operation, @NotNull String expression, @NotNull Long sequenceId) { + return calculator.evaluate(operation, expression, sequenceId); + } + + @Override + public boolean isConversionPossible(@NotNull Generic generic, @NotNull NumeralBase from, @NotNull NumeralBase to) { + return calculator.isConversionPossible(generic, from, to); + } + + @Override + @NotNull + public CalculatorEventData convert(@NotNull Generic generic, @NotNull NumeralBase to) { + return calculator.convert(generic, to); + } + + @Override + @NotNull + public CalculatorEventData fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + return calculator.fireCalculatorEvent(calculatorEventType, data); + } + + @Override + @NotNull + public CalculatorEventData fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data, @NotNull Long sequenceId) { + return calculator.fireCalculatorEvent(calculatorEventType, data, sequenceId); + } + + @Override + public void init() { + this.calculator.init(); + } + + @Override + public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { + calculator.addCalculatorEventListener(calculatorEventListener); + } + + @Override + public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { + calculator.removeCalculatorEventListener(calculatorEventListener); + } + + @Override + public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + calculator.fireCalculatorEvent(calculatorEventData, calculatorEventType, data); + } + + @Override + public void fireCalculatorEvents(@NotNull List calculatorEvents) { + calculator.fireCalculatorEvents(calculatorEvents); + } + + @Override + public void doHistoryAction(@NotNull HistoryAction historyAction) { + calculator.doHistoryAction(historyAction); + } + + @Override + public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { + calculator.setCurrentHistoryState(editorHistoryState); + } + + @Override + @NotNull + public CalculatorHistoryState getCurrentHistoryState() { + return calculator.getCurrentHistoryState(); + } + + @Override + public void evaluate() { + calculator.evaluate(); + } + + @Override + public void evaluate(@NotNull Long sequenceId) { + calculator.evaluate(sequenceId); + } + + @Override + public void simplify() { + calculator.simplify(); + } + +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidNumeralBase.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidNumeralBase.java index 4abf638d..cdd5e4a6 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidNumeralBase.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidNumeralBase.java @@ -3,14 +3,10 @@ package org.solovyev.android.calculator; import android.app.Activity; import jscl.NumeralBase; import org.jetbrains.annotations.NotNull; -import org.solovyev.math.units.Unit; -import org.solovyev.math.units.UnitConverter; -import org.solovyev.math.units.UnitImpl; -import org.solovyev.math.units.UnitType; +import org.solovyev.android.calculator.units.CalculatorNumeralBase; import org.solovyev.android.view.drag.DirectionDragButton; import org.solovyev.android.view.drag.DragDirection; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -20,9 +16,9 @@ import java.util.List; * Date: 4/21/12 * Time: 8:00 PM */ -public enum AndroidNumeralBase implements UnitType { +public enum AndroidNumeralBase { - bin(NumeralBase.bin) { + bin(CalculatorNumeralBase.bin) { @NotNull @Override public List getButtonIds() { @@ -30,7 +26,7 @@ public enum AndroidNumeralBase implements UnitType { } }, - oct(NumeralBase.oct) { + oct(CalculatorNumeralBase.oct) { @NotNull @Override public List getButtonIds() { @@ -40,7 +36,7 @@ public enum AndroidNumeralBase implements UnitType { } }, - dec(NumeralBase.dec) { + dec(CalculatorNumeralBase.dec) { @NotNull @Override public List getButtonIds() { @@ -50,7 +46,7 @@ public enum AndroidNumeralBase implements UnitType { } }, - hex(NumeralBase.hex) { + hex(CalculatorNumeralBase.hex) { @NotNull private List specialHexButtonIds = Arrays.asList(R.id.oneDigitButton, R.id.twoDigitButton, R.id.threeDigitButton, R.id.fourDigitButton, R.id.fiveDigitButton, R.id.sixDigitButton); @@ -72,15 +68,10 @@ public enum AndroidNumeralBase implements UnitType { }; @NotNull - private final NumeralBase numeralBase; + private final CalculatorNumeralBase calculatorNumeralBase; - private AndroidNumeralBase(@NotNull NumeralBase numeralBase) { - this.numeralBase = numeralBase; - } - - @NotNull - public Unit createUnit(@NotNull String value) { - return UnitImpl.newInstance(value, this); + private AndroidNumeralBase(@NotNull CalculatorNumeralBase calculatorNumeralBase) { + this.calculatorNumeralBase = calculatorNumeralBase; } @NotNull @@ -101,54 +92,13 @@ public enum AndroidNumeralBase implements UnitType { @NotNull public NumeralBase getNumeralBase() { - return numeralBase; - } - - @NotNull - @Override - public Class getUnitValueClass() { - return String.class; - } - - @NotNull - private static final Converter converter = new Converter(); - - @NotNull - public static Converter getConverter() { - return converter; - } - - public static class Converter implements UnitConverter { - - private Converter() { - } - - @Override - public boolean isSupported(@NotNull UnitType from, @NotNull UnitType to) { - return AndroidNumeralBase.class.isAssignableFrom(from.getClass()) && AndroidNumeralBase.class.isAssignableFrom(to.getClass()); - } - - @NotNull - @Override - public Unit convert(@NotNull Unit from, @NotNull UnitType toType) { - if (!isSupported(from.getUnitType(), toType)) { - throw new IllegalArgumentException("Types are not supported!"); - } - - final AndroidNumeralBase fromTypeAndroid = (AndroidNumeralBase) from.getUnitType(); - final NumeralBase fromNumeralBase = fromTypeAndroid.numeralBase; - final NumeralBase toNumeralBase = ((AndroidNumeralBase) toType).numeralBase; - final String fromValue = (String) from.getValue(); - - final BigInteger decBigInteger = fromNumeralBase.toBigInteger(fromValue); - return UnitImpl.newInstance(toNumeralBase.toString(decBigInteger), (AndroidNumeralBase) toType); - } + return calculatorNumeralBase.getNumeralBase(); } @NotNull public static AndroidNumeralBase valueOf(@NotNull NumeralBase nb) { for (AndroidNumeralBase androidNumeralBase : values()) { - if (androidNumeralBase.numeralBase == nb) { + if (androidNumeralBase.calculatorNumeralBase.getNumeralBase() == nb) { return androidNumeralBase; } } diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/ConversionMenuItem.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/ConversionMenuItem.java index 25dc9ef8..097d5a20 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/ConversionMenuItem.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/ConversionMenuItem.java @@ -1,57 +1,52 @@ -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.menu.AMenuItem; - -/** - * User: serso - * Date: 9/21/12 - * Time: 12:11 AM - */ -enum ConversionMenuItem implements AMenuItem { - - 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()) { - convert(generic); - - // conversion possible => return true - result = true; - } - } - - return result; - } - - @Override - public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { - final NumeralBase fromNumeralBase = CalculatorLocatorImpl.getInstance().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); - } -} +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.menu.AMenuItem; + +/** + * User: serso + * Date: 9/21/12 + * Time: 12:11 AM + */ +enum ConversionMenuItem implements AMenuItem { + + 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()) { + // conversion possible => return true + final NumeralBase fromNumeralBase = CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase(); + if (fromNumeralBase != toNumeralBase) { + result = CalculatorLocatorImpl.getInstance().getCalculator().isConversionPossible(generic, fromNumeralBase, this.toNumeralBase); + } + } + } + + return result; + } + + @Override + public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { + final Generic result = data.getResult(); + + if (result != null) { + CalculatorLocatorImpl.getInstance().getCalculator().convert(result, this.toNumeralBase); + } + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/NumeralBaseConverterDialog.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/NumeralBaseConverterDialog.java index 883e458a..b94e930e 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/NumeralBaseConverterDialog.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/NumeralBaseConverterDialog.java @@ -1,94 +1,95 @@ -package org.solovyev.android.calculator.view; - -import android.app.AlertDialog; -import android.content.Context; -import android.view.View; -import android.view.WindowManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.*; -import org.solovyev.math.units.Unit; -import org.solovyev.math.units.UnitImpl; -import org.solovyev.common.MutableObject; -import org.solovyev.common.text.StringUtils; - -import java.util.Arrays; - -/** - * User: serso - * Date: 4/22/12 - * Time: 12:20 AM - */ -public class NumeralBaseConverterDialog { - - @Nullable - private String initialFromValue; - - public NumeralBaseConverterDialog(String initialFromValue) { - this.initialFromValue = initialFromValue; - } - - public void show(@NotNull Context context) { - final UnitConverterViewBuilder b = new UnitConverterViewBuilder(); - b.setFromUnitTypes(Arrays.asList(AndroidNumeralBase.values())); - b.setToUnitTypes(Arrays.asList(AndroidNumeralBase.values())); - - if (!StringUtils.isEmpty(initialFromValue)) { - String value = initialFromValue; - try { - value = ToJsclTextProcessor.getInstance().process(value).getExpression(); - b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))); - } catch (CalculatorParseException e) { - b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))); - } - } else { - b.setFromValue(UnitImpl.newInstance("", AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))); - } - - b.setConverter(AndroidNumeralBase.getConverter()); - - final MutableObject alertDialogHolder = new MutableObject(); - b.setOkButtonOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - final AlertDialog alertDialog = alertDialogHolder.getObject(); - if (alertDialog != null) { - alertDialog.dismiss(); - } - } - }); - - b.setCustomButtonData(new UnitConverterViewBuilder.CustomButtonData(context.getString(R.string.c_use_short), new UnitConverterViewBuilder.CustomButtonOnClickListener() { - @Override - public void onClick(@NotNull Unit fromUnits, @NotNull Unit toUnits) { - String toUnitsValue = toUnits.getValue(); - - if (!toUnits.getUnitType().equals(AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))) { - toUnitsValue = ((AndroidNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue; - } - - CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(toUnitsValue); - final AlertDialog alertDialog = alertDialogHolder.getObject(); - if (alertDialog != null) { - alertDialog.dismiss(); - } - } - })); - - final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context); - alertBuilder.setView(b.build(context)); - alertBuilder.setTitle(R.string.c_conversion_tool); - - final AlertDialog alertDialog = alertBuilder.create(); - - final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); - lp.copyFrom(alertDialog.getWindow().getAttributes()); - - lp.width = WindowManager.LayoutParams.FILL_PARENT; - lp.height = WindowManager.LayoutParams.WRAP_CONTENT; - - alertDialogHolder.setObject(alertDialog); - alertDialog.show(); - alertDialog.getWindow().setAttributes(lp); - } -} +package org.solovyev.android.calculator.view; + +import android.app.AlertDialog; +import android.content.Context; +import android.view.View; +import android.view.WindowManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.*; +import org.solovyev.android.calculator.units.CalculatorNumeralBase; +import org.solovyev.math.units.Unit; +import org.solovyev.math.units.UnitImpl; +import org.solovyev.common.MutableObject; +import org.solovyev.common.text.StringUtils; + +import java.util.Arrays; + +/** + * User: serso + * Date: 4/22/12 + * Time: 12:20 AM + */ +public class NumeralBaseConverterDialog { + + @Nullable + private String initialFromValue; + + public NumeralBaseConverterDialog(String initialFromValue) { + this.initialFromValue = initialFromValue; + } + + public void show(@NotNull Context context) { + final UnitConverterViewBuilder b = new UnitConverterViewBuilder(); + b.setFromUnitTypes(Arrays.asList(CalculatorNumeralBase.values())); + b.setToUnitTypes(Arrays.asList(CalculatorNumeralBase.values())); + + if (!StringUtils.isEmpty(initialFromValue)) { + String value = initialFromValue; + try { + value = ToJsclTextProcessor.getInstance().process(value).getExpression(); + b.setFromValue(UnitImpl.newInstance(value, CalculatorNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))); + } catch (CalculatorParseException e) { + b.setFromValue(UnitImpl.newInstance(value, CalculatorNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))); + } + } else { + b.setFromValue(UnitImpl.newInstance("", CalculatorNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))); + } + + b.setConverter(CalculatorNumeralBase.getConverter()); + + final MutableObject alertDialogHolder = new MutableObject(); + b.setOkButtonOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final AlertDialog alertDialog = alertDialogHolder.getObject(); + if (alertDialog != null) { + alertDialog.dismiss(); + } + } + }); + + b.setCustomButtonData(new UnitConverterViewBuilder.CustomButtonData(context.getString(R.string.c_use_short), new UnitConverterViewBuilder.CustomButtonOnClickListener() { + @Override + public void onClick(@NotNull Unit fromUnits, @NotNull Unit toUnits) { + String toUnitsValue = toUnits.getValue(); + + if (!toUnits.getUnitType().equals(AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))) { + toUnitsValue = ((AndroidNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue; + } + + CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(toUnitsValue); + final AlertDialog alertDialog = alertDialogHolder.getObject(); + if (alertDialog != null) { + alertDialog.dismiss(); + } + } + })); + + final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context); + alertBuilder.setView(b.build(context)); + alertBuilder.setTitle(R.string.c_conversion_tool); + + final AlertDialog alertDialog = alertBuilder.create(); + + final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); + lp.copyFrom(alertDialog.getWindow().getAttributes()); + + lp.width = WindowManager.LayoutParams.FILL_PARENT; + lp.height = WindowManager.LayoutParams.WRAP_CONTENT; + + alertDialogHolder.setObject(alertDialog); + alertDialog.show(); + alertDialog.getWindow().setAttributes(lp); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java index 41603705..b9d73de1 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java @@ -1,224 +1,221 @@ -package org.solovyev.android.calculator.view; - -import android.app.Activity; -import android.content.Context; -import android.text.ClipboardManager; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.view.ViewGroup; -import android.widget.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.CalculatorImpl; -import org.solovyev.math.units.Unit; -import org.solovyev.math.units.UnitConverter; -import org.solovyev.math.units.UnitImpl; -import org.solovyev.math.units.UnitType; -import org.solovyev.android.calculator.R; -import org.solovyev.android.view.ViewBuilder; -import org.solovyev.android.view.ViewFromLayoutBuilder; - -import java.util.Collections; -import java.util.List; - -/** - * User: serso - * Date: 4/20/12 - * Time: 4:50 PM - */ -public class UnitConverterViewBuilder implements ViewBuilder { - - @NotNull - private List> fromUnitTypes = Collections.emptyList(); - - @NotNull - private List> toUnitTypes = Collections.emptyList(); - - @Nullable - private Unit fromValue; - - @NotNull - private UnitConverter converter = UnitConverter.Dummy.getInstance(); - - @Nullable - private View.OnClickListener okButtonOnClickListener; - - @Nullable - private CustomButtonData customButtonData; - - public void setFromUnitTypes(@NotNull List> fromUnitTypes) { - this.fromUnitTypes = fromUnitTypes; - } - - public void setToUnitTypes(@NotNull List> toUnitTypes) { - this.toUnitTypes = toUnitTypes; - } - - public void setFromValue(@Nullable Unit fromValue) { - this.fromValue = fromValue; - } - - public void setConverter(@NotNull UnitConverter converter) { - this.converter = converter; - } - - public void setOkButtonOnClickListener(@Nullable View.OnClickListener okButtonOnClickListener) { - this.okButtonOnClickListener = okButtonOnClickListener; - } - - public void setCustomButtonData(@Nullable CustomButtonData customButtonData) { - this.customButtonData = customButtonData; - } - - @NotNull - @Override - public View build(@NotNull final Context context) { - final View main = ViewFromLayoutBuilder.newInstance(R.layout.unit_converter).build(context); - - final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from); - final EditText fromEditText = (EditText) main.findViewById(R.id.units_from); - fromEditText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - doConversion(main, context, UnitConverterViewBuilder.this.converter); - } - }); - - fillSpinner(main, context, R.id.unit_types_from, fromUnitTypes); - fillSpinner(main, context, R.id.unit_types_to, toUnitTypes); - - if (fromValue != null) { - fromEditText.setText(fromValue.getValue()); - - int i = fromUnitTypes.indexOf(fromValue.getUnitType()); - if ( i >= 0 ) { - fromSpinner.setSelection(i); - } - } - - final Button copyButton = (Button) main.findViewById(R.id.unit_converter_copy_button); - copyButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - final EditText toEditText = (EditText) main.findViewById(R.id.units_to); - - final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); - clipboard.setText(toEditText.getText().toString()); - Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); - } - }); - - final Button okButton = (Button) main.findViewById(R.id.unit_converter_ok_button); - if ( okButtonOnClickListener == null ) { - ((ViewGroup) okButton.getParent()).removeView(okButton); - } else { - okButton.setOnClickListener(this.okButtonOnClickListener); - } - - final Button customButton = (Button) main.findViewById(R.id.unit_converter_custom_button); - if ( customButtonData == null ) { - ((ViewGroup) customButton.getParent()).removeView(customButton); - } else { - customButton.setText(customButtonData.text); - customButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - customButtonData.clickListener.onClick(getFromUnit(main), getToUnit(main)); - } - }); - } - - - - return main; - } - - private void fillSpinner(@NotNull final View main, - @NotNull final Context context, - final int spinnerId, - @NotNull List> unitTypes) { - final Spinner spinner = (Spinner) main.findViewById(spinnerId); - - final ArrayAdapter> adapter = new ArrayAdapter>(context, android.R.layout.simple_spinner_item); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - for (UnitType fromUnitType : unitTypes) { - adapter.add(fromUnitType); - } - spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - doConversion(main, context, UnitConverterViewBuilder.this.converter); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - spinner.setAdapter(adapter); - } - - private static void doConversion(@NotNull View main, @NotNull Context context, @NotNull UnitConverter converter) { - final EditText fromEditText = (EditText) main.findViewById(R.id.units_from); - - final EditText toEditText = (EditText) main.findViewById(R.id.units_to); - - final String from = fromEditText.getText().toString(); - try { - toEditText.setText(CalculatorImpl.doConversion(converter, from, getFromUnitType(main), getToUnitType(main))); - } catch (CalculatorImpl.ConversionException e) { - toEditText.setText(context.getString(R.string.c_error)); - } - } - - @NotNull - private static Unit getToUnit(@NotNull View main) { - final EditText toUnits = (EditText) main.findViewById(R.id.units_to); - return UnitImpl.newInstance(toUnits.getText().toString(), getToUnitType(main)); - } - - @NotNull - private static UnitType getToUnitType(@NotNull View main) { - final Spinner toSpinner = (Spinner) main.findViewById(R.id.unit_types_to); - return (UnitType) toSpinner.getSelectedItem(); - } - - @NotNull - private static Unit getFromUnit(@NotNull View main) { - final EditText fromUnits = (EditText) main.findViewById(R.id.units_from); - return UnitImpl.newInstance(fromUnits.getText().toString(), getFromUnitType(main)); - } - - @NotNull - private static UnitType getFromUnitType(@NotNull View main) { - final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from); - return (UnitType) fromSpinner.getSelectedItem(); - } - - public static class CustomButtonData { - - @NotNull - private String text; - - @NotNull - private CustomButtonOnClickListener clickListener; - - - public CustomButtonData(@NotNull String text, @NotNull CustomButtonOnClickListener clickListener) { - this.text = text; - this.clickListener = clickListener; - } - } - - public static interface CustomButtonOnClickListener { - void onClick(@NotNull Unit fromUnits, @NotNull Unit toUnits); - } -} +package org.solovyev.android.calculator.view; + +import android.app.Activity; +import android.content.Context; +import android.text.ClipboardManager; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.view.ViewGroup; +import android.widget.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.CalculatorImpl; +import org.solovyev.math.units.*; +import org.solovyev.android.calculator.R; +import org.solovyev.android.view.ViewBuilder; +import org.solovyev.android.view.ViewFromLayoutBuilder; + +import java.util.Collections; +import java.util.List; + +/** + * User: serso + * Date: 4/20/12 + * Time: 4:50 PM + */ +public class UnitConverterViewBuilder implements ViewBuilder { + + @NotNull + private List> fromUnitTypes = Collections.emptyList(); + + @NotNull + private List> toUnitTypes = Collections.emptyList(); + + @Nullable + private Unit fromValue; + + @NotNull + private UnitConverter converter = UnitConverter.Dummy.getInstance(); + + @Nullable + private View.OnClickListener okButtonOnClickListener; + + @Nullable + private CustomButtonData customButtonData; + + public void setFromUnitTypes(@NotNull List> fromUnitTypes) { + this.fromUnitTypes = fromUnitTypes; + } + + public void setToUnitTypes(@NotNull List> toUnitTypes) { + this.toUnitTypes = toUnitTypes; + } + + public void setFromValue(@Nullable Unit fromValue) { + this.fromValue = fromValue; + } + + public void setConverter(@NotNull UnitConverter converter) { + this.converter = converter; + } + + public void setOkButtonOnClickListener(@Nullable View.OnClickListener okButtonOnClickListener) { + this.okButtonOnClickListener = okButtonOnClickListener; + } + + public void setCustomButtonData(@Nullable CustomButtonData customButtonData) { + this.customButtonData = customButtonData; + } + + @NotNull + @Override + public View build(@NotNull final Context context) { + final View main = ViewFromLayoutBuilder.newInstance(R.layout.unit_converter).build(context); + + final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from); + final EditText fromEditText = (EditText) main.findViewById(R.id.units_from); + fromEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + doConversion(main, context, UnitConverterViewBuilder.this.converter); + } + }); + + fillSpinner(main, context, R.id.unit_types_from, fromUnitTypes); + fillSpinner(main, context, R.id.unit_types_to, toUnitTypes); + + if (fromValue != null) { + fromEditText.setText(fromValue.getValue()); + + int i = fromUnitTypes.indexOf(fromValue.getUnitType()); + if ( i >= 0 ) { + fromSpinner.setSelection(i); + } + } + + final Button copyButton = (Button) main.findViewById(R.id.unit_converter_copy_button); + copyButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final EditText toEditText = (EditText) main.findViewById(R.id.units_to); + + final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); + clipboard.setText(toEditText.getText().toString()); + Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); + } + }); + + final Button okButton = (Button) main.findViewById(R.id.unit_converter_ok_button); + if ( okButtonOnClickListener == null ) { + ((ViewGroup) okButton.getParent()).removeView(okButton); + } else { + okButton.setOnClickListener(this.okButtonOnClickListener); + } + + final Button customButton = (Button) main.findViewById(R.id.unit_converter_custom_button); + if ( customButtonData == null ) { + ((ViewGroup) customButton.getParent()).removeView(customButton); + } else { + customButton.setText(customButtonData.text); + customButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + customButtonData.clickListener.onClick(getFromUnit(main), getToUnit(main)); + } + }); + } + + + + return main; + } + + private void fillSpinner(@NotNull final View main, + @NotNull final Context context, + final int spinnerId, + @NotNull List> unitTypes) { + final Spinner spinner = (Spinner) main.findViewById(spinnerId); + + final ArrayAdapter> adapter = new ArrayAdapter>(context, android.R.layout.simple_spinner_item); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + for (UnitType fromUnitType : unitTypes) { + adapter.add(fromUnitType); + } + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + doConversion(main, context, UnitConverterViewBuilder.this.converter); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + spinner.setAdapter(adapter); + } + + private static void doConversion(@NotNull View main, @NotNull Context context, @NotNull UnitConverter converter) { + final EditText fromEditText = (EditText) main.findViewById(R.id.units_from); + + final EditText toEditText = (EditText) main.findViewById(R.id.units_to); + + final String from = fromEditText.getText().toString(); + try { + toEditText.setText(ConversionUtils.doConversion(converter, from, getFromUnitType(main), getToUnitType(main))); + } catch (ConversionException e) { + toEditText.setText(context.getString(R.string.c_error)); + } + } + + @NotNull + private static Unit getToUnit(@NotNull View main) { + final EditText toUnits = (EditText) main.findViewById(R.id.units_to); + return UnitImpl.newInstance(toUnits.getText().toString(), getToUnitType(main)); + } + + @NotNull + private static UnitType getToUnitType(@NotNull View main) { + final Spinner toSpinner = (Spinner) main.findViewById(R.id.unit_types_to); + return (UnitType) toSpinner.getSelectedItem(); + } + + @NotNull + private static Unit getFromUnit(@NotNull View main) { + final EditText fromUnits = (EditText) main.findViewById(R.id.units_from); + return UnitImpl.newInstance(fromUnits.getText().toString(), getFromUnitType(main)); + } + + @NotNull + private static UnitType getFromUnitType(@NotNull View main) { + final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from); + return (UnitType) fromSpinner.getSelectedItem(); + } + + public static class CustomButtonData { + + @NotNull + private String text; + + @NotNull + private CustomButtonOnClickListener clickListener; + + + public CustomButtonData(@NotNull String text, @NotNull CustomButtonOnClickListener clickListener) { + this.text = text; + this.clickListener = clickListener; + } + } + + public static interface CustomButtonOnClickListener { + void onClick(@NotNull Unit fromUnits, @NotNull Unit toUnits); + } +} diff --git a/calculatorpp/src/test/java/org/solovyev/android/AndroidNumeralBaseTest.java b/calculatorpp/src/test/java/org/solovyev/android/AndroidNumeralBaseTest.java index 5ad54751..56c4bbc9 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/AndroidNumeralBaseTest.java +++ b/calculatorpp/src/test/java/org/solovyev/android/AndroidNumeralBaseTest.java @@ -3,7 +3,7 @@ package org.solovyev.android; import junit.framework.Assert; import org.jetbrains.annotations.NotNull; import org.junit.Test; -import org.solovyev.android.calculator.AndroidNumeralBase; +import org.solovyev.android.calculator.units.CalculatorNumeralBase; import org.solovyev.math.units.Unit; import org.solovyev.math.units.UnitConverter; @@ -18,32 +18,32 @@ import java.util.Random; public class AndroidNumeralBaseTest { @NotNull - private final UnitConverter c = AndroidNumeralBase.getConverter(); + private final UnitConverter c = CalculatorNumeralBase.getConverter(); @Test public void testIsSupported() throws Exception { - Assert.assertTrue(c.isSupported(AndroidNumeralBase.bin, AndroidNumeralBase.dec)); + Assert.assertTrue(c.isSupported(CalculatorNumeralBase.bin, CalculatorNumeralBase.dec)); } @Test public void testConvertFromDec() throws Exception { - Assert.assertEquals("101", c.convert(AndroidNumeralBase.dec.createUnit("5"), 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("1111100111", c.convert(AndroidNumeralBase.dec.createUnit("999"), AndroidNumeralBase.bin).getValue()); + Assert.assertEquals("101", c.convert(CalculatorNumeralBase.dec.createUnit("5"), CalculatorNumeralBase.bin).getValue()); + Assert.assertEquals("1", c.convert(CalculatorNumeralBase.dec.createUnit("1"), CalculatorNumeralBase.bin).getValue()); + Assert.assertEquals("0", c.convert(CalculatorNumeralBase.dec.createUnit("0"), CalculatorNumeralBase.bin).getValue()); + Assert.assertEquals("1111100111", c.convert(CalculatorNumeralBase.dec.createUnit("999"), CalculatorNumeralBase.bin).getValue()); - Assert.assertEquals("A23", c.convert(AndroidNumeralBase.dec.createUnit("2595"), AndroidNumeralBase.hex).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("0", c.convert(AndroidNumeralBase.dec.createUnit("0"), AndroidNumeralBase.hex).getValue()); - Assert.assertEquals("3E7", c.convert(AndroidNumeralBase.dec.createUnit("999"), AndroidNumeralBase.hex).getValue()); + Assert.assertEquals("A23", c.convert(CalculatorNumeralBase.dec.createUnit("2595"), CalculatorNumeralBase.hex).getValue()); + Assert.assertEquals("AEE", c.convert(CalculatorNumeralBase.dec.createUnit("2798"), CalculatorNumeralBase.hex).getValue()); + Assert.assertEquals("15", c.convert(CalculatorNumeralBase.dec.createUnit("21"), CalculatorNumeralBase.hex).getValue()); + Assert.assertEquals("0", c.convert(CalculatorNumeralBase.dec.createUnit("0"), CalculatorNumeralBase.hex).getValue()); + Assert.assertEquals("3E7", c.convert(CalculatorNumeralBase.dec.createUnit("999"), CalculatorNumeralBase.hex).getValue()); - Assert.assertEquals("76", c.convert(AndroidNumeralBase.dec.createUnit("62"), AndroidNumeralBase.oct).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("0", c.convert(AndroidNumeralBase.dec.createUnit("0"), AndroidNumeralBase.oct).getValue()); - Assert.assertEquals("10445", c.convert(AndroidNumeralBase.dec.createUnit("4389"), AndroidNumeralBase.oct).getValue()); + Assert.assertEquals("76", c.convert(CalculatorNumeralBase.dec.createUnit("62"), CalculatorNumeralBase.oct).getValue()); + Assert.assertEquals("12", c.convert(CalculatorNumeralBase.dec.createUnit("10"), CalculatorNumeralBase.oct).getValue()); + Assert.assertEquals("15", c.convert(CalculatorNumeralBase.dec.createUnit("13"), CalculatorNumeralBase.oct).getValue()); + Assert.assertEquals("0", c.convert(CalculatorNumeralBase.dec.createUnit("0"), CalculatorNumeralBase.oct).getValue()); + Assert.assertEquals("10445", c.convert(CalculatorNumeralBase.dec.createUnit("4389"), CalculatorNumeralBase.oct).getValue()); } @Test @@ -51,20 +51,20 @@ public class AndroidNumeralBaseTest { final Random random = new Random(new Date().getTime()); for (int i = 0; i < 100000; i++) { final String value = String.valueOf(random.nextInt()); - Assert.assertEquals(value, convertChain(value, AndroidNumeralBase.dec, AndroidNumeralBase.oct, AndroidNumeralBase.oct, AndroidNumeralBase.bin, 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)); + Assert.assertEquals(value, convertChain(value, CalculatorNumeralBase.dec, CalculatorNumeralBase.oct, CalculatorNumeralBase.oct, CalculatorNumeralBase.bin, CalculatorNumeralBase.dec)); + Assert.assertEquals(value, convertChain(value, CalculatorNumeralBase.dec, CalculatorNumeralBase.bin, CalculatorNumeralBase.hex, CalculatorNumeralBase.dec, CalculatorNumeralBase.dec)); + Assert.assertEquals(value, convertChain(value, CalculatorNumeralBase.dec, CalculatorNumeralBase.dec, CalculatorNumeralBase.hex, CalculatorNumeralBase.oct, CalculatorNumeralBase.dec)); + Assert.assertEquals(value, convertChain(value, CalculatorNumeralBase.dec, CalculatorNumeralBase.hex, CalculatorNumeralBase.bin, CalculatorNumeralBase.oct, CalculatorNumeralBase.dec)); } } @NotNull - private String convertChain(@NotNull String value, @NotNull AndroidNumeralBase baseAndroid, @NotNull AndroidNumeralBase... typeAndroids) { + private String convertChain(@NotNull String value, @NotNull CalculatorNumeralBase baseAndroid, @NotNull CalculatorNumeralBase... typeAndroids) { Unit unit = baseAndroid.createUnit(value); - for (AndroidNumeralBase typeAndroid : typeAndroids) { - unit = AndroidNumeralBase.getConverter().convert(unit, typeAndroid); + for (CalculatorNumeralBase typeAndroid : typeAndroids) { + unit = CalculatorNumeralBase.getConverter().convert(unit, typeAndroid); } return unit.getValue();