core moved to android-app
This commit is contained in:
@@ -62,7 +62,6 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile project(':core')
|
||||
compile 'org.solovyev:common-core:1.0.7'
|
||||
compile 'org.solovyev:common-text:1.0.7'
|
||||
compile 'org.solovyev:common-security:1.0.7'
|
||||
@@ -91,6 +90,22 @@ dependencies {
|
||||
|
||||
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
|
||||
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
|
||||
compile group: 'org.solovyev', name: 'common-text', version: '1.0.7'
|
||||
compile group: 'org.solovyev', name: 'common-listeners', version: '1.0.7'
|
||||
compile(group: 'com.google.guava', name: 'guava', version: '11.0.2') {
|
||||
exclude(module: 'jsr305')
|
||||
}
|
||||
compile(group: 'org.solovyev', name: 'jscl', version: '1.0.11') {
|
||||
exclude(module: 'xercesImpl')
|
||||
}
|
||||
compile(group: 'org.simpleframework', name: 'simple-xml', version: '2.6.1') {
|
||||
exclude(module: 'stax-api')
|
||||
exclude(module: 'xpp3')
|
||||
}
|
||||
compile group: 'commons-cli', name: 'commons-cli', version: '1.2'
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile group: 'net.sf.opencsv', name: 'opencsv', version: '2.0'
|
||||
testCompile group: 'org.mockito', name: 'mockito-core', version: '1.9.0'
|
||||
}
|
||||
|
||||
task androidJavadocs(type: Javadoc) {
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.JBuilder;
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
import org.solovyev.common.math.MathRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/30/11
|
||||
* Time: 1:03 AM
|
||||
*/
|
||||
public abstract class AbstractCalculatorMathRegistry<T extends MathEntity, P extends MathPersistenceEntity> implements CalculatorMathRegistry<T> {
|
||||
|
||||
@Nonnull
|
||||
private final MathRegistry<T> mathRegistry;
|
||||
|
||||
@Nonnull
|
||||
private final String prefix;
|
||||
|
||||
@Nonnull
|
||||
private final MathEntityDao<P> mathEntityDao;
|
||||
|
||||
protected AbstractCalculatorMathRegistry(@Nonnull MathRegistry<T> mathRegistry,
|
||||
@Nonnull String prefix,
|
||||
@Nonnull MathEntityDao<P> mathEntityDao) {
|
||||
this.mathRegistry = mathRegistry;
|
||||
this.prefix = prefix;
|
||||
this.mathEntityDao = mathEntityDao;
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
protected abstract Map<String, String> getSubstitutes();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDescription(@Nonnull String mathEntityName) {
|
||||
final String stringName;
|
||||
|
||||
final Map<String, String> substitutes = getSubstitutes();
|
||||
final String substitute = substitutes.get(mathEntityName);
|
||||
if (substitute == null) {
|
||||
stringName = prefix + mathEntityName;
|
||||
} else {
|
||||
stringName = prefix + substitute;
|
||||
}
|
||||
|
||||
return mathEntityDao.getDescription(stringName);
|
||||
}
|
||||
|
||||
public synchronized void load() {
|
||||
final MathEntityPersistenceContainer<P> persistenceContainer = mathEntityDao.load();
|
||||
|
||||
final List<P> notCreatedEntities = new ArrayList<P>();
|
||||
|
||||
if (persistenceContainer != null) {
|
||||
for (P entity : persistenceContainer.getEntities()) {
|
||||
if (!contains(entity.getName())) {
|
||||
try {
|
||||
final JBuilder<? extends T> builder = createBuilder(entity);
|
||||
add(builder);
|
||||
} catch (RuntimeException e) {
|
||||
Locator.getInstance().getLogger().error(null, e.getLocalizedMessage(), e);
|
||||
notCreatedEntities.add(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (!notCreatedEntities.isEmpty()) {
|
||||
final StringBuilder errorMessage = new StringBuilder(notCreatedEntities.size() * 100);
|
||||
for (P notCreatedEntity : notCreatedEntities) {
|
||||
errorMessage.append(notCreatedEntity).append("\n\n");
|
||||
}
|
||||
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_message_dialog, MessageDialogData.newInstance(CalculatorMessages.newErrorMessage(CalculatorMessages.msg_007, errorMessage.toString()), null));
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// just in case
|
||||
Locator.getInstance().getLogger().error(null, e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected abstract JBuilder<? extends T> createBuilder(@Nonnull P entity);
|
||||
|
||||
@Override
|
||||
public synchronized void save() {
|
||||
final MathEntityPersistenceContainer<P> container = createPersistenceContainer();
|
||||
|
||||
for (T entity : this.getEntities()) {
|
||||
if (!entity.isSystem()) {
|
||||
final P persistenceEntity = transform(entity);
|
||||
if (persistenceEntity != null) {
|
||||
container.getEntities().add(persistenceEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.mathEntityDao.save(container);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract P transform(@Nonnull T entity);
|
||||
|
||||
@Nonnull
|
||||
protected abstract MathEntityPersistenceContainer<P> createPersistenceContainer();
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<T> getEntities() {
|
||||
return mathRegistry.getEntities();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<T> getSystemEntities() {
|
||||
return mathRegistry.getSystemEntities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T add(@Nonnull JBuilder<? extends T> JBuilder) {
|
||||
return mathRegistry.add(JBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(@Nonnull T var) {
|
||||
mathRegistry.remove(var);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return mathRegistry.getNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@Nonnull String name) {
|
||||
return mathRegistry.contains(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(@Nonnull String name) {
|
||||
return mathRegistry.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getById(@Nonnull Integer id) {
|
||||
return mathRegistry.getById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class AbstractFixableError implements FixableError {
|
||||
|
||||
@Nullable
|
||||
private String fixCaption;
|
||||
|
||||
protected AbstractFixableError() {
|
||||
}
|
||||
|
||||
protected AbstractFixableError(@Nullable String fixCaption) {
|
||||
this.fixCaption = fixCaption;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CharSequence getFixCaption() {
|
||||
return fixCaption;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.NumeralBase;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/15/11
|
||||
* Time: 9:01 PM
|
||||
*/
|
||||
public abstract class AbstractNumberBuilder {
|
||||
|
||||
@Nonnull
|
||||
protected final CalculatorEngine engine;
|
||||
|
||||
@Nullable
|
||||
protected StringBuilder numberBuilder = null;
|
||||
|
||||
@Nullable
|
||||
protected NumeralBase nb;
|
||||
|
||||
protected AbstractNumberBuilder(@Nonnull CalculatorEngine engine) {
|
||||
this.engine = engine;
|
||||
this.nb = engine.getNumeralBase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method determines if we can continue to process current number
|
||||
*
|
||||
* @param mathTypeResult current math type result
|
||||
* @return true if we can continue of processing of current number, if false - new number should be constructed
|
||||
*/
|
||||
protected boolean canContinue(@Nonnull MathType.Result mathTypeResult) {
|
||||
boolean result = mathTypeResult.getMathType().getGroupType() == MathType.MathGroupType.number &&
|
||||
!spaceBefore(mathTypeResult) &&
|
||||
numeralBaseCheck(mathTypeResult) &&
|
||||
numeralBaseInTheStart(mathTypeResult.getMathType()) || isSignAfterE(mathTypeResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean spaceBefore(@Nonnull MathType.Result mathTypeResult) {
|
||||
return numberBuilder == null && Strings.isEmpty(mathTypeResult.getMatch().trim());
|
||||
}
|
||||
|
||||
private boolean numeralBaseInTheStart(@Nonnull MathType mathType) {
|
||||
return mathType != MathType.numeral_base || numberBuilder == null;
|
||||
}
|
||||
|
||||
private boolean numeralBaseCheck(@Nonnull MathType.Result mathType) {
|
||||
return mathType.getMathType() != MathType.digit || getNumeralBase().getAcceptableCharacters().contains(mathType.getMatch().charAt(0));
|
||||
}
|
||||
|
||||
private boolean isSignAfterE(@Nonnull MathType.Result mathTypeResult) {
|
||||
if (!isHexMode()) {
|
||||
final String match = mathTypeResult.getMatch();
|
||||
if ("−".equals(match) || "-".equals(match) || "+".equals(match)) {
|
||||
final StringBuilder localNb = numberBuilder;
|
||||
if (localNb != null && localNb.length() > 0) {
|
||||
if (localNb.charAt(localNb.length() - 1) == MathType.POWER_10) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isHexMode() {
|
||||
return nb == NumeralBase.hex || (nb == null && engine.getNumeralBase() == NumeralBase.hex);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected NumeralBase getNumeralBase() {
|
||||
return nb == null ? engine.getNumeralBase() : nb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryState;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.common.history.HistoryControl;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 16:38
|
||||
*/
|
||||
public interface Calculator extends CalculatorEventContainer, HistoryControl<CalculatorHistoryState> {
|
||||
|
||||
void init();
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CALCULATIONS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
void evaluate();
|
||||
|
||||
void evaluate(@Nonnull Long sequenceId);
|
||||
|
||||
void simplify();
|
||||
|
||||
@Nonnull
|
||||
CalculatorEventData evaluate(@Nonnull JsclOperation operation,
|
||||
@Nonnull String expression);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEventData evaluate(@Nonnull JsclOperation operation,
|
||||
@Nonnull String expression,
|
||||
@Nonnull Long sequenceId);
|
||||
|
||||
boolean isCalculateOnFly();
|
||||
|
||||
void setCalculateOnFly(boolean calculateOnFly);
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONVERSION
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
boolean isConversionPossible(@Nonnull Generic generic, @Nonnull NumeralBase from, @Nonnull NumeralBase to);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEventData convert(@Nonnull Generic generic, @Nonnull NumeralBase to);
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* EVENTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
@Nonnull
|
||||
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data, @Nonnull Object source);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data, @Nonnull Long sequenceId);
|
||||
|
||||
@Nonnull
|
||||
PreparedExpression prepareExpression(@Nonnull String expression) throws CalculatorParseException;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 1:34 PM
|
||||
*/
|
||||
public interface CalculatorClipboard {
|
||||
|
||||
@Nullable
|
||||
String getText();
|
||||
|
||||
void setText(@Nonnull CharSequence text);
|
||||
|
||||
void setText(@Nonnull String text);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 24.09.12
|
||||
* Time: 16:45
|
||||
*/
|
||||
public interface CalculatorConversionEventData extends CalculatorEventData {
|
||||
|
||||
// display state on the moment of conversion
|
||||
@Nonnull
|
||||
CalculatorDisplayViewState getDisplayState();
|
||||
|
||||
@Nonnull
|
||||
NumeralBase getFromNumeralBase();
|
||||
|
||||
@Nonnull
|
||||
NumeralBase getToNumeralBase();
|
||||
|
||||
@Nonnull
|
||||
Generic getValue();
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 24.09.12
|
||||
* Time: 16:48
|
||||
*/
|
||||
public class CalculatorConversionEventDataImpl implements CalculatorConversionEventData {
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEventData calculatorEventData;
|
||||
|
||||
@Nonnull
|
||||
private NumeralBase fromNumeralBase;
|
||||
|
||||
@Nonnull
|
||||
private NumeralBase toNumeralBase;
|
||||
|
||||
@Nonnull
|
||||
private Generic value;
|
||||
|
||||
@Nonnull
|
||||
private CalculatorDisplayViewState displayState;
|
||||
|
||||
private CalculatorConversionEventDataImpl() {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorConversionEventData newInstance(@Nonnull CalculatorEventData calculatorEventData,
|
||||
@Nonnull Generic value,
|
||||
@Nonnull NumeralBase from,
|
||||
@Nonnull NumeralBase to,
|
||||
@Nonnull 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
|
||||
@Nonnull
|
||||
public Long getSequenceId() {
|
||||
return calculatorEventData.getSequenceId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return calculatorEventData.getSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfter(@Nonnull CalculatorEventData that) {
|
||||
return calculatorEventData.isAfter(that);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
|
||||
return calculatorEventData.isSameSequence(that);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
|
||||
return calculatorEventData.isAfterSequence(that);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorDisplayViewState getDisplayState() {
|
||||
return this.displayState;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public NumeralBase getFromNumeralBase() {
|
||||
return fromNumeralBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public NumeralBase getToNumeralBase() {
|
||||
return toNumeralBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Generic getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/17/11
|
||||
* Time: 9:45 PM
|
||||
*/
|
||||
public interface CalculatorDisplay extends CalculatorEventListener {
|
||||
|
||||
void clearView(@Nonnull CalculatorDisplayView view);
|
||||
|
||||
@Nullable
|
||||
CalculatorDisplayView getView();
|
||||
|
||||
void setView(@Nonnull CalculatorDisplayView view);
|
||||
|
||||
@Nonnull
|
||||
CalculatorDisplayViewState getViewState();
|
||||
|
||||
void setViewState(@Nonnull CalculatorDisplayViewState viewState);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEventData getLastEventData();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/21/12
|
||||
* Time: 9:49 PM
|
||||
*/
|
||||
public interface CalculatorDisplayChangeEventData extends Change<CalculatorDisplayViewState> {
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/21/12
|
||||
* Time: 9:50 PM
|
||||
*/
|
||||
public class CalculatorDisplayChangeEventDataImpl implements CalculatorDisplayChangeEventData {
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorDisplayViewState oldState;
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorDisplayViewState newState;
|
||||
|
||||
public CalculatorDisplayChangeEventDataImpl(@Nonnull CalculatorDisplayViewState oldState, @Nonnull CalculatorDisplayViewState newState) {
|
||||
this.oldState = oldState;
|
||||
this.newState = newState;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorDisplayViewState getOldValue() {
|
||||
return this.oldState;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorDisplayViewState getNewValue() {
|
||||
return this.newState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.calculation_cancelled;
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.calculation_failed;
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.calculation_result;
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.conversion_failed;
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.conversion_result;
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.display_state_changed;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 8:24 PM
|
||||
*/
|
||||
public class CalculatorDisplayImpl implements CalculatorDisplay {
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorEventHolder lastEvent;
|
||||
@Nonnull
|
||||
private final Object viewLock = new Object();
|
||||
@Nonnull
|
||||
private final Calculator calculator;
|
||||
@Nullable
|
||||
private CalculatorDisplayView view;
|
||||
@Nonnull
|
||||
private CalculatorDisplayViewState viewState = CalculatorDisplayViewStateImpl.newDefaultInstance();
|
||||
|
||||
public CalculatorDisplayImpl(@Nonnull Calculator calculator) {
|
||||
this.calculator = calculator;
|
||||
this.lastEvent = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
|
||||
this.calculator.addCalculatorEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView(@Nonnull CalculatorDisplayView view) {
|
||||
synchronized (viewLock) {
|
||||
if (this.view == view) {
|
||||
this.view = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CalculatorDisplayView getView() {
|
||||
return this.view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setView(@Nonnull CalculatorDisplayView view) {
|
||||
synchronized (viewLock) {
|
||||
this.view = view;
|
||||
this.view.setState(viewState);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorDisplayViewState getViewState() {
|
||||
return this.viewState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setViewState(@Nonnull CalculatorDisplayViewState newViewState) {
|
||||
synchronized (viewLock) {
|
||||
final CalculatorDisplayViewState oldViewState = setViewState0(newViewState);
|
||||
|
||||
this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState));
|
||||
}
|
||||
}
|
||||
|
||||
private void setViewStateForSequence(@Nonnull CalculatorDisplayViewState newViewState, @Nonnull 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
|
||||
@Nonnull
|
||||
private CalculatorDisplayViewState setViewState0(@Nonnull CalculatorDisplayViewState newViewState) {
|
||||
final CalculatorDisplayViewState oldViewState = this.viewState;
|
||||
|
||||
this.viewState = newViewState;
|
||||
if (this.view != null) {
|
||||
this.view.setState(newViewState);
|
||||
}
|
||||
return oldViewState;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public CalculatorEventData getLastEventData() {
|
||||
return lastEvent.getLastEventData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
|
||||
@Nonnull CalculatorEventType calculatorEventType,
|
||||
@Nullable Object data) {
|
||||
if (calculatorEventType.isOfType(calculation_result, calculation_failed, calculation_cancelled, conversion_result, conversion_failed)) {
|
||||
|
||||
final CalculatorEventHolder.Result result = lastEvent.apply(calculatorEventData);
|
||||
|
||||
if (result.isNewAfter()) {
|
||||
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(@Nonnull CalculatorConversionEventData calculatorEventData,
|
||||
@Nonnull ConversionFailure data) {
|
||||
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getDisplayState().getOperation(), CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error)), calculatorEventData.getSequenceId());
|
||||
|
||||
}
|
||||
|
||||
private void processCalculationFailed(@Nonnull CalculatorEvaluationEventData calculatorEventData, @Nonnull 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(@Nonnull CalculatorEvaluationEventData calculatorEventData) {
|
||||
final String errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
|
||||
|
||||
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId());
|
||||
}
|
||||
|
||||
private void processCalculationResult(@Nonnull CalculatorEvaluationEventData calculatorEventData, @Nonnull CalculatorOutput data) {
|
||||
final String stringResult = data.getStringResult();
|
||||
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newValidState(calculatorEventData.getOperation(), data.getResult(), stringResult, 0), calculatorEventData.getSequenceId());
|
||||
}
|
||||
|
||||
private void processConversationResult(@Nonnull CalculatorConversionEventData calculatorEventData, @Nonnull 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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 8:25 PM
|
||||
*/
|
||||
public interface CalculatorDisplayView {
|
||||
|
||||
@Nonnull
|
||||
CalculatorDisplayViewState getState();
|
||||
|
||||
void setState(@Nonnull CalculatorDisplayViewState state);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 9:50 PM
|
||||
*/
|
||||
public interface CalculatorDisplayViewState extends Serializable {
|
||||
|
||||
@Nonnull
|
||||
String getText();
|
||||
|
||||
int getSelection();
|
||||
|
||||
@Nullable
|
||||
Generic getResult();
|
||||
|
||||
boolean isValid();
|
||||
|
||||
@Nullable
|
||||
String getErrorMessage();
|
||||
|
||||
@Nonnull
|
||||
JsclOperation getOperation();
|
||||
|
||||
@Nullable
|
||||
String getStringResult();
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 9:50 PM
|
||||
*/
|
||||
public class CalculatorDisplayViewStateImpl implements CalculatorDisplayViewState {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
private JsclOperation operation = JsclOperation.numeric;
|
||||
|
||||
@Nullable
|
||||
private transient Generic result;
|
||||
|
||||
@Nullable
|
||||
private String stringResult = "";
|
||||
|
||||
private boolean valid = true;
|
||||
|
||||
@Nullable
|
||||
private String errorMessage;
|
||||
|
||||
private int selection = 0;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private CalculatorDisplayViewStateImpl() {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorDisplayViewState newDefaultInstance() {
|
||||
return new CalculatorDisplayViewStateImpl();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorDisplayViewState newErrorState(@Nonnull JsclOperation operation,
|
||||
@Nonnull String errorMessage) {
|
||||
final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl();
|
||||
calculatorDisplayState.valid = false;
|
||||
calculatorDisplayState.errorMessage = errorMessage;
|
||||
calculatorDisplayState.operation = operation;
|
||||
return calculatorDisplayState;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorDisplayViewState newValidState(@Nonnull JsclOperation operation,
|
||||
@Nullable Generic result,
|
||||
@Nonnull String stringResult,
|
||||
int selection) {
|
||||
final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl();
|
||||
calculatorDisplayState.valid = true;
|
||||
calculatorDisplayState.result = result;
|
||||
calculatorDisplayState.stringResult = stringResult;
|
||||
calculatorDisplayState.operation = operation;
|
||||
calculatorDisplayState.selection = selection;
|
||||
|
||||
return calculatorDisplayState;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getText() {
|
||||
return Strings.getNotEmpty(isValid() ? stringResult : errorMessage, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelection() {
|
||||
return selection;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Generic getResult() {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return this.valid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getErrorMessage() {
|
||||
return this.errorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getStringResult() {
|
||||
return stringResult;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public JsclOperation getOperation() {
|
||||
return this.operation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.gui.CursorControl;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 21.09.12
|
||||
* Time: 11:47
|
||||
*/
|
||||
public interface CalculatorEditor extends CalculatorEventListener {
|
||||
|
||||
@Nonnull
|
||||
String TAG = CalculatorEditor.class.getSimpleName();
|
||||
|
||||
void setView(@Nonnull CalculatorEditorView view);
|
||||
|
||||
void clearView(@Nonnull CalculatorEditorView view);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditorViewState getViewState();
|
||||
|
||||
void setViewState(@Nonnull CalculatorEditorViewState viewState);
|
||||
|
||||
// updates state of view (view.setState())
|
||||
void updateViewState();
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CURSOR CONTROL
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Method sets the cursor to the beginning
|
||||
*/
|
||||
@Nonnull
|
||||
public CalculatorEditorViewState setCursorOnStart();
|
||||
|
||||
/**
|
||||
* Method sets the cursor to the end
|
||||
*/
|
||||
@Nonnull
|
||||
public CalculatorEditorViewState setCursorOnEnd();
|
||||
|
||||
/**
|
||||
* Method moves cursor to the left of current position
|
||||
*/
|
||||
@Nonnull
|
||||
public CalculatorEditorViewState moveCursorLeft();
|
||||
|
||||
/**
|
||||
* Method moves cursor to the right of current position
|
||||
*/
|
||||
@Nonnull
|
||||
public CalculatorEditorViewState moveCursorRight();
|
||||
|
||||
@Nonnull
|
||||
CursorControl asCursorControl();
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* EDITOR OPERATIONS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
@Nonnull
|
||||
CalculatorEditorViewState erase();
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditorViewState clear();
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditorViewState setText(@Nonnull String text);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditorViewState setText(@Nonnull String text, int selection);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditorViewState insert(@Nonnull String text);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditorViewState insert(@Nonnull String text, int selectionOffset);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditorViewState moveSelection(int offset);
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditorViewState setSelection(int selection);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 21.09.12
|
||||
* Time: 13:46
|
||||
*/
|
||||
public final class CalculatorEditorChangeEventData implements Change<CalculatorEditorViewState> {
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEditorViewState oldState;
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEditorViewState newState;
|
||||
|
||||
private CalculatorEditorChangeEventData(@Nonnull CalculatorEditorViewState oldState,
|
||||
@Nonnull CalculatorEditorViewState newState) {
|
||||
this.oldState = oldState;
|
||||
this.newState = newState;
|
||||
}
|
||||
|
||||
public static CalculatorEditorChangeEventData newChangeEventData(@Nonnull CalculatorEditorViewState oldState,
|
||||
@Nonnull CalculatorEditorViewState newState) {
|
||||
return new CalculatorEditorChangeEventData(oldState, newState);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState getOldValue() {
|
||||
return this.oldState;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState getNewValue() {
|
||||
return this.newState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryState;
|
||||
import org.solovyev.android.calculator.history.EditorHistoryState;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
|
||||
import org.solovyev.common.gui.CursorControl;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static java.lang.Math.min;
|
||||
import static org.solovyev.android.calculator.CalculatorEditorChangeEventData.newChangeEventData;
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed;
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed_light;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 21.09.12
|
||||
* Time: 11:53
|
||||
*/
|
||||
public class CalculatorEditorImpl implements CalculatorEditor {
|
||||
|
||||
@Nonnull
|
||||
private final Object viewLock = new Object();
|
||||
@Nonnull
|
||||
private final Calculator calculator;
|
||||
@Nonnull
|
||||
private final CalculatorEventHolder lastEventHolder;
|
||||
@Nonnull
|
||||
private final CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this);
|
||||
@Nullable
|
||||
private final TextProcessor<TextProcessorEditorResult, String> textProcessor;
|
||||
@Nullable
|
||||
private CalculatorEditorView view;
|
||||
@Nonnull
|
||||
private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance();
|
||||
|
||||
public CalculatorEditorImpl(@Nonnull Calculator calculator, @Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) {
|
||||
this.calculator = calculator;
|
||||
this.textProcessor = textProcessor;
|
||||
this.calculator.addCalculatorEventListener(this);
|
||||
this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
|
||||
}
|
||||
|
||||
public static int correctSelection(int selection, @Nonnull CharSequence text) {
|
||||
return correctSelection(selection, text.length());
|
||||
}
|
||||
|
||||
public static int correctSelection(int selection, int textLength) {
|
||||
int result = Math.max(selection, 0);
|
||||
result = min(result, textLength);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setView(@Nonnull CalculatorEditorView view) {
|
||||
synchronized (viewLock) {
|
||||
this.view = view;
|
||||
this.view.setState(lastViewState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView(@Nonnull CalculatorEditorView view) {
|
||||
synchronized (viewLock) {
|
||||
if (this.view == view) {
|
||||
this.view = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState getViewState() {
|
||||
return lastViewState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setViewState(@Nonnull CalculatorEditorViewState newViewState) {
|
||||
setViewState(newViewState, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateViewState() {
|
||||
setViewState(this.lastViewState, false);
|
||||
}
|
||||
|
||||
private void setViewState(@Nonnull CalculatorEditorViewState newViewState, boolean majorChanges) {
|
||||
if (textProcessor != null) {
|
||||
try {
|
||||
final TextProcessorEditorResult result = textProcessor.process(newViewState.getText());
|
||||
newViewState = CalculatorEditorViewStateImpl.newInstance(result.getCharSequence(), newViewState.getSelection() + result.getOffset());
|
||||
} catch (CalculatorParseException e) {
|
||||
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
synchronized (viewLock) {
|
||||
final CalculatorEditorViewState oldViewState = this.lastViewState;
|
||||
|
||||
this.lastViewState = newViewState;
|
||||
if (this.view != null) {
|
||||
this.view.setState(newViewState);
|
||||
}
|
||||
|
||||
fireStateChangedEvent(majorChanges, oldViewState, newViewState);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* SELECTION
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private void fireStateChangedEvent(boolean majorChanges, @Nonnull CalculatorEditorViewState oldViewState, @Nonnull CalculatorEditorViewState newViewState) {
|
||||
if (!Thread.holdsLock(viewLock)) throw new AssertionError();
|
||||
|
||||
if (majorChanges) {
|
||||
calculator.fireCalculatorEvent(editor_state_changed, newChangeEventData(oldViewState, newViewState));
|
||||
} else {
|
||||
calculator.fireCalculatorEvent(editor_state_changed_light, newChangeEventData(oldViewState, newViewState));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
|
||||
@Nonnull CalculatorEventType calculatorEventType,
|
||||
@Nullable Object data) {
|
||||
final CalculatorEventHolder.Result result = lastEventHolder.apply(calculatorEventData);
|
||||
|
||||
if (result.isNewAfter()) {
|
||||
switch (calculatorEventType) {
|
||||
case use_history_state:
|
||||
final CalculatorHistoryState calculatorHistoryState = (CalculatorHistoryState) data;
|
||||
final EditorHistoryState editorState = calculatorHistoryState.getEditorState();
|
||||
this.setText(Strings.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEditorViewState newSelectionViewState(int newSelection) {
|
||||
if (this.lastViewState.getSelection() != newSelection) {
|
||||
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection);
|
||||
setViewState(result, false);
|
||||
return result;
|
||||
} else {
|
||||
return this.lastViewState;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CalculatorEditorViewState setCursorOnStart() {
|
||||
synchronized (viewLock) {
|
||||
return newSelectionViewState(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CalculatorEditorViewState setCursorOnEnd() {
|
||||
synchronized (viewLock) {
|
||||
return newSelectionViewState(this.lastViewState.getText().length());
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CalculatorEditorViewState moveCursorLeft() {
|
||||
synchronized (viewLock) {
|
||||
if (this.lastViewState.getSelection() > 0) {
|
||||
return newSelectionViewState(this.lastViewState.getSelection() - 1);
|
||||
} else {
|
||||
return this.lastViewState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* EDITOR ACTIONS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
public CalculatorEditorViewState moveCursorRight() {
|
||||
synchronized (viewLock) {
|
||||
if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) {
|
||||
return newSelectionViewState(this.lastViewState.getSelection() + 1);
|
||||
} else {
|
||||
return this.lastViewState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CursorControl asCursorControl() {
|
||||
return cursorControlAdapter;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState erase() {
|
||||
synchronized (viewLock) {
|
||||
int selection = this.lastViewState.getSelection();
|
||||
final String text = this.lastViewState.getText();
|
||||
if (selection > 0 && text.length() > 0 && selection <= text.length()) {
|
||||
final StringBuilder newText = new StringBuilder(text.length() - 1);
|
||||
newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length()));
|
||||
|
||||
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), selection - 1);
|
||||
setViewState(result);
|
||||
return result;
|
||||
} else {
|
||||
return this.lastViewState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState clear() {
|
||||
synchronized (viewLock) {
|
||||
return setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState setText(@Nonnull String text) {
|
||||
synchronized (viewLock) {
|
||||
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, text.length());
|
||||
setViewState(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState setText(@Nonnull String text, int selection) {
|
||||
synchronized (viewLock) {
|
||||
selection = correctSelection(selection, text);
|
||||
|
||||
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, selection);
|
||||
setViewState(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState insert(@Nonnull String text) {
|
||||
synchronized (viewLock) {
|
||||
return insert(text, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState insert(@Nonnull String text, int selectionOffset) {
|
||||
synchronized (viewLock) {
|
||||
final String oldText = lastViewState.getText();
|
||||
final int selection = correctSelection(lastViewState.getSelection(), oldText);
|
||||
|
||||
int newTextLength = text.length() + oldText.length();
|
||||
final StringBuilder newText = new StringBuilder(newTextLength);
|
||||
|
||||
newText.append(oldText.substring(0, selection));
|
||||
newText.append(text);
|
||||
newText.append(oldText.substring(selection));
|
||||
|
||||
int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength);
|
||||
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection);
|
||||
setViewState(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState moveSelection(int offset) {
|
||||
synchronized (viewLock) {
|
||||
int selection = this.lastViewState.getSelection() + offset;
|
||||
|
||||
return setSelection(selection);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditorViewState setSelection(int selection) {
|
||||
synchronized (viewLock) {
|
||||
selection = correctSelection(selection, this.lastViewState.getText());
|
||||
|
||||
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, selection);
|
||||
setViewState(result, false);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CursorControlAdapter implements CursorControl {
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorEditor calculatorEditor;
|
||||
|
||||
private CursorControlAdapter(@Nonnull CalculatorEditor calculatorEditor) {
|
||||
this.calculatorEditor = calculatorEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCursorOnStart() {
|
||||
this.calculatorEditor.setCursorOnStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCursorOnEnd() {
|
||||
this.calculatorEditor.setCursorOnEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveCursorLeft() {
|
||||
this.calculatorEditor.moveCursorLeft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveCursorRight() {
|
||||
this.calculatorEditor.moveCursorRight();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 21.09.12
|
||||
* Time: 11:48
|
||||
*/
|
||||
public interface CalculatorEditorView {
|
||||
|
||||
void setState(@Nonnull CalculatorEditorViewState viewState);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 21.09.12
|
||||
* Time: 11:48
|
||||
*/
|
||||
public interface CalculatorEditorViewState extends Serializable {
|
||||
|
||||
@Nonnull
|
||||
String getText();
|
||||
|
||||
@Nonnull
|
||||
CharSequence getTextAsCharSequence();
|
||||
|
||||
int getSelection();
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 21.09.12
|
||||
* Time: 12:02
|
||||
*/
|
||||
public class CalculatorEditorViewStateImpl implements CalculatorEditorViewState {
|
||||
|
||||
@Nonnull
|
||||
private CharSequence text = "";
|
||||
|
||||
private int selection = 0;
|
||||
|
||||
private CalculatorEditorViewStateImpl() {
|
||||
}
|
||||
|
||||
public CalculatorEditorViewStateImpl(@Nonnull CalculatorEditorViewState viewState) {
|
||||
this.text = viewState.getText();
|
||||
this.selection = viewState.getSelection();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorEditorViewState newDefaultInstance() {
|
||||
return new CalculatorEditorViewStateImpl();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorEditorViewState newSelection(@Nonnull CalculatorEditorViewState viewState, int newSelection) {
|
||||
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl(viewState);
|
||||
|
||||
result.selection = newSelection;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorEditorViewState newInstance(@Nonnull CharSequence text, int selection) {
|
||||
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl();
|
||||
result.text = text;
|
||||
result.selection = selection;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getText() {
|
||||
return this.text.toString();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CharSequence getTextAsCharSequence() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelection() {
|
||||
return this.selection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.text.DecimalFormatSymbols;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.AngleUnit;
|
||||
import jscl.MathEngine;
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IConstant;
|
||||
import jscl.math.operator.Operator;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 12:43
|
||||
*/
|
||||
public interface CalculatorEngine {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* INIT
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
void init();
|
||||
|
||||
void reset();
|
||||
|
||||
void softReset();
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* REGISTRIES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
CalculatorMathRegistry<IConstant> getVarsRegistry();
|
||||
|
||||
@Nonnull
|
||||
CalculatorMathRegistry<Function> getFunctionsRegistry();
|
||||
|
||||
@Nonnull
|
||||
CalculatorMathRegistry<Operator> getOperatorsRegistry();
|
||||
|
||||
@Nonnull
|
||||
CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry();
|
||||
|
||||
@Nonnull
|
||||
CalculatorMathEngine getMathEngine();
|
||||
|
||||
@Deprecated
|
||||
@Nonnull
|
||||
MathEngine getMathEngine0();
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* PREFERENCES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
String getMultiplicationSign();
|
||||
|
||||
void setMultiplicationSign(@Nonnull String multiplicationSign);
|
||||
|
||||
void setUseGroupingSeparator(boolean useGroupingSeparator);
|
||||
|
||||
void setGroupingSeparator(char groupingSeparator);
|
||||
|
||||
void setPrecision(@Nonnull Integer precision);
|
||||
|
||||
void setRoundResult(@Nonnull Boolean round);
|
||||
|
||||
@Nonnull
|
||||
AngleUnit getAngleUnits();
|
||||
|
||||
void setAngleUnits(@Nonnull AngleUnit angleUnits);
|
||||
|
||||
@Nonnull
|
||||
NumeralBase getNumeralBase();
|
||||
|
||||
void setNumeralBase(@Nonnull NumeralBase numeralBase);
|
||||
|
||||
void setScienceNotation(@Nonnull Boolean scienceNotation);
|
||||
|
||||
void setTimeout(@Nonnull Integer timeout);
|
||||
|
||||
void setDecimalGroupSymbols(@Nonnull DecimalFormatSymbols decimalGroupSymbols);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/24/11
|
||||
* Time: 9:55 PM
|
||||
*/
|
||||
public interface CalculatorEngineControl {
|
||||
|
||||
void evaluate();
|
||||
|
||||
void simplify();
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.text.DecimalFormatSymbols;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.AngleUnit;
|
||||
import jscl.JsclMathEngine;
|
||||
import jscl.MathEngine;
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IConstant;
|
||||
import jscl.math.operator.Operator;
|
||||
import jscl.text.ParseException;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/23/12
|
||||
* Time: 5:34 PM
|
||||
*/
|
||||
public class CalculatorEngineImpl implements CalculatorEngine {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
|
||||
|
||||
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* ENGINE/REGISTRIES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
@Nonnull
|
||||
private final MathEngine engine;
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorMathEngine mathEngine;
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorMathRegistry<IConstant> varsRegistry;
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorMathRegistry<Function> functionsRegistry;
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorMathRegistry<Operator> operatorsRegistry;
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorMathRegistry<Operator> postfixFunctionsRegistry;
|
||||
|
||||
@Nonnull
|
||||
private final Object lock;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* PREFERENCES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
|
||||
private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT);
|
||||
|
||||
@Nonnull
|
||||
private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT;
|
||||
|
||||
public CalculatorEngineImpl(@Nonnull JsclMathEngine engine,
|
||||
@Nonnull CalculatorMathRegistry<IConstant> varsRegistry,
|
||||
@Nonnull CalculatorMathRegistry<Function> functionsRegistry,
|
||||
@Nonnull CalculatorMathRegistry<Operator> operatorsRegistry,
|
||||
@Nonnull CalculatorMathRegistry<Operator> postfixFunctionsRegistry,
|
||||
@Nullable Object lock) {
|
||||
|
||||
this.engine = engine;
|
||||
this.mathEngine = new JsclCalculatorMathEngine(engine);
|
||||
|
||||
this.engine.setRoundResult(true);
|
||||
this.engine.setUseGroupingSeparator(true);
|
||||
|
||||
this.varsRegistry = varsRegistry;
|
||||
this.functionsRegistry = functionsRegistry;
|
||||
this.operatorsRegistry = operatorsRegistry;
|
||||
this.postfixFunctionsRegistry = postfixFunctionsRegistry;
|
||||
this.lock = lock == null ? new Object() : lock;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* REGISTRIES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorMathRegistry<IConstant> getVarsRegistry() {
|
||||
return this.varsRegistry;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorMathRegistry<Function> getFunctionsRegistry() {
|
||||
return this.functionsRegistry;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorMathRegistry<Operator> getOperatorsRegistry() {
|
||||
return this.operatorsRegistry;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry() {
|
||||
return this.postfixFunctionsRegistry;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorMathEngine getMathEngine() {
|
||||
return this.mathEngine;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MathEngine getMathEngine0() {
|
||||
return this.engine;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* INIT
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
synchronized (lock) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
synchronized (lock) {
|
||||
safeLoadRegistry(varsRegistry);
|
||||
safeLoadRegistry(functionsRegistry);
|
||||
safeLoadRegistry(operatorsRegistry);
|
||||
safeLoadRegistry(postfixFunctionsRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
private void safeLoadRegistry(@Nonnull CalculatorMathRegistry<?> registry) {
|
||||
try {
|
||||
registry.load();
|
||||
} catch (Exception e) {
|
||||
logException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void logException(@Nonnull Exception e) {
|
||||
final CalculatorLogger logger = Locator.getInstance().getLogger();
|
||||
logger.error("Engine", e.getMessage(), e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void softReset() {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.engine_preferences_changed, null);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* PREFERENCES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getMultiplicationSign() {
|
||||
return this.multiplicationSign;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMultiplicationSign(@Nonnull String multiplicationSign) {
|
||||
this.multiplicationSign = multiplicationSign;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseGroupingSeparator(boolean useGroupingSeparator) {
|
||||
synchronized (lock) {
|
||||
this.engine.setUseGroupingSeparator(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupingSeparator(char groupingSeparator) {
|
||||
synchronized (lock) {
|
||||
this.engine.setGroupingSeparator(groupingSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrecision(@Nonnull Integer precision) {
|
||||
synchronized (lock) {
|
||||
this.engine.setPrecision(precision);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRoundResult(@Nonnull Boolean round) {
|
||||
synchronized (lock) {
|
||||
this.engine.setRoundResult(round);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public AngleUnit getAngleUnits() {
|
||||
synchronized (lock) {
|
||||
return this.engine.getAngleUnits();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAngleUnits(@Nonnull AngleUnit angleUnits) {
|
||||
synchronized (lock) {
|
||||
this.engine.setAngleUnits(angleUnits);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public NumeralBase getNumeralBase() {
|
||||
synchronized (lock) {
|
||||
return this.engine.getNumeralBase();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNumeralBase(@Nonnull NumeralBase numeralBase) {
|
||||
synchronized (lock) {
|
||||
this.engine.setNumeralBase(numeralBase);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScienceNotation(@Nonnull Boolean scienceNotation) {
|
||||
synchronized (lock) {
|
||||
this.engine.setScienceNotation(scienceNotation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTimeout(@Nonnull Integer timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDecimalGroupSymbols(@Nonnull DecimalFormatSymbols decimalGroupSymbols) {
|
||||
synchronized (lock) {
|
||||
this.engine.setDecimalGroupSymbols(decimalGroupSymbols);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC CLASSES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static final class JsclCalculatorMathEngine implements CalculatorMathEngine {
|
||||
|
||||
@Nonnull
|
||||
private final MathEngine mathEngine;
|
||||
|
||||
private JsclCalculatorMathEngine(@Nonnull MathEngine mathEngine) {
|
||||
this.mathEngine = mathEngine;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String evaluate(@Nonnull String expression) throws ParseException {
|
||||
return this.mathEngine.evaluate(expression);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String simplify(@Nonnull String expression) throws ParseException {
|
||||
return this.mathEngine.simplify(expression);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String elementary(@Nonnull String expression) throws ParseException {
|
||||
return this.mathEngine.elementary(expression);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Generic evaluateGeneric(@Nonnull String expression) throws ParseException {
|
||||
return this.mathEngine.evaluateGeneric(expression);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Generic simplifyGeneric(@Nonnull String expression) throws ParseException {
|
||||
return this.mathEngine.simplifyGeneric(expression);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Generic elementaryGeneric(@Nonnull String expression) throws ParseException {
|
||||
return this.mathEngine.elementaryGeneric(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageLevel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/8/11
|
||||
* Time: 1:27 AM
|
||||
*/
|
||||
public class CalculatorEvalException extends Exception implements Message {
|
||||
|
||||
@Nonnull
|
||||
private final Message message;
|
||||
|
||||
@Nonnull
|
||||
private final String expression;
|
||||
|
||||
public CalculatorEvalException(@Nonnull Message message, @Nonnull Throwable cause, String expression) {
|
||||
super(cause);
|
||||
this.message = message;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getMessageCode() {
|
||||
return this.message.getMessageCode();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<Object> getParameters() {
|
||||
return this.message.getParameters();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MessageLevel getMessageLevel() {
|
||||
return this.message.getMessageLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String getLocalizedMessage() {
|
||||
return this.message.getLocalizedMessage(Locale.getDefault());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getLocalizedMessage(@Nonnull Locale locale) {
|
||||
return this.message.getLocalizedMessage(locale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 10:00 PM
|
||||
*/
|
||||
public interface CalculatorEvaluationEventData extends CalculatorEventData {
|
||||
|
||||
@Nonnull
|
||||
JsclOperation getOperation();
|
||||
|
||||
@Nonnull
|
||||
String getExpression();
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 10:01 PM
|
||||
*/
|
||||
public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEventData {
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorEventData calculatorEventData;
|
||||
|
||||
@Nonnull
|
||||
private final JsclOperation operation;
|
||||
|
||||
@Nonnull
|
||||
private final String expression;
|
||||
|
||||
public CalculatorEvaluationEventDataImpl(@Nonnull CalculatorEventData calculatorEventData,
|
||||
@Nonnull JsclOperation operation,
|
||||
@Nonnull String expression) {
|
||||
this.calculatorEventData = calculatorEventData;
|
||||
this.operation = operation;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public JsclOperation getOperation() {
|
||||
return this.operation;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getExpression() {
|
||||
return this.expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEventId() {
|
||||
return calculatorEventData.getEventId();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Long getSequenceId() {
|
||||
return calculatorEventData.getSequenceId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return calculatorEventData.getSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfter(@Nonnull CalculatorEventData that) {
|
||||
return calculatorEventData.isAfter(that);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
|
||||
return this.calculatorEventData.isSameSequence(that);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
|
||||
return this.calculatorEventData.isAfterSequence(that);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 16:39
|
||||
*/
|
||||
public interface CalculatorEventContainer {
|
||||
|
||||
void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener);
|
||||
|
||||
void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener);
|
||||
|
||||
void fireCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
|
||||
|
||||
void fireCalculatorEvents(@Nonnull List<CalculatorEvent> calculatorEvents);
|
||||
|
||||
public static class CalculatorEvent {
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEventData calculatorEventData;
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEventType calculatorEventType;
|
||||
|
||||
@Nullable
|
||||
private Object data;
|
||||
|
||||
public CalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
|
||||
@Nonnull CalculatorEventType calculatorEventType,
|
||||
@Nullable Object data) {
|
||||
this.calculatorEventData = calculatorEventData;
|
||||
this.calculatorEventType = calculatorEventType;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CalculatorEventData getCalculatorEventData() {
|
||||
return calculatorEventData;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CalculatorEventType getCalculatorEventType() {
|
||||
return calculatorEventType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@Nonnull
|
||||
Long getSequenceId();
|
||||
|
||||
@Nullable
|
||||
Object getSource();
|
||||
|
||||
boolean isAfter(@Nonnull CalculatorEventData that);
|
||||
|
||||
boolean isSameSequence(@Nonnull CalculatorEventData that);
|
||||
|
||||
boolean isAfterSequence(@Nonnull CalculatorEventData that);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
private final Object source;
|
||||
@Nonnull
|
||||
private Long sequenceId = NO_SEQUENCE;
|
||||
|
||||
private CalculatorEventDataImpl(long id, @Nonnull Long sequenceId, @Nullable Object source) {
|
||||
this.eventId = id;
|
||||
this.sequenceId = sequenceId;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId) {
|
||||
return new CalculatorEventDataImpl(id, sequenceId, null);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId, @Nonnull Object source) {
|
||||
return new CalculatorEventDataImpl(id, sequenceId, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEventId() {
|
||||
return this.eventId;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Long getSequenceId() {
|
||||
return this.sequenceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfter(@Nonnull CalculatorEventData that) {
|
||||
return this.eventId > that.getEventId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
|
||||
return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId.equals(that.getSequenceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterSequence(@Nonnull 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/9/12
|
||||
* Time: 9:59 PM
|
||||
*/
|
||||
public class CalculatorEventHolder {
|
||||
|
||||
@Nonnull
|
||||
private volatile CalculatorEventData lastEventData;
|
||||
|
||||
public CalculatorEventHolder(@Nonnull CalculatorEventData lastEventData) {
|
||||
this.lastEventData = lastEventData;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public synchronized CalculatorEventData getLastEventData() {
|
||||
return lastEventData;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public synchronized Result apply(@Nonnull CalculatorEventData newEventData) {
|
||||
final Result result = new Result(lastEventData, newEventData);
|
||||
|
||||
if (result.isNewAfter()) {
|
||||
this.lastEventData = newEventData;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class Result {
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorEventData lastEventData;
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorEventData newEventData;
|
||||
|
||||
@Nullable
|
||||
private Boolean after = null;
|
||||
|
||||
@Nullable
|
||||
private Boolean sameSequence = null;
|
||||
|
||||
public Result(@Nonnull CalculatorEventData lastEventData,
|
||||
@Nonnull CalculatorEventData newEventData) {
|
||||
this.lastEventData = lastEventData;
|
||||
this.newEventData = newEventData;
|
||||
}
|
||||
|
||||
public boolean isNewAfter() {
|
||||
if (after == null) {
|
||||
after = newEventData.isAfter(lastEventData);
|
||||
}
|
||||
return after;
|
||||
}
|
||||
|
||||
public boolean isSameSequence() {
|
||||
if (sameSequence == null) {
|
||||
sameSequence = newEventData.isSameSequence(lastEventData);
|
||||
}
|
||||
return sameSequence;
|
||||
}
|
||||
|
||||
public boolean isNewAfterSequence() {
|
||||
return newEventData.isAfterSequence(lastEventData);
|
||||
}
|
||||
|
||||
public boolean isNewSameOrAfterSequence() {
|
||||
return isSameSequence() || isNewAfterSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 16:39
|
||||
*/
|
||||
public interface CalculatorEventListener extends EventListener {
|
||||
|
||||
void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 16:40
|
||||
*/
|
||||
public enum CalculatorEventType {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CALCULATION
|
||||
* org.solovyev.android.calculator.CalculatorEvaluationEventData
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
|
||||
// @Nonnull CalculatorEditorViewState
|
||||
manual_calculation_requested,
|
||||
|
||||
// @Nonnull org.solovyev.android.calculator.CalculatorOutput
|
||||
calculation_result,
|
||||
|
||||
calculation_cancelled,
|
||||
|
||||
// @Nonnull org.solovyev.android.calculator.CalculatorFailure
|
||||
calculation_failed,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONVERSION
|
||||
* CalculatorConversionEventData
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
conversion_started,
|
||||
|
||||
// @Nonnull String conversion result
|
||||
conversion_result,
|
||||
|
||||
// @Nonnull ConversionFailure
|
||||
conversion_failed,
|
||||
|
||||
conversion_finished,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* EDITOR
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
// @Nonnull org.solovyev.android.calculator.CalculatorEditorChangeEventData
|
||||
editor_state_changed,
|
||||
editor_state_changed_light,
|
||||
|
||||
// @Nonnull CalculatorDisplayChangeEventData
|
||||
display_state_changed,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* ENGINE
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
engine_preferences_changed,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* HISTORY
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
// @Nonnull CalculatorHistoryState
|
||||
history_state_added,
|
||||
|
||||
// @Nonnull CalculatorHistoryState
|
||||
use_history_state,
|
||||
|
||||
clear_history_requested,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* MATH ENTITIES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
// @Nonnull IConstant
|
||||
use_constant,
|
||||
|
||||
// @Nonnull Function
|
||||
use_function,
|
||||
|
||||
// @Nonnull Operator
|
||||
use_operator,
|
||||
|
||||
// @Nonnull IConstant
|
||||
constant_added,
|
||||
|
||||
// @Nonnull Change<IConstant>
|
||||
constant_changed,
|
||||
|
||||
// @Nonnull IConstant
|
||||
constant_removed,
|
||||
|
||||
|
||||
// @Nonnull Function
|
||||
function_removed,
|
||||
|
||||
// @Nonnull Function
|
||||
function_added,
|
||||
|
||||
// @Nonnull Change<IFunction>
|
||||
function_changed,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* OTHER
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
// List<Message>
|
||||
calculation_messages,
|
||||
|
||||
show_history,
|
||||
show_history_detached,
|
||||
|
||||
show_functions,
|
||||
show_functions_detached,
|
||||
|
||||
show_vars,
|
||||
show_vars_detached,
|
||||
|
||||
open_app,
|
||||
|
||||
show_operators,
|
||||
show_operators_detached,
|
||||
|
||||
show_settings,
|
||||
show_settings_detached,
|
||||
|
||||
show_like_dialog,
|
||||
|
||||
show_create_var_dialog,
|
||||
show_create_matrix_dialog,
|
||||
show_create_function_dialog,
|
||||
|
||||
/**
|
||||
* {@link DialogData}
|
||||
*/
|
||||
show_message_dialog,
|
||||
|
||||
plot_graph,
|
||||
|
||||
/**
|
||||
* {@link org.solovyev.android.calculator.plot.PlotData}
|
||||
*/
|
||||
plot_data_changed,
|
||||
|
||||
//String
|
||||
show_evaluation_error;
|
||||
|
||||
public boolean isOfType(@Nonnull CalculatorEventType... types) {
|
||||
for (CalculatorEventType type : types) {
|
||||
if (this == type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 7:33 PM
|
||||
*/
|
||||
public interface CalculatorFailure {
|
||||
|
||||
@Nonnull
|
||||
Exception getException();
|
||||
|
||||
@Nullable
|
||||
CalculatorParseException getCalculationParseException();
|
||||
|
||||
@Nullable
|
||||
CalculatorEvalException getCalculationEvalException();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 7:34 PM
|
||||
*/
|
||||
public class CalculatorFailureImpl implements CalculatorFailure {
|
||||
|
||||
@Nonnull
|
||||
private Exception exception;
|
||||
|
||||
public CalculatorFailureImpl(@Nonnull Exception exception) {
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Exception getException() {
|
||||
return this.exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorParseException getCalculationParseException() {
|
||||
return exception instanceof CalculatorParseException ? (CalculatorParseException) exception : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorEvalException getCalculationEvalException() {
|
||||
return exception instanceof CalculatorEvalException ? (CalculatorEvalException) exception : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CalculatorFailureImpl{" +
|
||||
"exception=" + exception +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.collections.Collections;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.AngleUnit;
|
||||
import jscl.text.msg.Messages;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/17/12
|
||||
* Time: 7:30 PM
|
||||
*/
|
||||
public enum CalculatorFixableError implements FixableError {
|
||||
|
||||
must_be_rad(Messages.msg_23, Messages.msg_24, Messages.msg_25) {
|
||||
@Override
|
||||
public void fix() {
|
||||
Locator.getInstance().getPreferenceService().setAngleUnits(AngleUnit.rad);
|
||||
}
|
||||
},
|
||||
|
||||
preferred_numeral_base() {
|
||||
@Override
|
||||
public void fix() {
|
||||
Locator.getInstance().getPreferenceService().setPreferredNumeralBase();
|
||||
}
|
||||
},
|
||||
|
||||
preferred_angle_units() {
|
||||
@Override
|
||||
public void fix() {
|
||||
Locator.getInstance().getPreferenceService().setPreferredAngleUnits();
|
||||
}
|
||||
};
|
||||
|
||||
@Nonnull
|
||||
private final List<String> messageCodes;
|
||||
|
||||
CalculatorFixableError(@Nullable String... messageCodes) {
|
||||
this.messageCodes = Collections.asList(messageCodes);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CalculatorFixableError getErrorByMessageCode(@Nonnull String messageCode) {
|
||||
for (CalculatorFixableError fixableError : values()) {
|
||||
if (fixableError.messageCodes.contains(messageCode)) {
|
||||
return fixableError;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CharSequence getFixCaption() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.function.FunctionBuilderAdapter;
|
||||
import org.solovyev.android.calculator.model.AFunction;
|
||||
import org.solovyev.android.calculator.model.Functions;
|
||||
import org.solovyev.android.calculator.model.MathEntityBuilder;
|
||||
import org.solovyev.common.JBuilder;
|
||||
import org.solovyev.common.math.MathRegistry;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.CustomFunctionCalculationException;
|
||||
import jscl.math.function.CustomFunction;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IFunction;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/17/11
|
||||
* Time: 11:28 PM
|
||||
*/
|
||||
public class CalculatorFunctionsMathRegistry extends AbstractCalculatorMathRegistry<Function, AFunction> {
|
||||
|
||||
@Nonnull
|
||||
private static final Map<String, String> substitutes = new HashMap<String, String>();
|
||||
@Nonnull
|
||||
private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_";
|
||||
|
||||
static {
|
||||
substitutes.put("√", "sqrt");
|
||||
}
|
||||
|
||||
public CalculatorFunctionsMathRegistry(@Nonnull MathRegistry<Function> functionsRegistry,
|
||||
@Nonnull MathEntityDao<AFunction> mathEntityDao) {
|
||||
super(functionsRegistry, FUNCTION_DESCRIPTION_PREFIX, mathEntityDao);
|
||||
}
|
||||
|
||||
public static void saveFunction(@Nonnull CalculatorMathRegistry<Function> registry,
|
||||
@Nonnull MathEntityBuilder<? extends Function> builder,
|
||||
@Nullable IFunction editedInstance,
|
||||
@Nonnull Object source, boolean save) throws CustomFunctionCalculationException, AFunction.Builder.CreationException {
|
||||
final Function addedFunction = registry.add(builder);
|
||||
|
||||
if (save) {
|
||||
registry.save();
|
||||
}
|
||||
|
||||
if (editedInstance == null) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.function_added, addedFunction, source);
|
||||
} else {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.function_changed, ChangeImpl.newInstance(editedInstance, addedFunction), source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
add(new CustomFunction.Builder(true, "log", Arrays.asList("base", "x"), "ln(x)/ln(base)"));
|
||||
add(new CustomFunction.Builder(true, "√3", Arrays.asList("x"), "x^(1/3)"));
|
||||
add(new CustomFunction.Builder(true, "√4", Arrays.asList("x"), "x^(1/4)"));
|
||||
add(new CustomFunction.Builder(true, "√n", Arrays.asList("x", "n"), "x^(1/n)"));
|
||||
add(new CustomFunction.Builder(true, "re", Arrays.asList("x"), "(x+conjugate(x))/2"));
|
||||
add(new CustomFunction.Builder(true, "im", Arrays.asList("x"), "(x-conjugate(x))/(2*i)"));
|
||||
|
||||
super.load();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Map<String, String> getSubstitutes() {
|
||||
return substitutes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory(@Nonnull Function function) {
|
||||
for (FunctionCategory category : FunctionCategory.values()) {
|
||||
if (category.isInCategory(function)) {
|
||||
return category.name();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDescription(@Nonnull String functionName) {
|
||||
final Function function = get(functionName);
|
||||
|
||||
String result = null;
|
||||
if (function instanceof CustomFunction) {
|
||||
result = ((CustomFunction) function).getDescription();
|
||||
}
|
||||
|
||||
if (Strings.isEmpty(result)) {
|
||||
result = super.getDescription(functionName);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected JBuilder<? extends Function> createBuilder(@Nonnull AFunction function) {
|
||||
return new FunctionBuilderAdapter(new AFunction.Builder(function));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AFunction transform(@Nonnull Function function) {
|
||||
if (function instanceof CustomFunction) {
|
||||
return AFunction.fromIFunction((CustomFunction) function);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected MathEntityPersistenceContainer<AFunction> createPersistenceContainer() {
|
||||
return new Functions();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,637 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
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.model.Var;
|
||||
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.ListMessageRegistry;
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageRegistry;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
import org.solovyev.common.text.Strings;
|
||||
import org.solovyev.common.units.ConversionException;
|
||||
import org.solovyev.common.units.Conversions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.AbstractJsclArithmeticException;
|
||||
import jscl.NumeralBase;
|
||||
import jscl.NumeralBaseException;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IConstant;
|
||||
import jscl.math.operator.Operator;
|
||||
import jscl.text.ParseInterruptedException;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 16:42
|
||||
*/
|
||||
public class CalculatorImpl implements Calculator, CalculatorEventListener {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
// one minute
|
||||
private static final long PREFERENCE_CHECK_INTERVAL = 1000L * 60L;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer();
|
||||
|
||||
@Nonnull
|
||||
private final AtomicLong counter = new AtomicLong(CalculatorUtils.FIRST_ID);
|
||||
|
||||
@Nonnull
|
||||
private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
||||
|
||||
@Nonnull
|
||||
private final Executor calculationsExecutor = Executors.newFixedThreadPool(10);
|
||||
|
||||
// NOTE: only one thread is responsible for events as all events must be done in order of their creating
|
||||
@Nonnull
|
||||
private final Executor eventExecutor = Executors.newFixedThreadPool(1);
|
||||
|
||||
private volatile boolean calculateOnFly = true;
|
||||
|
||||
private volatile long lastPreferenceCheck = 0L;
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public CalculatorImpl() {
|
||||
this.addCalculatorEventListener(this);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
private static String doConversion(@Nonnull Generic generic,
|
||||
@Nonnull NumeralBase from,
|
||||
@Nonnull NumeralBase to) throws ConversionException {
|
||||
final String result;
|
||||
|
||||
if (from != to) {
|
||||
String fromString = generic.toString();
|
||||
if (!Strings.isEmpty(fromString)) {
|
||||
try {
|
||||
fromString = ToJsclTextProcessor.getInstance().process(fromString).getExpression();
|
||||
} catch (CalculatorParseException e) {
|
||||
// ok, problems while processing occurred
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
result = Conversions.doConversion(CalculatorNumeralBase.getConverter(), fromString, CalculatorNumeralBase.valueOf(from), CalculatorNumeralBase.valueOf(to));
|
||||
} else {
|
||||
result = generic.toString();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEventData nextEventData() {
|
||||
long eventId = counter.incrementAndGet();
|
||||
return CalculatorEventDataImpl.newInstance(eventId, eventId);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEventData nextEventData(@Nonnull Object source) {
|
||||
long eventId = counter.incrementAndGet();
|
||||
return CalculatorEventDataImpl.newInstance(eventId, eventId, source);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CALCULATION
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEventData nextEventData(@Nonnull Long sequenceId) {
|
||||
long eventId = counter.incrementAndGet();
|
||||
return CalculatorEventDataImpl.newInstance(eventId, sequenceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate() {
|
||||
final CalculatorEditorViewState viewState = getEditor().getViewState();
|
||||
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState);
|
||||
this.evaluate(JsclOperation.numeric, viewState.getText(), eventData.getSequenceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(@Nonnull 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();
|
||||
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState);
|
||||
this.evaluate(JsclOperation.simplify, viewState.getText(), eventData.getSequenceId());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEventData evaluate(@Nonnull final JsclOperation operation,
|
||||
@Nonnull final String expression) {
|
||||
|
||||
final CalculatorEventData eventDataId = nextEventData();
|
||||
|
||||
calculationsExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null);
|
||||
}
|
||||
});
|
||||
|
||||
return eventDataId;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEventData evaluate(@Nonnull final JsclOperation operation, @Nonnull final String expression, @Nonnull Long sequenceId) {
|
||||
final CalculatorEventData eventDataId = nextEventData(sequenceId);
|
||||
|
||||
calculationsExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null);
|
||||
}
|
||||
});
|
||||
|
||||
return eventDataId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Locator.getInstance().getEngine().init();
|
||||
Locator.getInstance().getHistory().load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCalculateOnFly() {
|
||||
return calculateOnFly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCalculateOnFly(boolean calculateOnFly) {
|
||||
if (this.calculateOnFly != calculateOnFly) {
|
||||
this.calculateOnFly = calculateOnFly;
|
||||
if (this.calculateOnFly) {
|
||||
evaluate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private CalculatorConversionEventData newConversionEventData(@Nonnull Long sequenceId,
|
||||
@Nonnull Generic value,
|
||||
@Nonnull NumeralBase from,
|
||||
@Nonnull NumeralBase to,
|
||||
@Nonnull CalculatorDisplayViewState displayViewState) {
|
||||
return CalculatorConversionEventDataImpl.newInstance(nextEventData(sequenceId), value, from, to, displayViewState);
|
||||
}
|
||||
|
||||
private void evaluate(@Nonnull Long sequenceId,
|
||||
@Nonnull JsclOperation operation,
|
||||
@Nonnull String expression,
|
||||
@Nullable MessageRegistry mr) {
|
||||
|
||||
checkPreferredPreferences();
|
||||
|
||||
PreparedExpression preparedExpression = null;
|
||||
|
||||
try {
|
||||
|
||||
expression = expression.trim();
|
||||
|
||||
if (Strings.isEmpty(expression)) {
|
||||
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, CalculatorOutputImpl.newEmptyOutput(operation));
|
||||
} else {
|
||||
preparedExpression = prepareExpression(expression);
|
||||
|
||||
final String jsclExpression = preparedExpression.toString();
|
||||
|
||||
try {
|
||||
|
||||
final CalculatorMathEngine mathEngine = Locator.getInstance().getEngine().getMathEngine();
|
||||
|
||||
final MessageRegistry messageRegistry = new ListMessageRegistry();
|
||||
Locator.getInstance().getEngine().getMathEngine0().setMessageRegistry(messageRegistry);
|
||||
|
||||
final Generic result = operation.evaluateGeneric(jsclExpression, mathEngine);
|
||||
|
||||
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
||||
result.toString();
|
||||
|
||||
if (messageRegistry.hasMessage()) {
|
||||
final CalculatorLogger logger = Locator.getInstance().getLogger();
|
||||
try {
|
||||
final List<Message> messages = new ArrayList<Message>();
|
||||
while (messageRegistry.hasMessage()) {
|
||||
messages.add(messageRegistry.getMessage());
|
||||
}
|
||||
if (!messages.isEmpty()) {
|
||||
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_messages, messages);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
// todo serso: not good but we need proper synchronization
|
||||
logger.error("Calculator", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPreferredPreferences() {
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
|
||||
if (currentTime - lastPreferenceCheck > PREFERENCE_CHECK_INTERVAL) {
|
||||
lastPreferenceCheck = currentTime;
|
||||
Locator.getInstance().getPreferenceService().checkPreferredPreferences(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public PreparedExpression prepareExpression(@Nonnull String expression) throws CalculatorParseException {
|
||||
return preprocessor.process(expression);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEventData newCalculationEventData(@Nonnull JsclOperation operation,
|
||||
@Nonnull String expression,
|
||||
@Nonnull Long calculationId) {
|
||||
return new CalculatorEvaluationEventDataImpl(nextEventData(calculationId), operation, expression);
|
||||
}
|
||||
|
||||
private void handleException(@Nonnull Long sequenceId,
|
||||
@Nonnull JsclOperation operation,
|
||||
@Nonnull String expression,
|
||||
@Nullable MessageRegistry mr,
|
||||
@Nullable PreparedExpression preparedExpression,
|
||||
@Nonnull 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));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONVERSION
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private void handleException(@Nonnull Long calculationId,
|
||||
@Nonnull JsclOperation operation,
|
||||
@Nonnull String expression,
|
||||
@Nullable MessageRegistry mr,
|
||||
@Nonnull CalculatorEvalException evalException) {
|
||||
|
||||
if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) {
|
||||
evaluate(calculationId, JsclOperation.simplify, expression, mr);
|
||||
} else {
|
||||
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEventData convert(@Nonnull final Generic value,
|
||||
@Nonnull final NumeralBase to) {
|
||||
final CalculatorEventData eventDataId = nextEventData();
|
||||
|
||||
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
|
||||
final NumeralBase from = Locator.getInstance().getEngine().getNumeralBase();
|
||||
|
||||
calculationsExecutor.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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConversionPossible(@Nonnull Generic generic, NumeralBase from, @Nonnull NumeralBase to) {
|
||||
try {
|
||||
doConversion(generic, from, to);
|
||||
return true;
|
||||
} catch (ConversionException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* EVENTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
|
||||
calculatorEventContainer.addCalculatorEventListener(calculatorEventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
|
||||
calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCalculatorEvent(@Nonnull final CalculatorEventData calculatorEventData, @Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data) {
|
||||
eventExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCalculatorEvents(@Nonnull final List<CalculatorEvent> calculatorEvents) {
|
||||
eventExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
calculatorEventContainer.fireCalculatorEvents(calculatorEvents);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data) {
|
||||
final CalculatorEventData eventData = nextEventData();
|
||||
|
||||
fireCalculatorEvent(eventData, calculatorEventType, data);
|
||||
|
||||
return eventData;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data, @Nonnull Object source) {
|
||||
final CalculatorEventData eventData = nextEventData(source);
|
||||
|
||||
fireCalculatorEvent(eventData, calculatorEventType, data);
|
||||
|
||||
return eventData;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data, @Nonnull Long sequenceId) {
|
||||
final CalculatorEventData eventData = nextEventData(sequenceId);
|
||||
|
||||
fireCalculatorEvent(eventData, calculatorEventType, data);
|
||||
|
||||
return eventData;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* EVENTS HANDLER
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
|
||||
switch (calculatorEventType) {
|
||||
case editor_state_changed:
|
||||
if (calculateOnFly) {
|
||||
final CalculatorEditorChangeEventData editorChangeEventData = (CalculatorEditorChangeEventData) data;
|
||||
|
||||
final String newText = editorChangeEventData.getNewValue().getText();
|
||||
final String oldText = editorChangeEventData.getOldValue().getText();
|
||||
|
||||
if (!newText.equals(oldText)) {
|
||||
evaluate(JsclOperation.numeric, editorChangeEventData.getNewValue().getText(), calculatorEventData.getSequenceId());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case display_state_changed:
|
||||
onDisplayStateChanged((CalculatorDisplayChangeEventData) data);
|
||||
break;
|
||||
|
||||
case constant_changed:
|
||||
final IConstant newConstant = ((Change<IConstant>) data).getNewValue();
|
||||
if (!newConstant.getName().equals(CalculatorVarsRegistry.ANS)) {
|
||||
evaluate();
|
||||
}
|
||||
break;
|
||||
|
||||
case constant_added:
|
||||
case constant_removed:
|
||||
case function_added:
|
||||
case function_changed:
|
||||
case function_removed:
|
||||
evaluate();
|
||||
break;
|
||||
|
||||
case engine_preferences_changed:
|
||||
evaluate(calculatorEventData.getSequenceId());
|
||||
break;
|
||||
|
||||
case use_constant:
|
||||
final IConstant constant = (IConstant) data;
|
||||
Locator.getInstance().getKeyboard().buttonPressed(constant.getName());
|
||||
break;
|
||||
|
||||
case use_operator:
|
||||
final Operator operator = (Operator) data;
|
||||
Locator.getInstance().getKeyboard().buttonPressed(operator.getName());
|
||||
break;
|
||||
|
||||
case use_function:
|
||||
final Function function = (Function) data;
|
||||
Locator.getInstance().getKeyboard().buttonPressed(function.getName());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void onDisplayStateChanged(@Nonnull CalculatorDisplayChangeEventData displayChangeEventData) {
|
||||
final CalculatorDisplayViewState newState = displayChangeEventData.getNewValue();
|
||||
if (newState.isValid()) {
|
||||
final String result = newState.getStringResult();
|
||||
if (!Strings.isEmpty(result)) {
|
||||
final CalculatorMathRegistry<IConstant> varsRegistry = Locator.getInstance().getEngine().getVarsRegistry();
|
||||
final IConstant ansVar = varsRegistry.get(CalculatorVarsRegistry.ANS);
|
||||
|
||||
final Var.Builder varBuilder;
|
||||
if (ansVar != null) {
|
||||
varBuilder = new Var.Builder(ansVar);
|
||||
} else {
|
||||
varBuilder = new Var.Builder();
|
||||
}
|
||||
|
||||
varBuilder.setName(CalculatorVarsRegistry.ANS);
|
||||
varBuilder.setValue(result);
|
||||
varBuilder.setDescription(CalculatorMessages.getBundle().getString(CalculatorMessages.ans_description));
|
||||
|
||||
CalculatorVarsRegistry.saveVariable(varsRegistry, varBuilder, ansVar, this, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* HISTORY
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void doHistoryAction(@Nonnull HistoryAction historyAction) {
|
||||
final CalculatorHistory history = Locator.getInstance().getHistory();
|
||||
if (history.isActionAvailable(historyAction)) {
|
||||
final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState());
|
||||
if (newState != null) {
|
||||
setCurrentHistoryState(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorHistoryState getCurrentHistoryState() {
|
||||
return CalculatorHistoryState.newInstance(getEditor(), getDisplay());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentHistoryState(@Nonnull CalculatorHistoryState editorHistoryState) {
|
||||
editorHistoryState.setValuesFromHistory(getEditor(), getDisplay());
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* OTHER
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
private CalculatorEditor getEditor() {
|
||||
return Locator.getInstance().getEditor();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private CalculatorDisplay getDisplay() {
|
||||
return Locator.getInstance().getDisplay();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 7:25 PM
|
||||
*/
|
||||
public interface CalculatorInput {
|
||||
|
||||
@Nonnull
|
||||
String getExpression();
|
||||
|
||||
@Nonnull
|
||||
JsclOperation getOperation();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 7:26 PM
|
||||
*/
|
||||
public class CalculatorInputImpl implements CalculatorInput {
|
||||
|
||||
@Nonnull
|
||||
private String expression;
|
||||
|
||||
@Nonnull
|
||||
private JsclOperation operation;
|
||||
|
||||
public CalculatorInputImpl(@Nonnull String expression, @Nonnull JsclOperation operation) {
|
||||
this.expression = expression;
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public JsclOperation getOperation() {
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 1:08 PM
|
||||
*/
|
||||
public interface CalculatorKeyboard {
|
||||
|
||||
boolean buttonPressed(@Nullable String text);
|
||||
|
||||
void roundBracketsButtonPressed();
|
||||
|
||||
void pasteButtonPressed();
|
||||
|
||||
void clearButtonPressed();
|
||||
|
||||
void copyButtonPressed();
|
||||
|
||||
void moveCursorLeft();
|
||||
|
||||
void moveCursorRight();
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 1:08 PM
|
||||
*/
|
||||
public class CalculatorKeyboardImpl implements CalculatorKeyboard {
|
||||
|
||||
@Nonnull
|
||||
private final Calculator calculator;
|
||||
|
||||
public CalculatorKeyboardImpl(@Nonnull Calculator calculator) {
|
||||
this.calculator = calculator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean buttonPressed(@Nullable final String text) {
|
||||
if (!Strings.isEmpty(text)) {
|
||||
if (text == null) throw new AssertionError();
|
||||
|
||||
// process special buttons
|
||||
boolean processed = processSpecialButtons(text);
|
||||
|
||||
if (!processed) {
|
||||
processText(prepareText(text));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void processText(@Nonnull String text) {
|
||||
int cursorPositionOffset = 0;
|
||||
final StringBuilder textToBeInserted = new StringBuilder(text);
|
||||
|
||||
final MathType.Result mathType = MathType.getType(text, 0, false);
|
||||
switch (mathType.getMathType()) {
|
||||
case function:
|
||||
textToBeInserted.append("()");
|
||||
cursorPositionOffset = -1;
|
||||
break;
|
||||
case operator:
|
||||
textToBeInserted.append("()");
|
||||
cursorPositionOffset = -1;
|
||||
break;
|
||||
case comma:
|
||||
textToBeInserted.append(" ");
|
||||
break;
|
||||
}
|
||||
|
||||
if (cursorPositionOffset == 0) {
|
||||
if (MathType.openGroupSymbols.contains(text)) {
|
||||
cursorPositionOffset = -1;
|
||||
}
|
||||
}
|
||||
|
||||
final CalculatorEditor editor = Locator.getInstance().getEditor();
|
||||
editor.insert(textToBeInserted.toString(), cursorPositionOffset);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private String prepareText(@Nonnull String text) {
|
||||
if ("( )".equals(text) || "( )".equals(text)) {
|
||||
return "()";
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean processSpecialButtons(@Nonnull String text) {
|
||||
boolean result = false;
|
||||
|
||||
final CalculatorSpecialButton button = CalculatorSpecialButton.getByActionCode(text);
|
||||
if (button != null) {
|
||||
button.onClick(this);
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void roundBracketsButtonPressed() {
|
||||
final CalculatorEditor editor = Locator.getInstance().getEditor();
|
||||
CalculatorEditorViewState viewState = editor.getViewState();
|
||||
|
||||
final int cursorPosition = viewState.getSelection();
|
||||
final String oldText = viewState.getText();
|
||||
|
||||
final StringBuilder newText = new StringBuilder(oldText.length() + 2);
|
||||
newText.append("(");
|
||||
newText.append(oldText.substring(0, cursorPosition));
|
||||
newText.append(")");
|
||||
newText.append(oldText.substring(cursorPosition));
|
||||
editor.setText(newText.toString(), cursorPosition + 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pasteButtonPressed() {
|
||||
final String text = Locator.getInstance().getClipboard().getText();
|
||||
if (text != null) {
|
||||
Locator.getInstance().getEditor().insert(text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearButtonPressed() {
|
||||
Locator.getInstance().getEditor().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyButtonPressed() {
|
||||
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
|
||||
if (displayViewState.isValid()) {
|
||||
final CharSequence text = displayViewState.getText();
|
||||
if (!Strings.isEmpty(text)) {
|
||||
Locator.getInstance().getClipboard().setText(text);
|
||||
Locator.getInstance().getNotifier().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveCursorLeft() {
|
||||
Locator.getInstance().getEditor().moveCursorLeft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveCursorRight() {
|
||||
Locator.getInstance().getEditor().moveCursorRight();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 12:45
|
||||
*/
|
||||
public interface CalculatorLocator {
|
||||
|
||||
void init(@Nonnull Calculator calculator,
|
||||
@Nonnull CalculatorEngine engine,
|
||||
@Nonnull CalculatorClipboard clipboard,
|
||||
@Nonnull CalculatorNotifier notifier,
|
||||
@Nonnull CalculatorHistory history,
|
||||
@Nonnull CalculatorLogger logger,
|
||||
@Nonnull CalculatorPreferenceService preferenceService,
|
||||
@Nonnull CalculatorKeyboard keyboard,
|
||||
@Nonnull CalculatorPlotter plotter,
|
||||
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor);
|
||||
|
||||
@Nonnull
|
||||
Calculator getCalculator();
|
||||
|
||||
@Nonnull
|
||||
CalculatorEngine getEngine();
|
||||
|
||||
@Nonnull
|
||||
CalculatorDisplay getDisplay();
|
||||
|
||||
@Nonnull
|
||||
CalculatorEditor getEditor();
|
||||
|
||||
@Nonnull
|
||||
CalculatorKeyboard getKeyboard();
|
||||
|
||||
@Nonnull
|
||||
CalculatorClipboard getClipboard();
|
||||
|
||||
@Nonnull
|
||||
CalculatorNotifier getNotifier();
|
||||
|
||||
@Nonnull
|
||||
CalculatorHistory getHistory();
|
||||
|
||||
@Nonnull
|
||||
CalculatorLogger getLogger();
|
||||
|
||||
@Nonnull
|
||||
CalculatorPlotter getPlotter();
|
||||
|
||||
@Nonnull
|
||||
CalculatorPreferenceService getPreferenceService();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/11/12
|
||||
* Time: 12:11 AM
|
||||
*/
|
||||
public interface CalculatorLogger {
|
||||
|
||||
void debug(@Nullable String tag, @Nonnull String message);
|
||||
|
||||
void debug(@Nullable String tag, @Nullable String message, @Nonnull Throwable e);
|
||||
|
||||
void error(@Nullable String tag, @Nullable String message, @Nonnull Throwable e);
|
||||
|
||||
void error(@Nullable String tag, @Nullable String message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.Generic;
|
||||
import jscl.text.ParseException;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/23/12
|
||||
* Time: 6:05 PM
|
||||
*/
|
||||
public interface CalculatorMathEngine {
|
||||
|
||||
@Nonnull
|
||||
String evaluate(@Nonnull String expression) throws ParseException;
|
||||
|
||||
@Nonnull
|
||||
String simplify(@Nonnull String expression) throws ParseException;
|
||||
|
||||
@Nonnull
|
||||
String elementary(@Nonnull String expression) throws ParseException;
|
||||
|
||||
@Nonnull
|
||||
Generic evaluateGeneric(@Nonnull String expression) throws ParseException;
|
||||
|
||||
@Nonnull
|
||||
Generic simplifyGeneric(@Nonnull String expression) throws ParseException;
|
||||
|
||||
@Nonnull
|
||||
Generic elementaryGeneric(@Nonnull String expression) throws ParseException;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
import org.solovyev.common.math.MathRegistry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/30/11
|
||||
* Time: 1:02 AM
|
||||
*/
|
||||
public interface CalculatorMathRegistry<T extends MathEntity> extends MathRegistry<T> {
|
||||
|
||||
@Nullable
|
||||
String getDescription(@Nonnull String mathEntityName);
|
||||
|
||||
@Nullable
|
||||
String getCategory(@Nonnull T mathEntity);
|
||||
|
||||
void load();
|
||||
|
||||
void save();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.AbstractMessage;
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 8:06 PM
|
||||
*/
|
||||
public class CalculatorMessage extends AbstractMessage {
|
||||
|
||||
public CalculatorMessage(@Nonnull String messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters) {
|
||||
super(messageCode, messageType, parameters);
|
||||
}
|
||||
|
||||
public CalculatorMessage(@Nonnull String messageCode, @Nonnull MessageType messageType, @Nonnull List<?> parameters) {
|
||||
super(messageCode, messageType, parameters);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Message newInfoMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
|
||||
return new CalculatorMessage(messageCode, MessageType.info, parameters);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Message newWarningMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
|
||||
return new CalculatorMessage(messageCode, MessageType.warning, parameters);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Message newErrorMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
|
||||
return new CalculatorMessage(messageCode, MessageType.error, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMessagePattern(@Nonnull Locale locale) {
|
||||
final ResourceBundle rb = CalculatorMessages.getBundle(locale);
|
||||
return rb.getString(getMessageCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.solovyev.common.msg.MessageType.error;
|
||||
import static org.solovyev.common.msg.MessageType.info;
|
||||
import static org.solovyev.common.msg.MessageType.warning;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 8:10 PM
|
||||
*/
|
||||
public final class CalculatorMessages {
|
||||
|
||||
|
||||
/* Arithmetic error occurred: {0} */
|
||||
public static final String msg_001 = "msg_1";
|
||||
/* Too complex expression*/
|
||||
public static final String msg_002 = "msg_2";
|
||||
/* Too long execution time - check the expression*/
|
||||
public static final String msg_003 = "msg_3";
|
||||
/* Evaluation was cancelled*/
|
||||
public static final String msg_004 = "msg_4";
|
||||
/* No parameters are specified for function: {0}*/
|
||||
public static final String msg_005 = "msg_5";
|
||||
/* Infinite loop is detected in expression*/
|
||||
public static final String msg_006 = "msg_6";
|
||||
/**
|
||||
* Some data could not be loaded. Contact authors of application with information below.\n\nUnable to load:\n{0}
|
||||
*/
|
||||
public static final String msg_007 = "msg_7";
|
||||
/* Error */
|
||||
public static final String syntax_error = "syntax_error";
|
||||
/* Result copied to clipboard! */
|
||||
public static final String result_copied = "result_copied";
|
||||
/* Text copied to clipboard! */
|
||||
public static final String text_copied = "text_copied";
|
||||
/* Last calculated value */
|
||||
public static final String ans_description = "ans_description";
|
||||
|
||||
private CalculatorMessages() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static ResourceBundle getBundle() {
|
||||
return getBundle(Locale.getDefault());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static ResourceBundle getBundle(@Nonnull Locale locale) {
|
||||
try {
|
||||
return ResourceBundle.getBundle("org/solovyev/android/calculator/messages", locale);
|
||||
} catch (MissingResourceException e) {
|
||||
return ResourceBundle.getBundle("org/solovyev/android/calculator/messages", Locale.ENGLISH);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorMessage newErrorMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
|
||||
return new CalculatorMessage(messageCode, error, parameters);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
static MessageType toMessageType(int messageLevel) {
|
||||
if (messageLevel < info.getMessageLevel()) {
|
||||
return info;
|
||||
} else if (messageLevel < warning.getMessageLevel()) {
|
||||
return warning;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 1:52 PM
|
||||
*/
|
||||
public interface CalculatorNotifier {
|
||||
|
||||
void showMessage(@Nonnull Message message);
|
||||
|
||||
void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nonnull List<Object> parameters);
|
||||
|
||||
void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters);
|
||||
|
||||
void showDebugMessage(@Nullable String tag, @Nonnull String message);
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.JBuilder;
|
||||
import org.solovyev.common.math.MathRegistry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.operator.Operator;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/17/11
|
||||
* Time: 11:29 PM
|
||||
*/
|
||||
public class CalculatorOperatorsMathRegistry extends AbstractCalculatorMathRegistry<Operator, MathPersistenceEntity> {
|
||||
|
||||
@Nonnull
|
||||
private static final Map<String, String> substitutes = new HashMap<String, String>();
|
||||
@Nonnull
|
||||
private static final String OPERATOR_DESCRIPTION_PREFIX = "c_op_description_";
|
||||
|
||||
static {
|
||||
substitutes.put("Σ", "sum");
|
||||
substitutes.put("∏", "product");
|
||||
substitutes.put("∂", "derivative");
|
||||
substitutes.put("∫ab", "integral_ab");
|
||||
substitutes.put("∫", "integral");
|
||||
substitutes.put("Σ", "sum");
|
||||
}
|
||||
|
||||
public CalculatorOperatorsMathRegistry(@Nonnull MathRegistry<Operator> functionsRegistry,
|
||||
@Nonnull MathEntityDao<MathPersistenceEntity> mathEntityDao) {
|
||||
super(functionsRegistry, OPERATOR_DESCRIPTION_PREFIX, mathEntityDao);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Map<String, String> getSubstitutes() {
|
||||
return substitutes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory(@Nonnull Operator operator) {
|
||||
for (OperatorCategory category : OperatorCategory.values()) {
|
||||
if (category.isInCategory(operator)) {
|
||||
return category.name();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
// not supported yet
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected JBuilder<? extends Operator> createBuilder(@Nonnull MathPersistenceEntity entity) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
// not supported yet
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MathPersistenceEntity transform(@Nonnull Operator entity) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected MathEntityPersistenceContainer<MathPersistenceEntity> createPersistenceContainer() {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 7:29 PM
|
||||
*/
|
||||
public interface CalculatorOutput {
|
||||
|
||||
@Nonnull
|
||||
String getStringResult();
|
||||
|
||||
@Nonnull
|
||||
JsclOperation getOperation();
|
||||
|
||||
|
||||
// null in case of empty expression
|
||||
@Nullable
|
||||
Generic getResult();
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/20/12
|
||||
* Time: 7:28 PM
|
||||
*/
|
||||
public class CalculatorOutputImpl implements CalculatorOutput {
|
||||
|
||||
@Nullable
|
||||
private Generic result;
|
||||
|
||||
@Nonnull
|
||||
private String stringResult;
|
||||
|
||||
@Nonnull
|
||||
private JsclOperation operation;
|
||||
|
||||
private CalculatorOutputImpl(@Nonnull String stringResult,
|
||||
@Nonnull JsclOperation operation,
|
||||
@Nullable Generic result) {
|
||||
this.stringResult = stringResult;
|
||||
this.operation = operation;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorOutput newOutput(@Nonnull String stringResult,
|
||||
@Nonnull JsclOperation operation,
|
||||
@Nonnull Generic result) {
|
||||
return new CalculatorOutputImpl(stringResult, operation, result);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorOutput newEmptyOutput(@Nonnull JsclOperation operation) {
|
||||
return new CalculatorOutputImpl("", operation, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String getStringResult() {
|
||||
return stringResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public JsclOperation getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Generic getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageLevel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/6/11
|
||||
* Time: 9:25 PM
|
||||
*/
|
||||
public class CalculatorParseException extends Exception implements Message {
|
||||
|
||||
@Nonnull
|
||||
private final Message message;
|
||||
|
||||
@Nonnull
|
||||
private final String expression;
|
||||
|
||||
@Nullable
|
||||
private final Integer position;
|
||||
|
||||
public CalculatorParseException(@Nonnull jscl.text.ParseException jsclParseException) {
|
||||
this.message = jsclParseException;
|
||||
this.expression = jsclParseException.getExpression();
|
||||
this.position = jsclParseException.getPosition();
|
||||
}
|
||||
|
||||
public CalculatorParseException(@Nullable Integer position,
|
||||
@Nonnull String expression,
|
||||
@Nonnull Message message) {
|
||||
this.message = message;
|
||||
this.expression = expression;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public CalculatorParseException(@Nonnull String expression,
|
||||
@Nonnull Message message) {
|
||||
this(null, expression, message);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getMessageCode() {
|
||||
return this.message.getMessageCode();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<Object> getParameters() {
|
||||
return this.message.getParameters();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MessageLevel getMessageLevel() {
|
||||
return this.message.getMessageLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String getLocalizedMessage() {
|
||||
return this.message.getLocalizedMessage(Locale.getDefault());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getLocalizedMessage(@Nonnull Locale locale) {
|
||||
return this.message.getLocalizedMessage(locale);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.JBuilder;
|
||||
import org.solovyev.common.math.MathRegistry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.operator.Operator;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/19/11
|
||||
* Time: 1:48 PM
|
||||
*/
|
||||
public class CalculatorPostfixFunctionsRegistry extends AbstractCalculatorMathRegistry<Operator, MathPersistenceEntity> {
|
||||
|
||||
@Nonnull
|
||||
private static final Map<String, String> substitutes = new HashMap<String, String>();
|
||||
@Nonnull
|
||||
private static final String POSTFIX_FUNCTION_DESCRIPTION_PREFIX = "c_pf_description_";
|
||||
|
||||
static {
|
||||
substitutes.put("%", "percent");
|
||||
substitutes.put("!", "factorial");
|
||||
substitutes.put("!!", "double_factorial");
|
||||
substitutes.put("°", "degree");
|
||||
}
|
||||
|
||||
public CalculatorPostfixFunctionsRegistry(@Nonnull MathRegistry<Operator> functionsRegistry,
|
||||
@Nonnull MathEntityDao<MathPersistenceEntity> mathEntityDao) {
|
||||
super(functionsRegistry, POSTFIX_FUNCTION_DESCRIPTION_PREFIX, mathEntityDao);
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Map<String, String> getSubstitutes() {
|
||||
return substitutes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory(@Nonnull Operator operator) {
|
||||
for (OperatorCategory category : OperatorCategory.values()) {
|
||||
if (category.isInCategory(operator)) {
|
||||
return category.name();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
// not supported yet
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected JBuilder<? extends Operator> createBuilder(@Nonnull MathPersistenceEntity entity) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
// not supported yet
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MathPersistenceEntity transform(@Nonnull Operator entity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected MathEntityPersistenceContainer<MathPersistenceEntity> createPersistenceContainer() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.AngleUnit;
|
||||
import jscl.NumeralBase;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/17/12
|
||||
* Time: 7:45 PM
|
||||
*/
|
||||
public interface CalculatorPreferenceService {
|
||||
|
||||
void setPreferredAngleUnits();
|
||||
|
||||
void setAngleUnits(@Nonnull AngleUnit angleUnit);
|
||||
|
||||
void setPreferredNumeralBase();
|
||||
|
||||
void setNumeralBase(@Nonnull NumeralBase numeralBase);
|
||||
|
||||
void checkPreferredPreferences(boolean force);
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/20/12
|
||||
* Time: 2:05 PM
|
||||
*/
|
||||
public enum CalculatorSpecialButton {
|
||||
|
||||
history("history") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_history, null);
|
||||
}
|
||||
},
|
||||
history_detached("history_detached") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_history_detached, null);
|
||||
}
|
||||
},
|
||||
cursor_right("▷") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
keyboard.moveCursorRight();
|
||||
}
|
||||
},
|
||||
cursor_left("◁") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
keyboard.moveCursorLeft();
|
||||
}
|
||||
},
|
||||
settings("settings") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings, null);
|
||||
}
|
||||
},
|
||||
|
||||
settings_detached("settings_detached") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings_detached, null);
|
||||
}
|
||||
},
|
||||
|
||||
like("like") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_like_dialog, null);
|
||||
}
|
||||
},
|
||||
erase("erase") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getEditor().erase();
|
||||
}
|
||||
},
|
||||
paste("paste") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
keyboard.pasteButtonPressed();
|
||||
}
|
||||
},
|
||||
copy("copy") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
keyboard.copyButtonPressed();
|
||||
}
|
||||
},
|
||||
equals("=") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
final Calculator calculator = Locator.getInstance().getCalculator();
|
||||
if (!calculator.isCalculateOnFly()) {
|
||||
// no automatic calculations are => equals button must be used to calculate
|
||||
calculator.evaluate();
|
||||
return;
|
||||
}
|
||||
|
||||
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
|
||||
if (displayViewState.isValid()) {
|
||||
final CharSequence text = displayViewState.getText();
|
||||
if (!Strings.isEmpty(text)) {
|
||||
Locator.getInstance().getEditor().setText(text.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
clear("clear") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
keyboard.clearButtonPressed();
|
||||
}
|
||||
},
|
||||
functions("functions") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_functions, null);
|
||||
}
|
||||
},
|
||||
functions_detached("functions_detached") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_functions_detached, null);
|
||||
}
|
||||
},
|
||||
open_app("open_app") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.open_app, null);
|
||||
}
|
||||
},
|
||||
vars("vars") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_vars, null);
|
||||
}
|
||||
},
|
||||
vars_detached("vars_detached") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_vars_detached, null);
|
||||
}
|
||||
},
|
||||
operators("operators") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators, null);
|
||||
}
|
||||
},
|
||||
|
||||
operators_detached("operators_detached") {
|
||||
@Override
|
||||
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators_detached, null);
|
||||
}
|
||||
};
|
||||
|
||||
@Nonnull
|
||||
private static Map<String, CalculatorSpecialButton> buttonsByActionCodes = new HashMap<>();
|
||||
|
||||
@Nonnull
|
||||
private final String actionCode;
|
||||
|
||||
CalculatorSpecialButton(@Nonnull String actionCode) {
|
||||
this.actionCode = actionCode;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CalculatorSpecialButton getByActionCode(@Nonnull String actionCode) {
|
||||
initButtonsByActionCodesMap();
|
||||
return buttonsByActionCodes.get(actionCode);
|
||||
}
|
||||
|
||||
private static void initButtonsByActionCodesMap() {
|
||||
if (buttonsByActionCodes.isEmpty()) {
|
||||
// if not initialized
|
||||
|
||||
final CalculatorSpecialButton[] specialButtons = values();
|
||||
|
||||
final Map<String, CalculatorSpecialButton> localButtonsByActionCodes = new HashMap<String, CalculatorSpecialButton>(specialButtons.length);
|
||||
for (CalculatorSpecialButton specialButton : specialButtons) {
|
||||
localButtonsByActionCodes.put(specialButton.getActionCode(), specialButton);
|
||||
}
|
||||
|
||||
buttonsByActionCodes = localButtonsByActionCodes;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getActionCode() {
|
||||
return actionCode;
|
||||
}
|
||||
|
||||
public abstract void onClick(@Nonnull CalculatorKeyboard keyboard);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
import jscl.math.function.IConstant;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorEventData createFirstEventDataId() {
|
||||
return CalculatorEventDataImpl.newInstance(FIRST_ID, FIRST_ID);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Set<Constant> getNotSystemConstants(@Nonnull Generic expression) {
|
||||
final Set<Constant> notSystemConstants = new HashSet<Constant>();
|
||||
|
||||
for (Constant constant : expression.getConstants()) {
|
||||
IConstant var = Locator.getInstance().getEngine().getVarsRegistry().get(constant.getName());
|
||||
if (var != null && !var.isSystem() && !var.isDefined()) {
|
||||
notSystemConstants.add(constant);
|
||||
}
|
||||
}
|
||||
|
||||
return notSystemConstants;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.model.MathEntityBuilder;
|
||||
import org.solovyev.android.calculator.model.Var;
|
||||
import org.solovyev.android.calculator.model.Vars;
|
||||
import org.solovyev.common.JBuilder;
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
import org.solovyev.common.math.MathRegistry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.function.IConstant;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/29/11
|
||||
* Time: 4:57 PM
|
||||
*/
|
||||
public class CalculatorVarsRegistry extends AbstractCalculatorMathRegistry<IConstant, Var> {
|
||||
|
||||
@Nonnull
|
||||
public static final String ANS = "ans";
|
||||
|
||||
@Nonnull
|
||||
private static final Map<String, String> substitutes = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
substitutes.put("π", "pi");
|
||||
substitutes.put("Π", "PI");
|
||||
substitutes.put("∞", "inf");
|
||||
substitutes.put("h", "h_reduced");
|
||||
substitutes.put("NaN", "nan");
|
||||
}
|
||||
|
||||
public CalculatorVarsRegistry(@Nonnull MathRegistry<IConstant> mathRegistry,
|
||||
@Nonnull MathEntityDao<Var> mathEntityDao) {
|
||||
super(mathRegistry, "c_var_description_", mathEntityDao);
|
||||
}
|
||||
|
||||
public static <T extends MathEntity> void saveVariable(@Nonnull CalculatorMathRegistry<T> registry,
|
||||
@Nonnull MathEntityBuilder<? extends T> builder,
|
||||
@Nullable T editedInstance,
|
||||
@Nonnull Object source, boolean save) {
|
||||
final T addedVar = registry.add(builder);
|
||||
|
||||
if (save) {
|
||||
registry.save();
|
||||
}
|
||||
|
||||
if (editedInstance == null) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.constant_added, addedVar, source);
|
||||
} else {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.constant_changed, ChangeImpl.newInstance(editedInstance, addedVar), source);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Map<String, String> getSubstitutes() {
|
||||
return substitutes;
|
||||
}
|
||||
|
||||
public synchronized void load() {
|
||||
super.load();
|
||||
|
||||
tryToAddAuxVar("x");
|
||||
tryToAddAuxVar("y");
|
||||
tryToAddAuxVar("t");
|
||||
tryToAddAuxVar("j");
|
||||
|
||||
|
||||
/*Log.d(AndroidVarsRegistry.class.getName(), vars.size() + " variables registered!");
|
||||
for (Var var : vars) {
|
||||
Log.d(AndroidVarsRegistry.class.getName(), var.toString());
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected JBuilder<? extends IConstant> createBuilder(@Nonnull Var entity) {
|
||||
return new Var.Builder(entity);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected MathEntityPersistenceContainer<Var> createPersistenceContainer() {
|
||||
return new Vars();
|
||||
}
|
||||
|
||||
private void tryToAddAuxVar(@Nonnull String name) {
|
||||
if (!contains(name)) {
|
||||
add(new Var.Builder(name, (String) null));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Var transform(@Nonnull IConstant entity) {
|
||||
if (entity instanceof Var) {
|
||||
return (Var) entity;
|
||||
} else {
|
||||
return new Var.Builder(entity).create();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(@Nonnull String mathEntityName) {
|
||||
final IConstant var = get(mathEntityName);
|
||||
if (var != null && !var.isSystem()) {
|
||||
return var.getDescription();
|
||||
} else {
|
||||
return super.getDescription(mathEntityName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory(@Nonnull IConstant var) {
|
||||
for (VarCategory category : VarCategory.values()) {
|
||||
if (category.isInCategory(var)) {
|
||||
return category.name();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/1/12
|
||||
* Time: 11:16 PM
|
||||
*/
|
||||
public interface Change<T> {
|
||||
|
||||
@Nonnull
|
||||
T getOldValue();
|
||||
|
||||
@Nonnull
|
||||
T getNewValue();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/1/12
|
||||
* Time: 11:18 PM
|
||||
*/
|
||||
public class ChangeImpl<T> implements Change<T> {
|
||||
|
||||
@Nonnull
|
||||
private T oldValue;
|
||||
|
||||
@Nonnull
|
||||
private T newValue;
|
||||
|
||||
private ChangeImpl() {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static <T> Change<T> newInstance(@Nonnull T oldValue, @Nonnull T newValue) {
|
||||
final ChangeImpl<T> result = new ChangeImpl<T>();
|
||||
|
||||
result.oldValue = oldValue;
|
||||
result.newValue = newValue;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public T getOldValue() {
|
||||
return this.oldValue;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public T getNewValue() {
|
||||
return this.newValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 24.09.12
|
||||
* Time: 16:12
|
||||
*/
|
||||
public interface ConversionFailure {
|
||||
|
||||
@Nonnull
|
||||
Exception getException();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 24.09.12
|
||||
* Time: 16:12
|
||||
*/
|
||||
public class ConversionFailureImpl implements ConversionFailure {
|
||||
|
||||
@Nonnull
|
||||
private Exception exception;
|
||||
|
||||
public ConversionFailureImpl(@Nonnull Exception exception) {
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Exception getException() {
|
||||
return this.exception;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.MessageLevel;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/20/13
|
||||
* Time: 12:47 PM
|
||||
*/
|
||||
public interface DialogData {
|
||||
|
||||
@Nonnull
|
||||
String getMessage();
|
||||
|
||||
@Nonnull
|
||||
MessageLevel getMessageLevel();
|
||||
|
||||
@Nullable
|
||||
String getTitle();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 2:00 PM
|
||||
*/
|
||||
public class DummyCalculatorClipboard implements CalculatorClipboard {
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(@Nonnull CharSequence text) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(@Nonnull String text) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 2:00 PM
|
||||
*/
|
||||
public class DummyCalculatorNotifier implements CalculatorNotifier {
|
||||
|
||||
@Override
|
||||
public void showMessage(@Nonnull Message message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nonnull List<Object> parameters) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDebugMessage(@Nullable String tag, @Nonnull String message) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/17/11
|
||||
* Time: 9:37 PM
|
||||
*/
|
||||
public interface Editor {
|
||||
|
||||
@Nullable
|
||||
CharSequence getText();
|
||||
|
||||
void setText(@Nullable CharSequence text);
|
||||
|
||||
int getSelection();
|
||||
|
||||
void setSelection(int selection);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/2/12
|
||||
* Time: 10:21 PM
|
||||
*/
|
||||
public interface FixableError extends Serializable {
|
||||
|
||||
@Nullable
|
||||
CharSequence getFixCaption();
|
||||
|
||||
void fix();
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.collections.Collections;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.function.ArcTrigonometric;
|
||||
import jscl.math.function.Comparison;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.Trigonometric;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/7/12
|
||||
* Time: 7:15 PM
|
||||
*/
|
||||
public enum FunctionCategory {
|
||||
|
||||
trigonometric(100) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Function function) {
|
||||
return (function instanceof Trigonometric || function instanceof ArcTrigonometric) && !hyperbolic_trigonometric.isInCategory(function);
|
||||
}
|
||||
},
|
||||
|
||||
hyperbolic_trigonometric(300) {
|
||||
|
||||
private final List<String> names = Arrays.asList("sinh", "cosh", "tanh", "coth", "asinh", "acosh", "atanh", "acoth");
|
||||
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Function function) {
|
||||
return names.contains(function.getName());
|
||||
}
|
||||
},
|
||||
|
||||
comparison(200) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Function function) {
|
||||
return function instanceof Comparison;
|
||||
}
|
||||
},
|
||||
|
||||
my(0) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Function function) {
|
||||
return !function.isSystem();
|
||||
}
|
||||
},
|
||||
|
||||
common(50) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Function function) {
|
||||
for (FunctionCategory category : values()) {
|
||||
if (category != this) {
|
||||
if (category.isInCategory(function)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private final int tabOrder;
|
||||
|
||||
FunctionCategory(int tabOrder) {
|
||||
this.tabOrder = tabOrder;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static List<FunctionCategory> getCategoriesByTabOrder() {
|
||||
final List<FunctionCategory> result = Collections.asList(FunctionCategory.values());
|
||||
|
||||
java.util.Collections.sort(result, new Comparator<FunctionCategory>() {
|
||||
@Override
|
||||
public int compare(FunctionCategory category, FunctionCategory category1) {
|
||||
return category.tabOrder - category1.tabOrder;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract boolean isInCategory(@Nonnull Function function);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.listeners.JListeners;
|
||||
import org.solovyev.common.listeners.Listeners;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 16:42
|
||||
*/
|
||||
public class ListCalculatorEventContainer implements CalculatorEventContainer {
|
||||
|
||||
@Nonnull
|
||||
private static final String TAG = "CalculatorEventData";
|
||||
|
||||
@Nonnull
|
||||
private final JListeners<CalculatorEventListener> listeners = Listeners.newWeakRefListeners();
|
||||
|
||||
@Override
|
||||
public void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
|
||||
listeners.addListener(calculatorEventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
|
||||
listeners.removeListener(calculatorEventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
fireCalculatorEvents(Arrays.asList(new CalculatorEvent(calculatorEventData, calculatorEventType, data)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCalculatorEvents(@Nonnull List<CalculatorEvent> calculatorEvents) {
|
||||
final Collection<CalculatorEventListener> listeners = this.listeners.getListeners();
|
||||
|
||||
//final CalculatorLogger logger = Locator.getInstance().getLogger();
|
||||
|
||||
for (CalculatorEvent e : calculatorEvents) {
|
||||
//Locator.getInstance().getLogger().debug(TAG, "Event fired: " + e.getCalculatorEventType());
|
||||
for (CalculatorEventListener listener : listeners) {
|
||||
/*long startTime = System.currentTimeMillis();*/
|
||||
listener.onCalculatorEvent(e.getCalculatorEventData(), e.getCalculatorEventType(), e.getData());
|
||||
/* long endTime = System.currentTimeMillis();
|
||||
long totalTime = (endTime - startTime);
|
||||
if ( totalTime > 300 ) {
|
||||
logger.debug(TAG + "_" + e.getCalculatorEventData().getEventId(), "Started event: " + e.getCalculatorEventType() + " with data: " + e.getData() + " for: " + listener.getClass().getSimpleName());
|
||||
logger.debug(TAG + "_" + e.getCalculatorEventData().getEventId(), "Total time, ms: " + totalTime);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.NumeralBase;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/15/11
|
||||
* Time: 8:33 PM
|
||||
*/
|
||||
|
||||
public class LiteNumberBuilder extends AbstractNumberBuilder {
|
||||
|
||||
public LiteNumberBuilder(@Nonnull CalculatorEngine engine) {
|
||||
super(engine);
|
||||
this.nb = engine.getNumeralBase();
|
||||
}
|
||||
|
||||
public void process(@Nonnull MathType.Result mathTypeResult) {
|
||||
if (canContinue(mathTypeResult)) {
|
||||
// let's continue building number
|
||||
if (numberBuilder == null) {
|
||||
// if new number => create new builder
|
||||
numberBuilder = new StringBuilder();
|
||||
}
|
||||
|
||||
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
||||
// just add matching string
|
||||
numberBuilder.append(mathTypeResult.getMatch());
|
||||
} else {
|
||||
// set explicitly numeral base (do not include it into number)
|
||||
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
||||
}
|
||||
|
||||
} else {
|
||||
// process current number (and go to the next one)
|
||||
if (numberBuilder != null) {
|
||||
numberBuilder = null;
|
||||
|
||||
// must set default numeral base (exit numeral base mode)
|
||||
nb = engine.getNumeralBase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 12:45
|
||||
*/
|
||||
public class Locator implements CalculatorLocator {
|
||||
|
||||
@Nonnull
|
||||
private static final Locator instance = new Locator();
|
||||
@Nonnull
|
||||
private CalculatorEngine calculatorEngine;
|
||||
@Nonnull
|
||||
private Calculator calculator;
|
||||
@Nonnull
|
||||
private CalculatorEditor calculatorEditor;
|
||||
@Nonnull
|
||||
private CalculatorDisplay calculatorDisplay;
|
||||
@Nonnull
|
||||
private CalculatorKeyboard calculatorKeyboard;
|
||||
@Nonnull
|
||||
private CalculatorHistory calculatorHistory;
|
||||
@Nonnull
|
||||
private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier();
|
||||
@Nonnull
|
||||
private CalculatorLogger calculatorLogger = new SystemOutCalculatorLogger();
|
||||
@Nonnull
|
||||
private CalculatorClipboard calculatorClipboard = new DummyCalculatorClipboard();
|
||||
@Nonnull
|
||||
private CalculatorPreferenceService calculatorPreferenceService;
|
||||
|
||||
@Nonnull
|
||||
private CalculatorPlotter calculatorPlotter;
|
||||
|
||||
public Locator() {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorLocator getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(@Nonnull Calculator calculator,
|
||||
@Nonnull CalculatorEngine engine,
|
||||
@Nonnull CalculatorClipboard clipboard,
|
||||
@Nonnull CalculatorNotifier notifier,
|
||||
@Nonnull CalculatorHistory history,
|
||||
@Nonnull CalculatorLogger logger,
|
||||
@Nonnull CalculatorPreferenceService preferenceService,
|
||||
@Nonnull CalculatorKeyboard keyboard,
|
||||
@Nonnull CalculatorPlotter plotter,
|
||||
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor) {
|
||||
|
||||
this.calculator = calculator;
|
||||
this.calculatorEngine = engine;
|
||||
this.calculatorClipboard = clipboard;
|
||||
this.calculatorNotifier = notifier;
|
||||
this.calculatorHistory = history;
|
||||
this.calculatorLogger = logger;
|
||||
this.calculatorPreferenceService = preferenceService;
|
||||
this.calculatorPlotter = plotter;
|
||||
|
||||
calculatorEditor = new CalculatorEditorImpl(this.calculator, editorTextProcessor);
|
||||
calculatorDisplay = new CalculatorDisplayImpl(this.calculator);
|
||||
calculatorKeyboard = keyboard;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEngine getEngine() {
|
||||
return calculatorEngine;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Calculator getCalculator() {
|
||||
return this.calculator;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public CalculatorDisplay getDisplay() {
|
||||
return calculatorDisplay;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorEditor getEditor() {
|
||||
return calculatorEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public CalculatorKeyboard getKeyboard() {
|
||||
return calculatorKeyboard;
|
||||
}
|
||||
|
||||
public static void setKeyboard(@Nonnull CalculatorKeyboard keyboard) {
|
||||
instance.calculatorKeyboard = keyboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public CalculatorClipboard getClipboard() {
|
||||
return calculatorClipboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public CalculatorNotifier getNotifier() {
|
||||
return calculatorNotifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public CalculatorHistory getHistory() {
|
||||
return calculatorHistory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public CalculatorLogger getLogger() {
|
||||
return calculatorLogger;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorPlotter getPlotter() {
|
||||
return calculatorPlotter;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CalculatorPreferenceService getPreferenceService() {
|
||||
return this.calculatorPreferenceService;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/7/12
|
||||
* Time: 6:43 PM
|
||||
*/
|
||||
public interface MathEntityDao<T extends MathPersistenceEntity> {
|
||||
|
||||
void save(@Nonnull MathEntityPersistenceContainer<T> container);
|
||||
|
||||
@Nullable
|
||||
MathEntityPersistenceContainer<T> load();
|
||||
|
||||
@Nullable
|
||||
String getDescription(@Nonnull String descriptionId);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/22/11
|
||||
* Time: 5:03 PM
|
||||
*/
|
||||
public interface MathEntityPersistenceContainer<T extends MathPersistenceEntity> {
|
||||
|
||||
public List<T> getEntities();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/22/11
|
||||
* Time: 5:27 PM
|
||||
*/
|
||||
public interface MathPersistenceEntity {
|
||||
|
||||
@Nonnull
|
||||
String getName();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageLevel;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/20/13
|
||||
* Time: 12:45 PM
|
||||
*/
|
||||
public class MessageDialogData implements DialogData {
|
||||
|
||||
@Nonnull
|
||||
private Message message;
|
||||
|
||||
@Nullable
|
||||
private String title;
|
||||
|
||||
private MessageDialogData(@Nonnull Message message, @Nullable String title) {
|
||||
this.message = message;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static DialogData newInstance(@Nonnull Message message, @Nullable String title) {
|
||||
return new MessageDialogData(message, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String getMessage() {
|
||||
return message.getLocalizedMessage();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MessageLevel getMessageLevel() {
|
||||
return message.getMessageLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.common.MutableObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.MathContext;
|
||||
import jscl.MathEngine;
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.numeric.Real;
|
||||
import jscl.text.DoubleParser;
|
||||
import jscl.text.JsclIntegerParser;
|
||||
import jscl.text.MutableInt;
|
||||
import jscl.text.ParseException;
|
||||
import jscl.text.Parser;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/23/11
|
||||
* Time: 2:57 PM
|
||||
*/
|
||||
public class NumberBuilder extends AbstractNumberBuilder {
|
||||
|
||||
public NumberBuilder(@Nonnull CalculatorEngine engine) {
|
||||
super(engine);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static MathType.Result replaceNumberInText(@Nonnull StringBuilder text,
|
||||
@Nullable String number,
|
||||
int trimmedChars,
|
||||
@Nullable MutableObject<Integer> offset,
|
||||
@Nonnull NumeralBase nb,
|
||||
@Nonnull final MathEngine engine) {
|
||||
MathType.Result result = null;
|
||||
|
||||
if (number != null) {
|
||||
// in any case remove old number from text
|
||||
final int oldNumberLength = number.length() + trimmedChars;
|
||||
text.delete(text.length() - oldNumberLength, text.length());
|
||||
|
||||
final String newNumber = formatNumber(number, nb, engine);
|
||||
if (offset != null) {
|
||||
// register offset between old number and new number
|
||||
offset.setObject(newNumber.length() - oldNumberLength);
|
||||
}
|
||||
text.append(newNumber);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static String formatNumber(@Nonnull String number, @Nonnull NumeralBase nb, @Nonnull MathEngine engine) {
|
||||
String result;
|
||||
|
||||
int indexOfDot = number.indexOf('.');
|
||||
|
||||
if (indexOfDot < 0) {
|
||||
int indexOfE;
|
||||
if (nb == NumeralBase.hex) {
|
||||
indexOfE = -1;
|
||||
} else {
|
||||
indexOfE = number.indexOf(MathType.POWER_10);
|
||||
}
|
||||
if (indexOfE < 0) {
|
||||
result = engine.addGroupingSeparators(nb, number);
|
||||
} else {
|
||||
final String partBeforeE;
|
||||
if (indexOfE != 0) {
|
||||
partBeforeE = engine.addGroupingSeparators(nb, number.substring(0, indexOfE));
|
||||
} else {
|
||||
partBeforeE = "";
|
||||
}
|
||||
result = partBeforeE + number.substring(indexOfE);
|
||||
}
|
||||
} else {
|
||||
final String integerPart;
|
||||
if (indexOfDot != 0) {
|
||||
integerPart = engine.addGroupingSeparators(nb, number.substring(0, indexOfDot));
|
||||
} else {
|
||||
integerPart = "";
|
||||
}
|
||||
result = integerPart + number.substring(indexOfDot);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static Double toDouble(@Nonnull String s, @Nonnull NumeralBase nb, @Nonnull final MathContext mc) throws NumberFormatException {
|
||||
final NumeralBase defaultNb = mc.getNumeralBase();
|
||||
try {
|
||||
mc.setNumeralBase(nb);
|
||||
|
||||
try {
|
||||
return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content().doubleValue();
|
||||
} catch (ParseException e) {
|
||||
try {
|
||||
return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content()).doubleValue();
|
||||
} catch (ParseException e1) {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
mc.setNumeralBase(defaultNb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method replaces number in text according to some rules (e.g. formatting)
|
||||
*
|
||||
* @param text text where number can be replaced
|
||||
* @param mathTypeResult math type result of current token
|
||||
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
||||
* @return new math type result (as one can be changed due to substituting of number with constant)
|
||||
*/
|
||||
@Nonnull
|
||||
public MathType.Result process(@Nonnull StringBuilder text, @Nonnull MathType.Result mathTypeResult, @Nullable MutableObject<Integer> offset) {
|
||||
final MathType.Result possibleResult;
|
||||
if (canContinue(mathTypeResult)) {
|
||||
// let's continue building number
|
||||
if (numberBuilder == null) {
|
||||
// if new number => create new builder
|
||||
numberBuilder = new StringBuilder();
|
||||
}
|
||||
|
||||
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
||||
// just add matching string
|
||||
numberBuilder.append(mathTypeResult.getMatch());
|
||||
} else {
|
||||
// set explicitly numeral base (do not include it into number)
|
||||
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
||||
}
|
||||
|
||||
possibleResult = null;
|
||||
} else {
|
||||
// process current number (and go to the next one)
|
||||
possibleResult = processNumber(text, offset);
|
||||
}
|
||||
|
||||
return possibleResult == null ? mathTypeResult : possibleResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method replaces number in text according to some rules (e.g. formatting)
|
||||
*
|
||||
* @param text text where number can be replaced
|
||||
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
||||
* @return new math type result (as one can be changed due to substituting of number with constant)
|
||||
*/
|
||||
@Nullable
|
||||
public MathType.Result processNumber(@Nonnull StringBuilder text, @Nullable MutableObject<Integer> offset) {
|
||||
// total number of trimmed chars
|
||||
int trimmedChars = 0;
|
||||
|
||||
String number = null;
|
||||
|
||||
// toXml numeral base (as later it might be replaced)
|
||||
final NumeralBase localNb = getNumeralBase();
|
||||
|
||||
if (numberBuilder != null) {
|
||||
try {
|
||||
number = numberBuilder.toString();
|
||||
|
||||
// let's get rid of unnecessary characters (grouping separators, + after E)
|
||||
final List<String> tokens = new ArrayList<String>();
|
||||
tokens.addAll(MathType.grouping_separator.getTokens());
|
||||
// + after E can be omitted: 10+E = 10E (NOTE: - cannot be omitted )
|
||||
tokens.add("+");
|
||||
for (String groupingSeparator : tokens) {
|
||||
final String trimmedNumber = number.replace(groupingSeparator, "");
|
||||
trimmedChars += number.length() - trimmedNumber.length();
|
||||
number = trimmedNumber;
|
||||
}
|
||||
|
||||
// check if number still valid
|
||||
toDouble(number, getNumeralBase(), engine.getMathEngine0());
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
// number is not valid => stop
|
||||
number = null;
|
||||
}
|
||||
|
||||
numberBuilder = null;
|
||||
|
||||
// must set default numeral base (exit numeral base mode)
|
||||
nb = engine.getNumeralBase();
|
||||
}
|
||||
|
||||
return replaceNumberInText(text, number, trimmedChars, offset, localNb, engine.getMathEngine0());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.collections.Collections;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.operator.Derivative;
|
||||
import jscl.math.operator.IndefiniteIntegral;
|
||||
import jscl.math.operator.Integral;
|
||||
import jscl.math.operator.Operator;
|
||||
import jscl.math.operator.Product;
|
||||
import jscl.math.operator.Sum;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/7/12
|
||||
* Time: 7:40 PM
|
||||
*/
|
||||
public enum OperatorCategory {
|
||||
|
||||
derivatives(100) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Operator operator) {
|
||||
return operator instanceof Derivative || operator instanceof Integral || operator instanceof IndefiniteIntegral;
|
||||
}
|
||||
},
|
||||
|
||||
other(200) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Operator operator) {
|
||||
return operator instanceof Sum || operator instanceof Product;
|
||||
}
|
||||
},
|
||||
|
||||
my(0) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Operator operator) {
|
||||
return !operator.isSystem();
|
||||
}
|
||||
},
|
||||
|
||||
common(50) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull Operator operator) {
|
||||
for (OperatorCategory category : values()) {
|
||||
if (category != this) {
|
||||
if (category.isInCategory(operator)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private final int tabOrder;
|
||||
|
||||
OperatorCategory(int tabOrder) {
|
||||
this.tabOrder = tabOrder;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static List<OperatorCategory> getCategoriesByTabOrder() {
|
||||
final List<OperatorCategory> result = Collections.asList(OperatorCategory.values());
|
||||
|
||||
java.util.Collections.sort(result, new Comparator<OperatorCategory>() {
|
||||
@Override
|
||||
public int compare(OperatorCategory category, OperatorCategory category1) {
|
||||
return category.tabOrder - category1.tabOrder;
|
||||
}
|
||||
});
|
||||
|
||||
// todo serso: current solution (as creating operators is not implemented yet)
|
||||
result.remove(my);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract boolean isInCategory(@Nonnull Operator operator);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.function.IConstant;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/18/11
|
||||
* Time: 10:07 PM
|
||||
*/
|
||||
public class PreparedExpression implements CharSequence {
|
||||
|
||||
@Nonnull
|
||||
private String expression;
|
||||
|
||||
@Nonnull
|
||||
private List<IConstant> undefinedVars;
|
||||
|
||||
public PreparedExpression(@Nonnull String expression, @Nonnull List<IConstant> undefinedVars) {
|
||||
this.expression = expression;
|
||||
this.undefinedVars = undefinedVars;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
public boolean isExistsUndefinedVar() {
|
||||
return !this.undefinedVars.isEmpty();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<IConstant> getUndefinedVars() {
|
||||
return undefinedVars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return expression.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int i) {
|
||||
return expression.charAt(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int i, int i1) {
|
||||
return expression.subSequence(i, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.expression;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/20/13
|
||||
* Time: 1:01 PM
|
||||
*/
|
||||
public class StringDialogData implements DialogData {
|
||||
|
||||
@Nonnull
|
||||
private final String message;
|
||||
|
||||
@Nonnull
|
||||
private final MessageType messageType;
|
||||
|
||||
@Nullable
|
||||
private final String title;
|
||||
|
||||
private StringDialogData(@Nonnull String message, @Nonnull MessageType messageType, @Nullable String title) {
|
||||
this.message = message;
|
||||
this.messageType = messageType;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static DialogData newInstance(@Nonnull String message, @Nonnull MessageType messageType, @Nullable String title) {
|
||||
return new StringDialogData(message, messageType, title);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MessageType getMessageLevel() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/11/12
|
||||
* Time: 12:12 AM
|
||||
*/
|
||||
public class SystemOutCalculatorLogger implements CalculatorLogger {
|
||||
|
||||
@Nonnull
|
||||
private static final String TAG = SystemOutCalculatorLogger.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable String tag, @Nullable String message) {
|
||||
System.out.println(getTag(tag) + ": " + message);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private String getTag(@Nullable String tag) {
|
||||
return tag != null ? tag : TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable String tag, @Nullable String message, @Nonnull Throwable e) {
|
||||
debug(tag, message);
|
||||
e.printStackTrace(System.out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@Nullable String tag, @Nullable String message, @Nonnull Throwable e) {
|
||||
System.out.println(getTag(tag) + ": " + message);
|
||||
e.printStackTrace(System.out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@Nullable String tag, @Nullable String message) {
|
||||
System.out.println(getTag(tag) + ": " + message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
import org.solovyev.common.collections.Collections;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
import org.solovyev.common.search.StartsWithFinder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IConstant;
|
||||
|
||||
public class ToJsclTextProcessor implements TextProcessor<PreparedExpression, String> {
|
||||
|
||||
@Nonnull
|
||||
private static final Integer MAX_DEPTH = 20;
|
||||
|
||||
@Nonnull
|
||||
private static final TextProcessor<PreparedExpression, String> instance = new ToJsclTextProcessor();
|
||||
|
||||
private ToJsclTextProcessor() {
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
public static TextProcessor<PreparedExpression, String> getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static PreparedExpression processWithDepth(@Nonnull String s, int depth, @Nonnull List<IConstant> undefinedVars) throws CalculatorParseException {
|
||||
return replaceVariables(processExpression(s).toString(), depth, undefinedVars);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static StringBuilder processExpression(@Nonnull String s) throws CalculatorParseException {
|
||||
final StartsWithFinder startsWithFinder = StartsWithFinder.newInstance(s);
|
||||
final StringBuilder result = new StringBuilder();
|
||||
|
||||
MathType.Result mathTypeResult = null;
|
||||
MathType.Result mathTypeBefore;
|
||||
|
||||
final LiteNumberBuilder nb = new LiteNumberBuilder(Locator.getInstance().getEngine());
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (s.charAt(i) == ' ') continue;
|
||||
startsWithFinder.setI(i);
|
||||
|
||||
mathTypeBefore = mathTypeResult == null ? null : mathTypeResult;
|
||||
|
||||
mathTypeResult = MathType.getType(s, i, nb.isHexMode());
|
||||
|
||||
nb.process(mathTypeResult);
|
||||
|
||||
if (mathTypeBefore != null) {
|
||||
|
||||
final MathType current = mathTypeResult.getMathType();
|
||||
|
||||
if (current.isNeedMultiplicationSignBefore(mathTypeBefore.getMathType())) {
|
||||
result.append("*");
|
||||
}
|
||||
}
|
||||
|
||||
if (mathTypeBefore != null &&
|
||||
(mathTypeBefore.getMathType() == MathType.function || mathTypeBefore.getMathType() == MathType.operator) &&
|
||||
Collections.find(MathType.openGroupSymbols, startsWithFinder) != null) {
|
||||
final String functionName = mathTypeBefore.getMatch();
|
||||
final Function function = Locator.getInstance().getEngine().getFunctionsRegistry().get(functionName);
|
||||
if (function == null || function.getMinParameters() > 0) {
|
||||
throw new CalculatorParseException(i, s, new CalculatorMessage(CalculatorMessages.msg_005, MessageType.error, mathTypeBefore.getMatch()));
|
||||
}
|
||||
}
|
||||
|
||||
i = mathTypeResult.processToJscl(result, i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static PreparedExpression replaceVariables(@Nonnull final String s, int depth, @Nonnull List<IConstant> undefinedVars) throws CalculatorParseException {
|
||||
if (depth >= MAX_DEPTH) {
|
||||
throw new CalculatorParseException(s, new CalculatorMessage(CalculatorMessages.msg_006, MessageType.error));
|
||||
} else {
|
||||
depth++;
|
||||
}
|
||||
|
||||
final StartsWithFinder startsWithFinder = StartsWithFinder.newInstance(s);
|
||||
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
startsWithFinder.setI(i);
|
||||
|
||||
int offset = 0;
|
||||
String functionName = Collections.find(MathType.function.getTokens(), startsWithFinder);
|
||||
if (functionName == null) {
|
||||
String operatorName = Collections.find(MathType.operator.getTokens(), startsWithFinder);
|
||||
if (operatorName == null) {
|
||||
String varName = Collections.find(Locator.getInstance().getEngine().getVarsRegistry().getNames(), startsWithFinder);
|
||||
if (varName != null) {
|
||||
final IConstant var = Locator.getInstance().getEngine().getVarsRegistry().get(varName);
|
||||
if (var != null) {
|
||||
if (!var.isDefined()) {
|
||||
undefinedVars.add(var);
|
||||
result.append(varName);
|
||||
offset = varName.length();
|
||||
} else {
|
||||
final String value = var.getValue();
|
||||
if (value == null) throw new AssertionError();
|
||||
|
||||
if (var.getDoubleValue() != null) {
|
||||
//result.append(value);
|
||||
// NOTE: append varName as JSCL engine will convert it to double if needed
|
||||
result.append(varName);
|
||||
} else {
|
||||
result.append("(").append(processWithDepth(value, depth, undefinedVars)).append(")");
|
||||
}
|
||||
offset = varName.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.append(operatorName);
|
||||
offset = operatorName.length();
|
||||
}
|
||||
} else {
|
||||
result.append(functionName);
|
||||
offset = functionName.length();
|
||||
}
|
||||
|
||||
|
||||
if (offset == 0) {
|
||||
result.append(s.charAt(i));
|
||||
} else {
|
||||
i += offset - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return new PreparedExpression(result.toString(), undefinedVars);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public PreparedExpression process(@Nonnull String s) throws CalculatorParseException {
|
||||
return processWithDepth(s, 0, new ArrayList<IConstant>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.solovyev.common.collections.Collections;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.function.IConstant;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/22/11
|
||||
* Time: 4:25 PM
|
||||
*/
|
||||
public enum VarCategory {
|
||||
|
||||
system(100) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull IConstant var) {
|
||||
return var.isSystem();
|
||||
}
|
||||
},
|
||||
|
||||
my(0) {
|
||||
@Override
|
||||
public boolean isInCategory(@Nonnull IConstant var) {
|
||||
return !var.isSystem();
|
||||
}
|
||||
};
|
||||
|
||||
private final int tabOrder;
|
||||
|
||||
VarCategory(int tabOrder) {
|
||||
this.tabOrder = tabOrder;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static List<VarCategory> getCategoriesByTabOrder() {
|
||||
final List<VarCategory> result = Collections.asList(VarCategory.values());
|
||||
|
||||
java.util.Collections.sort(result, new Comparator<VarCategory>() {
|
||||
@Override
|
||||
public int compare(VarCategory category, VarCategory category1) {
|
||||
return category.tabOrder - category1.tabOrder;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract boolean isInCategory(@Nonnull IConstant var);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.function;
|
||||
|
||||
import org.solovyev.android.calculator.model.AFunction;
|
||||
import org.solovyev.android.calculator.model.MathEntityBuilder;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.CustomFunctionCalculationException;
|
||||
import jscl.math.function.CustomFunction;
|
||||
import jscl.math.function.Function;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/20/13
|
||||
* Time: 12:21 PM
|
||||
*/
|
||||
public final class FunctionBuilderAdapter implements MathEntityBuilder<Function> {
|
||||
|
||||
@Nonnull
|
||||
private final AFunction.Builder nestedBuilder;
|
||||
|
||||
public FunctionBuilderAdapter(@Nonnull AFunction.Builder nestedBuilder) {
|
||||
this.nestedBuilder = nestedBuilder;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setName(@Nonnull String name) {
|
||||
nestedBuilder.setName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setDescription(@Nullable String description) {
|
||||
nestedBuilder.setDescription(description);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setValue(@Nullable String value) {
|
||||
nestedBuilder.setValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Function create() throws CustomFunctionCalculationException, AFunction.Builder.CreationException {
|
||||
final AFunction function = nestedBuilder.create();
|
||||
return new CustomFunction.Builder(function).create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.Transient;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/15/11
|
||||
* Time: 1:45 PM
|
||||
*/
|
||||
public class AbstractHistoryState implements Cloneable {
|
||||
|
||||
@Element
|
||||
private long time = new Date().getTime();
|
||||
|
||||
@Element(required = false)
|
||||
@Nullable
|
||||
private String comment;
|
||||
|
||||
@Transient
|
||||
private boolean saved;
|
||||
|
||||
@Transient
|
||||
private int id = 0;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void setComment(@Nullable String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public boolean isSaved() {
|
||||
return saved;
|
||||
}
|
||||
|
||||
public void setSaved(boolean saved) {
|
||||
this.saved = saved;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractHistoryState clone() {
|
||||
AbstractHistoryState clone;
|
||||
|
||||
try {
|
||||
clone = (AbstractHistoryState) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.Root;
|
||||
import org.simpleframework.xml.Transient;
|
||||
import org.solovyev.android.calculator.CalculatorDisplay;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayViewState;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/17/11
|
||||
* Time: 11:05 PM
|
||||
*/
|
||||
|
||||
@Root
|
||||
public class CalculatorDisplayHistoryState implements Cloneable {
|
||||
|
||||
@Transient
|
||||
private boolean valid = true;
|
||||
|
||||
@Transient
|
||||
@Nullable
|
||||
private String errorMessage = null;
|
||||
|
||||
@Element
|
||||
@Nonnull
|
||||
private EditorHistoryState editorState;
|
||||
|
||||
@Element
|
||||
@Nonnull
|
||||
private JsclOperation jsclOperation;
|
||||
|
||||
@Transient
|
||||
@Nullable
|
||||
private Generic genericResult;
|
||||
|
||||
private CalculatorDisplayHistoryState() {
|
||||
// for xml
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorDisplayHistoryState newInstance(@Nonnull CalculatorDisplayViewState viewState) {
|
||||
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
|
||||
|
||||
result.editorState = EditorHistoryState.newInstance(viewState);
|
||||
|
||||
result.valid = viewState.isValid();
|
||||
result.jsclOperation = viewState.getOperation();
|
||||
result.genericResult = viewState.getResult();
|
||||
result.errorMessage = viewState.getErrorMessage();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setValuesFromHistory(@Nonnull CalculatorDisplay display) {
|
||||
if (this.isValid()) {
|
||||
display.setViewState(CalculatorDisplayViewStateImpl.newValidState(this.getJsclOperation(), this.getGenericResult(), Strings.getNotEmpty(this.getEditorState().getText(), ""), this.getEditorState().getCursorPosition()));
|
||||
} else {
|
||||
display.setViewState(CalculatorDisplayViewStateImpl.newErrorState(this.getJsclOperation(), Strings.getNotEmpty(this.getErrorMessage(), "")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public EditorHistoryState getEditorState() {
|
||||
return editorState;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public JsclOperation getJsclOperation() {
|
||||
return jsclOperation;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Generic getGenericResult() {
|
||||
return genericResult;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
CalculatorDisplayHistoryState that = (CalculatorDisplayHistoryState) o;
|
||||
|
||||
if (!editorState.equals(that.editorState)) return false;
|
||||
if (jsclOperation != that.jsclOperation) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = editorState.hashCode();
|
||||
result = 31 * result + jsclOperation.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CalculatorDisplayHistoryState{" +
|
||||
"valid=" + valid +
|
||||
", errorMessage='" + errorMessage + '\'' +
|
||||
", editorHistoryState=" + editorState +
|
||||
", jsclOperation=" + jsclOperation +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CalculatorDisplayHistoryState clone() {
|
||||
try {
|
||||
final CalculatorDisplayHistoryState clone = (CalculatorDisplayHistoryState) super.clone();
|
||||
|
||||
clone.editorState = this.editorState.clone();
|
||||
|
||||
return clone;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import org.solovyev.android.calculator.CalculatorEventListener;
|
||||
import org.solovyev.common.history.HistoryHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 20.09.12
|
||||
* Time: 16:11
|
||||
*/
|
||||
public interface CalculatorHistory extends HistoryHelper<CalculatorHistoryState>, CalculatorEventListener {
|
||||
|
||||
void load();
|
||||
|
||||
void save();
|
||||
|
||||
void fromXml(@Nonnull String xml);
|
||||
|
||||
String toXml();
|
||||
|
||||
void clearSavedHistory();
|
||||
|
||||
void removeSavedHistory(@Nonnull CalculatorHistoryState historyState);
|
||||
|
||||
@Nonnull
|
||||
List<CalculatorHistoryState> getSavedHistory();
|
||||
|
||||
@Nonnull
|
||||
CalculatorHistoryState addSavedState(@Nonnull CalculatorHistoryState historyState);
|
||||
|
||||
@Nonnull
|
||||
List<CalculatorHistoryState> getStates();
|
||||
|
||||
@Nonnull
|
||||
List<CalculatorHistoryState> getStates(boolean includeIntermediateStates);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import org.solovyev.android.calculator.Calculator;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayChangeEventData;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayViewState;
|
||||
import org.solovyev.android.calculator.CalculatorEditorChangeEventData;
|
||||
import org.solovyev.android.calculator.CalculatorEditorViewState;
|
||||
import org.solovyev.android.calculator.CalculatorEventData;
|
||||
import org.solovyev.android.calculator.CalculatorEventHolder;
|
||||
import org.solovyev.android.calculator.CalculatorEventType;
|
||||
import org.solovyev.android.calculator.CalculatorUtils;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
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.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
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);
|
||||
|
||||
@Nonnull
|
||||
private final HistoryHelper<CalculatorHistoryState> history = SimpleHistoryHelper.newInstance();
|
||||
|
||||
@Nonnull
|
||||
private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState>();
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorEventHolder lastEventData = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
|
||||
|
||||
@Nullable
|
||||
private volatile CalculatorEditorViewState lastEditorViewState;
|
||||
|
||||
public CalculatorHistoryImpl(@Nonnull 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(@Nonnull HistoryAction historyAction) {
|
||||
synchronized (history) {
|
||||
return history.isActionAvailable(historyAction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorHistoryState doAction(@Nonnull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
|
||||
synchronized (history) {
|
||||
return history.doAction(historyAction, currentState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addState(@Nullable CalculatorHistoryState currentState) {
|
||||
synchronized (history) {
|
||||
history.addState(currentState);
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, currentState);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<CalculatorHistoryState> getStates() {
|
||||
synchronized (history) {
|
||||
return history.getStates();
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<CalculatorHistoryState> getStates(boolean includeIntermediateStates) {
|
||||
synchronized (history) {
|
||||
if (includeIntermediateStates) {
|
||||
return getStates();
|
||||
} else {
|
||||
final List<CalculatorHistoryState> states = getStates();
|
||||
|
||||
final List<CalculatorHistoryState> result = new LinkedList<CalculatorHistoryState>();
|
||||
|
||||
CalculatorHistoryState laterState = null;
|
||||
for (CalculatorHistoryState state : org.solovyev.common.collections.Collections.reversed(states)) {
|
||||
if (laterState != null) {
|
||||
final String laterEditorText = laterState.getEditorState().getText();
|
||||
final String editorText = state.getEditorState().getText();
|
||||
if (laterEditorText != null && editorText != null && isIntermediate(laterEditorText, editorText)) {
|
||||
// intermediate result => skip from add
|
||||
} else {
|
||||
result.add(0, state);
|
||||
}
|
||||
} else {
|
||||
result.add(0, state);
|
||||
}
|
||||
|
||||
laterState = state;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isIntermediate(@Nonnull String laterEditorText,
|
||||
@Nonnull String editorText) {
|
||||
if (Math.abs(laterEditorText.length() - editorText.length()) <= 1) {
|
||||
if (laterEditorText.length() > editorText.length()) {
|
||||
return laterEditorText.startsWith(editorText);
|
||||
} else {
|
||||
return editorText.startsWith(laterEditorText);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
synchronized (history) {
|
||||
this.history.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public List<CalculatorHistoryState> getSavedHistory() {
|
||||
return Collections.unmodifiableList(savedHistory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public CalculatorHistoryState addSavedState(@Nonnull 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(@Nonnull 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(@Nonnull CalculatorHistoryState historyState) {
|
||||
this.savedHistory.remove(historyState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
|
||||
@Nonnull CalculatorEventType calculatorEventType,
|
||||
@Nullable Object data) {
|
||||
if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) {
|
||||
|
||||
final CalculatorEventHolder.Result result = lastEventData.apply(calculatorEventData);
|
||||
|
||||
if (result.isNewAfter() && result.isNewSameOrAfterSequence()) {
|
||||
switch (calculatorEventType) {
|
||||
case manual_calculation_requested:
|
||||
lastEditorViewState = (CalculatorEditorViewState) data;
|
||||
break;
|
||||
case editor_state_changed:
|
||||
final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data;
|
||||
lastEditorViewState = editorChangeData.getNewValue();
|
||||
break;
|
||||
case display_state_changed:
|
||||
if (result.isSameSequence()) {
|
||||
if (lastEditorViewState != null) {
|
||||
final CalculatorEditorViewState editorViewState = lastEditorViewState;
|
||||
final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data;
|
||||
final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue();
|
||||
addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState));
|
||||
}
|
||||
} else {
|
||||
lastEditorViewState = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.Root;
|
||||
import org.solovyev.android.calculator.CalculatorDisplay;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayViewState;
|
||||
import org.solovyev.android.calculator.CalculatorEditor;
|
||||
import org.solovyev.android.calculator.CalculatorEditorViewState;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/11/11
|
||||
* Time: 12:16 AM
|
||||
*/
|
||||
|
||||
@Root
|
||||
public class CalculatorHistoryState extends AbstractHistoryState {
|
||||
|
||||
@Element
|
||||
@Nonnull
|
||||
private EditorHistoryState editorState;
|
||||
|
||||
@Element
|
||||
@Nonnull
|
||||
private CalculatorDisplayHistoryState displayState;
|
||||
|
||||
private CalculatorHistoryState() {
|
||||
// for xml
|
||||
}
|
||||
|
||||
private CalculatorHistoryState(@Nonnull EditorHistoryState editorState,
|
||||
@Nonnull CalculatorDisplayHistoryState displayState) {
|
||||
this.editorState = editorState;
|
||||
this.displayState = displayState;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditor editor,
|
||||
@Nonnull CalculatorDisplay display) {
|
||||
final CalculatorEditorViewState editorViewState = editor.getViewState();
|
||||
final CalculatorDisplayViewState displayViewState = display.getViewState();
|
||||
|
||||
return newInstance(editorViewState, displayViewState);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditorViewState editorViewState,
|
||||
@Nonnull CalculatorDisplayViewState displayViewState) {
|
||||
final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editorViewState);
|
||||
|
||||
final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(displayViewState);
|
||||
|
||||
return new CalculatorHistoryState(editorHistoryState, displayHistoryState);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public EditorHistoryState getEditorState() {
|
||||
return editorState;
|
||||
}
|
||||
|
||||
public void setEditorState(@Nonnull EditorHistoryState editorState) {
|
||||
this.editorState = editorState;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public CalculatorDisplayHistoryState getDisplayState() {
|
||||
return displayState;
|
||||
}
|
||||
|
||||
public void setDisplayState(@Nonnull CalculatorDisplayHistoryState displayState) {
|
||||
this.displayState = displayState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CalculatorHistoryState{" +
|
||||
"editorState=" + editorState +
|
||||
", displayState=" + displayState +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
CalculatorHistoryState that = (CalculatorHistoryState) o;
|
||||
|
||||
if (this.isSaved() != that.isSaved()) return false;
|
||||
if (this.getId() != that.getId()) return false;
|
||||
if (!displayState.equals(that.displayState)) return false;
|
||||
if (!editorState.equals(that.editorState)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Boolean.valueOf(isSaved()).hashCode();
|
||||
result = 31 * result + getId();
|
||||
result = 31 * result + editorState.hashCode();
|
||||
result = 31 * result + displayState.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setValuesFromHistory(@Nonnull CalculatorEditor editor, @Nonnull CalculatorDisplay display) {
|
||||
this.getEditorState().setValuesFromHistory(editor);
|
||||
this.getDisplayState().setValuesFromHistory(display);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CalculatorHistoryState clone() {
|
||||
final CalculatorHistoryState clone = (CalculatorHistoryState) super.clone();
|
||||
|
||||
clone.editorState = this.editorState.clone();
|
||||
clone.displayState = this.displayState.clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.Root;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayViewState;
|
||||
import org.solovyev.android.calculator.CalculatorEditor;
|
||||
import org.solovyev.android.calculator.CalculatorEditorViewState;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Root
|
||||
public class EditorHistoryState implements Cloneable {
|
||||
|
||||
@Element
|
||||
private int cursorPosition;
|
||||
|
||||
@Element(required = false)
|
||||
@Nullable
|
||||
private String text = "";
|
||||
|
||||
private EditorHistoryState() {
|
||||
// for xml
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static EditorHistoryState newInstance(@Nonnull CalculatorEditorViewState viewState) {
|
||||
final EditorHistoryState result = new EditorHistoryState();
|
||||
|
||||
result.text = String.valueOf(viewState.getText());
|
||||
result.cursorPosition = viewState.getSelection();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static EditorHistoryState newInstance(@Nonnull CalculatorDisplayViewState viewState) {
|
||||
final EditorHistoryState result = new EditorHistoryState();
|
||||
|
||||
result.text = viewState.getText();
|
||||
result.cursorPosition = viewState.getSelection();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setValuesFromHistory(@Nonnull CalculatorEditor editor) {
|
||||
editor.setText(Strings.getNotEmpty(this.getText(), ""));
|
||||
editor.setSelection(this.getCursorPosition());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public int getCursorPosition() {
|
||||
return cursorPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof EditorHistoryState)) return false;
|
||||
|
||||
EditorHistoryState that = (EditorHistoryState) o;
|
||||
|
||||
if (cursorPosition != that.cursorPosition) return false;
|
||||
if (text != null ? !text.equals(that.text) : that.text != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = cursorPosition;
|
||||
result = 31 * result + (text != null ? text.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EditorHistoryState{" +
|
||||
"cursorPosition=" + cursorPosition +
|
||||
", text='" + text + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EditorHistoryState clone() {
|
||||
try {
|
||||
return (EditorHistoryState) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import org.simpleframework.xml.ElementList;
|
||||
import org.simpleframework.xml.Root;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/17/11
|
||||
* Time: 9:30 PM
|
||||
*/
|
||||
|
||||
@Root
|
||||
public class History {
|
||||
|
||||
@ElementList(type = CalculatorHistoryState.class)
|
||||
private List<CalculatorHistoryState> historyItems = new ArrayList<CalculatorHistoryState>();
|
||||
|
||||
public History() {
|
||||
}
|
||||
|
||||
public List<CalculatorHistoryState> getHistoryItems() {
|
||||
return historyItems;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import org.simpleframework.xml.Serializer;
|
||||
import org.simpleframework.xml.core.Persister;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/17/11
|
||||
* Time: 9:59 PM
|
||||
*/
|
||||
class HistoryUtils {
|
||||
|
||||
// not intended for instantiation
|
||||
private HistoryUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static void fromXml(@Nullable String xml, @Nonnull List<CalculatorHistoryState> historyItems) {
|
||||
if (xml != null) {
|
||||
final Serializer serializer = new Persister();
|
||||
try {
|
||||
final History history = serializer.read(History.class, xml);
|
||||
for (CalculatorHistoryState historyItem : history.getHistoryItems()) {
|
||||
historyItems.add(historyItem);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String toXml(@Nonnull List<CalculatorHistoryState> historyItems) {
|
||||
final History history = new History();
|
||||
for (CalculatorHistoryState historyState : historyItems) {
|
||||
if (historyState.isSaved()) {
|
||||
history.getHistoryItems().add(historyState);
|
||||
}
|
||||
}
|
||||
|
||||
final StringWriter xml = new StringWriter();
|
||||
final Serializer serializer = new Persister();
|
||||
try {
|
||||
serializer.write(history, xml);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return xml.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.jscl;
|
||||
|
||||
import org.solovyev.android.calculator.CalculatorParseException;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/6/11
|
||||
* Time: 9:48 PM
|
||||
*/
|
||||
class FromJsclNumericTextProcessor implements TextProcessor<String, Generic> {
|
||||
|
||||
public static final FromJsclNumericTextProcessor instance = new FromJsclNumericTextProcessor();
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String process(@Nonnull Generic numeric) throws CalculatorParseException {
|
||||
return numeric.toString().replace("*", "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.jscl;
|
||||
|
||||
|
||||
import org.solovyev.android.calculator.CalculatorMathEngine;
|
||||
import org.solovyev.android.calculator.text.DummyTextProcessor;
|
||||
import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import jscl.math.Generic;
|
||||
import jscl.text.ParseException;
|
||||
|
||||
public enum JsclOperation {
|
||||
|
||||
simplify,
|
||||
elementary,
|
||||
numeric;
|
||||
|
||||
JsclOperation() {
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
public TextProcessor<String, Generic> getFromProcessor() {
|
||||
switch (this) {
|
||||
case simplify:
|
||||
return FromJsclSimplifyTextProcessor.instance;
|
||||
case elementary:
|
||||
return DummyTextProcessor.instance;
|
||||
case numeric:
|
||||
return FromJsclNumericTextProcessor.instance;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final String evaluate(@Nonnull String expression, @Nonnull CalculatorMathEngine engine) throws ParseException {
|
||||
switch (this) {
|
||||
case simplify:
|
||||
return engine.simplify(expression);
|
||||
case elementary:
|
||||
return engine.elementary(expression);
|
||||
case numeric:
|
||||
return engine.evaluate(expression);
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final Generic evaluateGeneric(@Nonnull String expression, @Nonnull CalculatorMathEngine engine) throws ParseException {
|
||||
switch (this) {
|
||||
case simplify:
|
||||
return engine.simplifyGeneric(expression);
|
||||
case elementary:
|
||||
return engine.elementaryGeneric(expression);
|
||||
case numeric:
|
||||
return engine.evaluateGeneric(expression);
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.math;
|
||||
|
||||
import org.solovyev.android.calculator.CalculatorParseException;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.common.JPredicate;
|
||||
import org.solovyev.common.collections.Collections;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.JsclMathEngine;
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.function.Constants;
|
||||
|
||||
|
||||
public enum MathType {
|
||||
|
||||
numeral_base(50, true, false, MathGroupType.number) {
|
||||
|
||||
private final List<String> tokens = new ArrayList<String>(10);
|
||||
{
|
||||
for (NumeralBase numeralBase : NumeralBase.values()) {
|
||||
tokens.add(numeralBase.getJsclPrefix());
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<String> getTokens() {
|
||||
return tokens;
|
||||
}
|
||||
},
|
||||
|
||||
dot(200, true, true, MathGroupType.number, ".") {
|
||||
@Override
|
||||
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
|
||||
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit;
|
||||
}
|
||||
},
|
||||
|
||||
grouping_separator(250, false, false, MathGroupType.number, "'", " ") {
|
||||
@Override
|
||||
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) throws CalculatorParseException {
|
||||
return i;
|
||||
}
|
||||
},
|
||||
|
||||
power_10(300, false, false, MathGroupType.number, "E"),
|
||||
|
||||
postfix_function(400, false, true, MathGroupType.function) {
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<String> getTokens() {
|
||||
return Locator.getInstance().getEngine().getPostfixFunctionsRegistry().getNames();
|
||||
}
|
||||
},
|
||||
|
||||
unary_operation(500, false, false, MathGroupType.operation, "−", "-", "=") {
|
||||
@Nullable
|
||||
@Override
|
||||
protected String getSubstituteToJscl(@Nonnull String match) {
|
||||
if (match.equals("−")) {
|
||||
return "-";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected String getSubstituteFromJscl(@Nonnull String match) {
|
||||
if (match.equals("-")) {
|
||||
return "−";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
binary_operation(600, false, false, MathGroupType.operation, "−", "-", "+", "*", "×", "∙", "/", "^") {
|
||||
@Nullable
|
||||
@Override
|
||||
protected String getSubstituteFromJscl(@Nonnull String match) {
|
||||
if (match.equals("-")) {
|
||||
return "−";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubstituteToJscl(@Nonnull String match) {
|
||||
switch (match) {
|
||||
case "×":
|
||||
case "∙":
|
||||
return "*";
|
||||
case "−":
|
||||
return "-";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
open_group_symbol(800, true, false, MathGroupType.other, "[", "(", "{") {
|
||||
@Override
|
||||
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
|
||||
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function && mathTypeBefore != operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubstituteToJscl(@Nonnull String match) {
|
||||
return "(";
|
||||
}
|
||||
},
|
||||
|
||||
close_group_symbol(900, false, true, MathGroupType.other, "]", ")", "}") {
|
||||
@Override
|
||||
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubstituteToJscl(@Nonnull String match) {
|
||||
return ")";
|
||||
}
|
||||
},
|
||||
|
||||
function(1000, true, true, MathGroupType.function) {
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<String> getTokens() {
|
||||
return Locator.getInstance().getEngine().getFunctionsRegistry().getNames();
|
||||
}
|
||||
},
|
||||
|
||||
operator(1050, true, true, MathGroupType.function) {
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<String> getTokens() {
|
||||
return Locator.getInstance().getEngine().getOperatorsRegistry().getNames();
|
||||
}
|
||||
},
|
||||
|
||||
constant(1100, true, true, MathGroupType.other) {
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<String> getTokens() {
|
||||
return Locator.getInstance().getEngine().getVarsRegistry().getNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubstituteFromJscl(@Nonnull String match) {
|
||||
return Constants.INF_2.getName().equals(match) ? MathType.INFINITY : super.getSubstituteFromJscl(match);
|
||||
}
|
||||
},
|
||||
|
||||
digit(1125, true, true, MathGroupType.number) {
|
||||
|
||||
private final List<String> tokens = new ArrayList<>(16);
|
||||
{
|
||||
for (Character character : NumeralBase.hex.getAcceptableCharacters()) {
|
||||
tokens.add(character.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
|
||||
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit && mathTypeBefore != dot /*&& mathTypeBefore != numeral_base*/;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<String> getTokens() {
|
||||
return tokens;
|
||||
}
|
||||
},
|
||||
|
||||
comma(1150, false, false, MathGroupType.other, ","),
|
||||
|
||||
text(1200, false, false, MathGroupType.other) {
|
||||
@Override
|
||||
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
|
||||
if (match.length() > 0) {
|
||||
result.append(match.charAt(0));
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int processFromJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
|
||||
if (match.length() > 0) {
|
||||
result.append(match.charAt(0));
|
||||
}
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
public static final List<String> openGroupSymbols = Arrays.asList("[]", "()", "{}");
|
||||
public final static Character POWER_10 = 'E';
|
||||
public static final String IMAGINARY_NUMBER = "i";
|
||||
public static final String IMAGINARY_NUMBER_JSCL = "√(-1)";
|
||||
public static final String PI = "π";
|
||||
public static final String E = "e";
|
||||
public static final String C = "c";
|
||||
public static final Double C_VALUE = 299792458d;
|
||||
public static final String G = "G";
|
||||
|
||||
/* public static int getPostfixFunctionStart(@Nonnull CharSequence s, int position) throws ParseException {
|
||||
assert s.length() > position;
|
||||
|
||||
int numberOfOpenGroups = 0;
|
||||
int result = position;
|
||||
for (; result >= 0; result--) {
|
||||
|
||||
final MathType mathType = getType(s.toString(), result).getMathType();
|
||||
|
||||
if (Collections.contains(mathType, digit, dot, grouping_separator, power_10)) {
|
||||
// continue
|
||||
} else if (mathType == close_group_symbol) {
|
||||
numberOfOpenGroups++;
|
||||
} else if (mathType == open_group_symbol) {
|
||||
if (numberOfOpenGroups > 0) {
|
||||
numberOfOpenGroups--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (stop(s, numberOfOpenGroups, result)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numberOfOpenGroups != 0){
|
||||
throw new ParseException("Could not find start of prefix function!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean stop(CharSequence s, int numberOfOpenGroups, int i) {
|
||||
if (numberOfOpenGroups == 0) {
|
||||
if (i > 0) {
|
||||
final EndsWithFinder endsWithFinder = new EndsWithFinder(s);
|
||||
endsWithFinder.setI(i + 1);
|
||||
if (!Collections.contains(function.getTokens(), FilterType.included, endsWithFinder)) {
|
||||
MathType type = getType(s.toString(), i).getMathType();
|
||||
if (type != constant) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}*/
|
||||
public static final Double G_VALUE = 6.6738480E-11;
|
||||
public static final String H_REDUCED = "h";
|
||||
public static final Double H_REDUCED_VALUE = 6.6260695729E-34 / (2 * Math.PI);
|
||||
public final static String NAN = "NaN";
|
||||
public final static String INFINITY = "∞";
|
||||
public final static String INFINITY_JSCL = "Infinity";
|
||||
private static List<MathType> mathTypesByPriority;
|
||||
@Nonnull
|
||||
private final List<String> tokens;
|
||||
@Nonnull
|
||||
private final Integer priority;
|
||||
private final boolean needMultiplicationSignBefore;
|
||||
private final boolean needMultiplicationSignAfter;
|
||||
@Nonnull
|
||||
private final MathGroupType groupType;
|
||||
MathType(@Nonnull Integer priority,
|
||||
boolean needMultiplicationSignBefore,
|
||||
boolean needMultiplicationSignAfter,
|
||||
@Nonnull MathGroupType groupType,
|
||||
@Nonnull String... tokens) {
|
||||
this(priority, needMultiplicationSignBefore, needMultiplicationSignAfter, groupType, Collections.asList(tokens));
|
||||
}
|
||||
|
||||
MathType(@Nonnull Integer priority,
|
||||
boolean needMultiplicationSignBefore,
|
||||
boolean needMultiplicationSignAfter,
|
||||
@Nonnull MathGroupType groupType,
|
||||
@Nonnull List<String> tokens) {
|
||||
this.priority = priority;
|
||||
this.needMultiplicationSignBefore = needMultiplicationSignBefore;
|
||||
this.needMultiplicationSignAfter = needMultiplicationSignAfter;
|
||||
this.groupType = groupType;
|
||||
this.tokens = java.util.Collections.unmodifiableList(tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method determines mathematical entity type for text substring starting from ith index
|
||||
*
|
||||
* @param text analyzed text
|
||||
* @param i index which points to start of substring
|
||||
* @param hexMode
|
||||
* @return math entity type of substring starting from ith index of specified text
|
||||
*/
|
||||
@Nonnull
|
||||
public static Result getType(@Nonnull String text, int i, boolean hexMode) {
|
||||
if (i < 0) {
|
||||
throw new IllegalArgumentException("I must be more or equals to 0.");
|
||||
} else if (i >= text.length() && i != 0) {
|
||||
throw new IllegalArgumentException("I must be less than size of text.");
|
||||
} else if (i == 0 && text.length() == 0) {
|
||||
return new Result(MathType.text, text);
|
||||
}
|
||||
|
||||
final StartsWithFinder startsWithFinder = new StartsWithFinder(text, i);
|
||||
|
||||
for (MathType mathType : getMathTypesByPriority()) {
|
||||
final String s = Collections.find(mathType.getTokens(), startsWithFinder);
|
||||
if (s != null) {
|
||||
if (s.length() == 1) {
|
||||
if (hexMode || JsclMathEngine.getInstance().getNumeralBase() == NumeralBase.hex) {
|
||||
final Character ch = s.charAt(0);
|
||||
if (NumeralBase.hex.getAcceptableCharacters().contains(ch)) {
|
||||
return new Result(MathType.digit, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Result(mathType, s);
|
||||
}
|
||||
}
|
||||
|
||||
return new Result(MathType.text, text.substring(i));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static List<MathType> getMathTypesByPriority() {
|
||||
if (mathTypesByPriority == null) {
|
||||
final List<MathType> result = Collections.asList(MathType.values());
|
||||
|
||||
java.util.Collections.sort(result, new Comparator<MathType>() {
|
||||
@Override
|
||||
public int compare(MathType l, MathType r) {
|
||||
return l.priority.compareTo(r.priority);
|
||||
}
|
||||
});
|
||||
|
||||
mathTypesByPriority = result;
|
||||
}
|
||||
|
||||
return mathTypesByPriority;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public MathGroupType getGroupType() {
|
||||
return groupType;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<String> getTokens() {
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private boolean isNeedMultiplicationSignBefore() {
|
||||
return needMultiplicationSignBefore;
|
||||
}
|
||||
|
||||
private boolean isNeedMultiplicationSignAfter() {
|
||||
return needMultiplicationSignAfter;
|
||||
}
|
||||
|
||||
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
|
||||
return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter();
|
||||
}
|
||||
|
||||
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) throws CalculatorParseException {
|
||||
final String substitute = getSubstituteToJscl(match);
|
||||
result.append(substitute == null ? match : substitute);
|
||||
return returnI(i, match);
|
||||
}
|
||||
|
||||
protected int returnI(int i, @Nonnull String match) {
|
||||
if (match.length() > 1) {
|
||||
return i + match.length() - 1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
public int processFromJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
|
||||
final String substitute = getSubstituteFromJscl(match);
|
||||
result.append(substitute == null ? match : substitute);
|
||||
return returnI(i, match);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String getSubstituteFromJscl(@Nonnull String match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String getSubstituteToJscl(@Nonnull String match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static enum MathGroupType {
|
||||
function,
|
||||
number,
|
||||
operation,
|
||||
other
|
||||
}
|
||||
|
||||
public static class Result {
|
||||
|
||||
@Nonnull
|
||||
private final MathType mathType;
|
||||
|
||||
@Nonnull
|
||||
private final String match;
|
||||
|
||||
public Result(@Nonnull MathType mathType, @Nonnull String match) {
|
||||
this.mathType = mathType;
|
||||
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
public int processToJscl(@Nonnull StringBuilder result, int i) throws CalculatorParseException {
|
||||
return mathType.processToJscl(result, i, match);
|
||||
}
|
||||
|
||||
public int processFromJscl(@Nonnull StringBuilder result, int i) {
|
||||
return mathType.processFromJscl(result, i, match);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getMatch() {
|
||||
return match;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public MathType getMathType() {
|
||||
return mathType;
|
||||
}
|
||||
}
|
||||
|
||||
private static class EndsWithFinder implements JPredicate<String> {
|
||||
|
||||
@Nonnull
|
||||
private final CharSequence targetString;
|
||||
private int i;
|
||||
|
||||
private EndsWithFinder(@Nonnull CharSequence targetString) {
|
||||
this.targetString = targetString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(@Nullable String s) {
|
||||
return targetString.subSequence(0, i).toString().endsWith(s);
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
private static class StartsWithFinder implements JPredicate<String> {
|
||||
|
||||
@Nonnull
|
||||
private final String targetString;
|
||||
private int i;
|
||||
|
||||
public StartsWithFinder(@Nonnull String targetString, int i) {
|
||||
this.targetString = targetString;
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(@Nullable String s) {
|
||||
return s != null && targetString.startsWith(s, i);
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.model;
|
||||
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.ElementList;
|
||||
import org.simpleframework.xml.Root;
|
||||
import org.simpleframework.xml.Transient;
|
||||
import org.solovyev.android.calculator.CalculatorParseException;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.MathPersistenceEntity;
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageLevel;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.function.IFunction;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/22/11
|
||||
* Time: 5:25 PM
|
||||
*/
|
||||
|
||||
@Root(name = "function")
|
||||
public class AFunction implements IFunction, MathPersistenceEntity, Serializable {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
@Transient
|
||||
private Integer id;
|
||||
|
||||
@Element
|
||||
@Nonnull
|
||||
private String name;
|
||||
|
||||
@Element(name = "body")
|
||||
@Nonnull
|
||||
private String content;
|
||||
|
||||
@ElementList(type = String.class)
|
||||
@Nonnull
|
||||
private List<String> parameterNames = new ArrayList<String>();
|
||||
|
||||
@Element
|
||||
private boolean system;
|
||||
|
||||
@Element(required = false)
|
||||
@Nonnull
|
||||
private String description = "";
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public AFunction() {
|
||||
}
|
||||
|
||||
public AFunction(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static AFunction fromIFunction(@Nonnull IFunction function) {
|
||||
final AFunction result = new AFunction();
|
||||
|
||||
copy(result, function);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static void copy(@Nonnull AFunction target,
|
||||
@Nonnull IFunction source) {
|
||||
target.name = source.getName();
|
||||
target.content = source.getContent();
|
||||
target.description = Strings.getNotEmpty(source.getDescription(), "");
|
||||
target.system = source.isSystem();
|
||||
if (source.isIdDefined()) {
|
||||
target.id = source.getId();
|
||||
}
|
||||
target.parameterNames = new ArrayList<String>(source.getParameterNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy(@Nonnull MathEntity mathEntity) {
|
||||
if (mathEntity instanceof IFunction) {
|
||||
copy(this, (IFunction) mathEntity);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + mathEntity.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJava() {
|
||||
return String.valueOf(this.content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AFunction{" +
|
||||
"name='" + name + '\'' +
|
||||
", parameterNames=" + parameterNames +
|
||||
", content='" + content + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* GETTERS/SETTERS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(@Nonnull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(@Nonnull Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdDefined() {
|
||||
return this.id != null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(@Nonnull String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<String> getParameterNames() {
|
||||
return parameterNames;
|
||||
}
|
||||
|
||||
public void setParameterNames(@Nonnull List<String> parameterNames) {
|
||||
this.parameterNames = parameterNames;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public static class Builder implements MathEntityBuilder<AFunction> {
|
||||
|
||||
@Nonnull
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
private boolean system = false;
|
||||
|
||||
@Nullable
|
||||
private String description;
|
||||
|
||||
@Nullable
|
||||
private Integer id;
|
||||
|
||||
@Nonnull
|
||||
private List<String> parameterNames = Collections.emptyList();
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public Builder(@Nonnull IFunction function) {
|
||||
this.name = function.getName();
|
||||
this.value = function.getContent();
|
||||
this.system = function.isSystem();
|
||||
this.description = function.getDescription();
|
||||
if (function.isIdDefined()) {
|
||||
this.id = function.getId();
|
||||
}
|
||||
this.parameterNames = new ArrayList<String>(function.getParameterNames());
|
||||
}
|
||||
|
||||
public Builder(@Nonnull String name,
|
||||
@Nonnull String value,
|
||||
@Nonnull List<String> parameterNames) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.parameterNames = parameterNames;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Builder setName(@Nonnull String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Builder setValue(@Nullable String value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Builder setSystem(boolean system) {
|
||||
this.system = system;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setParameterNames(@Nonnull List<String> parameterNames) {
|
||||
this.parameterNames = parameterNames;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Builder setDescription(@Nullable String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AFunction create() throws AFunction.Builder.CreationException {
|
||||
final AFunction result;
|
||||
if (id != null) {
|
||||
result = new AFunction(id);
|
||||
} else {
|
||||
result = new AFunction();
|
||||
}
|
||||
|
||||
result.name = name;
|
||||
try {
|
||||
result.content = Locator.getInstance().getCalculator().prepareExpression(value).toString();
|
||||
} catch (CalculatorParseException e) {
|
||||
throw new CreationException(e);
|
||||
}
|
||||
result.system = system;
|
||||
result.description = Strings.getNotEmpty(description, "");
|
||||
result.parameterNames = new ArrayList<String>(parameterNames);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class CreationException extends RuntimeException implements Message {
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorParseException message;
|
||||
|
||||
public CreationException(@Nonnull CalculatorParseException cause) {
|
||||
super(cause);
|
||||
message = cause;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getMessageCode() {
|
||||
return message.getMessageCode();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<Object> getParameters() {
|
||||
return message.getParameters();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MessageLevel getMessageLevel() {
|
||||
return message.getMessageLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String getLocalizedMessage() {
|
||||
return message.getLocalizedMessage();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getLocalizedMessage(@Nonnull Locale locale) {
|
||||
return message.getLocalizedMessage(locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.model;
|
||||
|
||||
import org.simpleframework.xml.ElementList;
|
||||
import org.simpleframework.xml.Root;
|
||||
import org.solovyev.android.calculator.MathEntityPersistenceContainer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/22/11
|
||||
* Time: 5:15 PM
|
||||
*/
|
||||
@Root
|
||||
public class Functions implements MathEntityPersistenceContainer<AFunction> {
|
||||
|
||||
@ElementList(type = AFunction.class)
|
||||
private List<AFunction> functions = new ArrayList<AFunction>();
|
||||
|
||||
public Functions() {
|
||||
}
|
||||
|
||||
public List<AFunction> getEntities() {
|
||||
return functions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.model;
|
||||
|
||||
import org.solovyev.common.JBuilder;
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/22/11
|
||||
* Time: 9:21 PM
|
||||
*/
|
||||
public interface MathEntityBuilder<T extends MathEntity> extends JBuilder<T> {
|
||||
|
||||
@Nonnull
|
||||
public MathEntityBuilder<T> setName(@Nonnull String name);
|
||||
|
||||
@Nonnull
|
||||
public MathEntityBuilder<T> setDescription(@Nullable String description);
|
||||
|
||||
@Nonnull
|
||||
public MathEntityBuilder<T> setValue(@Nullable String value);
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.model;
|
||||
|
||||
import org.simpleframework.xml.Element;
|
||||
import org.simpleframework.xml.Root;
|
||||
import org.simpleframework.xml.Transient;
|
||||
import org.solovyev.android.calculator.MathPersistenceEntity;
|
||||
import org.solovyev.common.JBuilder;
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.function.Constant;
|
||||
import jscl.math.function.ExtendedConstant;
|
||||
import jscl.math.function.IConstant;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/28/11
|
||||
* Time: 11:22 PM
|
||||
*/
|
||||
|
||||
@Root
|
||||
public class Var implements IConstant, MathPersistenceEntity {
|
||||
|
||||
@Transient
|
||||
private Integer id;
|
||||
|
||||
@Element
|
||||
@Nonnull
|
||||
private String name;
|
||||
|
||||
@Element(required = false)
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
@Element
|
||||
private boolean system;
|
||||
|
||||
@Element(required = false)
|
||||
@Nullable
|
||||
private String description;
|
||||
|
||||
@Transient
|
||||
private Constant constant;
|
||||
|
||||
private Var() {
|
||||
}
|
||||
|
||||
private Var(@Nonnull Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void copy(@Nonnull MathEntity o) {
|
||||
if (o instanceof IConstant) {
|
||||
final IConstant that = ((IConstant) o);
|
||||
this.name = that.getName();
|
||||
this.value = that.getValue();
|
||||
this.description = that.getDescription();
|
||||
this.system = that.isSystem();
|
||||
if (that.isIdDefined()) {
|
||||
this.id = that.getId();
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + o.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Double getDoubleValue() {
|
||||
Double result = null;
|
||||
if (value != null) {
|
||||
try {
|
||||
result = Double.valueOf(value);
|
||||
} catch (NumberFormatException e) {
|
||||
// do nothing - string is not a double
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toJava() {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
public boolean isSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(@Nonnull Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdDefined() {
|
||||
return this.id != null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Constant getConstant() {
|
||||
if (constant == null) {
|
||||
constant = new Constant(this.name);
|
||||
}
|
||||
return constant;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefined() {
|
||||
return !Strings.isEmpty(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ExtendedConstant.toString(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Var var = (Var) o;
|
||||
|
||||
if (!name.equals(var.name)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
public static class Builder implements JBuilder<Var>, MathEntityBuilder<Var> {
|
||||
|
||||
@Nonnull
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
private boolean system = false;
|
||||
|
||||
@Nullable
|
||||
private String description;
|
||||
|
||||
@Nullable
|
||||
private Integer id;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public Builder(@Nonnull Var var) {
|
||||
this.name = var.name;
|
||||
this.value = var.value;
|
||||
this.system = var.system;
|
||||
this.description = var.description;
|
||||
this.id = var.id;
|
||||
}
|
||||
|
||||
public Builder(@Nonnull IConstant iConstant) {
|
||||
this.name = iConstant.getName();
|
||||
|
||||
this.value = iConstant.getValue();
|
||||
|
||||
this.system = iConstant.isSystem();
|
||||
this.description = iConstant.getDescription();
|
||||
if (iConstant.isIdDefined()) {
|
||||
this.id = iConstant.getId();
|
||||
}
|
||||
}
|
||||
|
||||
public Builder(@Nonnull String name, @Nonnull Double value) {
|
||||
this(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Builder(@Nonnull String name, @Nullable String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
public Builder setName(@Nonnull String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Builder setValue(@Nullable String value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Builder setSystem(boolean system) {
|
||||
this.system = system;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Builder setDescription(@Nullable String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Var create() {
|
||||
final Var result;
|
||||
if (id != null) {
|
||||
result = new Var(id);
|
||||
} else {
|
||||
result = new Var();
|
||||
}
|
||||
|
||||
result.name = name;
|
||||
result.value = value;
|
||||
result.system = system;
|
||||
result.description = description;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.model;
|
||||
|
||||
import org.simpleframework.xml.ElementList;
|
||||
import org.simpleframework.xml.Root;
|
||||
import org.solovyev.android.calculator.MathEntityPersistenceContainer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/29/11
|
||||
* Time: 5:19 PM
|
||||
*/
|
||||
|
||||
@Root
|
||||
public class Vars implements MathEntityPersistenceContainer<Var> {
|
||||
|
||||
@ElementList(type = Var.class)
|
||||
private List<Var> vars = new ArrayList<Var>();
|
||||
|
||||
public Vars() {
|
||||
}
|
||||
|
||||
public List<Var> getEntities() {
|
||||
return vars;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2013 serso aka se.solovyev
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Contact details
|
||||
*
|
||||
* Email: se.solovyev@gmail.com
|
||||
* Site: http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.plot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/12/13
|
||||
* Time: 8:23 PM
|
||||
*/
|
||||
public interface CalculatorPlotter {
|
||||
|
||||
@Nonnull
|
||||
PlotData getPlotData();
|
||||
|
||||
boolean addFunction(@Nonnull Generic expression);
|
||||
|
||||
boolean addFunction(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
boolean addFunction(@Nonnull XyFunction xyFunction);
|
||||
|
||||
boolean addFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef);
|
||||
|
||||
boolean updateFunction(@Nonnull PlotFunction newFunction);
|
||||
|
||||
boolean updateFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef);
|
||||
|
||||
boolean removeFunction(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
boolean removeFunction(@Nonnull XyFunction xyFunction);
|
||||
|
||||
@Nonnull
|
||||
PlotFunction pin(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
@Nonnull
|
||||
PlotFunction unpin(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
@Nonnull
|
||||
PlotFunction show(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
@Nonnull
|
||||
PlotFunction hide(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
void clearAllFunctions();
|
||||
|
||||
@Nullable
|
||||
PlotFunction getFunctionById(@Nonnull String functionId);
|
||||
|
||||
@Nonnull
|
||||
List<PlotFunction> getFunctions();
|
||||
|
||||
@Nonnull
|
||||
List<PlotFunction> getVisibleFunctions();
|
||||
|
||||
void plot();
|
||||
|
||||
void plot(@Nonnull Generic expression);
|
||||
|
||||
boolean is2dPlotPossible();
|
||||
|
||||
boolean isPlotPossibleFor(@Nonnull Generic expression);
|
||||
|
||||
void setPlot3d(boolean plot3d);
|
||||
|
||||
void removeAllUnpinned();
|
||||
|
||||
void setPlotImag(boolean plotImag);
|
||||
|
||||
void savePlotBoundaries(@Nonnull PlotBoundaries plotBoundaries);
|
||||
|
||||
void setPlotBoundaries(@Nonnull PlotBoundaries plotBoundaries);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user