New architecture

This commit is contained in:
Sergey Solovyev 2012-09-22 15:02:38 +04:00
parent d0fe0ca012
commit 3661774d9b
28 changed files with 741 additions and 462 deletions

View File

@ -0,0 +1,19 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: serso
* Date: 9/22/12
* Time: 1:34 PM
*/
public interface CalculatorClipboard {
@Nullable
String getText();
void setText(@NotNull String text);
void setText(@NotNull CharSequence text);
}

View File

@ -30,6 +30,7 @@ public class CalculatorDisplayImpl implements CalculatorDisplay {
public CalculatorDisplayImpl(@NotNull Calculator calculator) { public CalculatorDisplayImpl(@NotNull Calculator calculator) {
this.calculator = calculator; this.calculator = calculator;
this.lastCalculatorEventData = CalculatorEventDataImpl.newInstance(calculator.createFirstEventDataId()); this.lastCalculatorEventData = CalculatorEventDataImpl.newInstance(calculator.createFirstEventDataId());
this.calculator.addCalculatorEventListener(this);
} }
@Override @Override

View File

@ -59,6 +59,9 @@ public interface CalculatorEditor extends CalculatorEventListener/*, CursorContr
@NotNull @NotNull
CalculatorEditorViewState erase(); CalculatorEditorViewState erase();
@NotNull
CalculatorEditorViewState clear();
@NotNull @NotNull
CalculatorEditorViewState setText(@NotNull String text); CalculatorEditorViewState setText(@NotNull String text);
@ -68,6 +71,9 @@ public interface CalculatorEditor extends CalculatorEventListener/*, CursorContr
@NotNull @NotNull
CalculatorEditorViewState insert(@NotNull String text); CalculatorEditorViewState insert(@NotNull String text);
@NotNull
CalculatorEditorViewState insert(@NotNull String text, int selectionOffset);
@NotNull @NotNull
CalculatorEditorViewState moveSelection(int offset); CalculatorEditorViewState moveSelection(int offset);

View File

@ -24,6 +24,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
public CalculatorEditorImpl(@NotNull Calculator calculator) { public CalculatorEditorImpl(@NotNull Calculator calculator) {
this.calculator = calculator; this.calculator = calculator;
this.calculator.addCalculatorEventListener(this);
} }
@Override @Override
@ -130,6 +131,14 @@ public class CalculatorEditorImpl implements CalculatorEditor {
} }
} }
@NotNull
@Override
public CalculatorEditorViewState clear() {
synchronized (viewLock) {
return setText("");
}
}
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState setText(@NotNull String text) { public CalculatorEditorViewState setText(@NotNull String text) {
@ -155,17 +164,27 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState insert(@NotNull String text) { public CalculatorEditorViewState insert(@NotNull String text) {
synchronized (viewLock) {
return insert(text, 0);
}
}
@NotNull
@Override
public CalculatorEditorViewState insert(@NotNull String text, int selectionOffset) {
synchronized (viewLock) { synchronized (viewLock) {
final int selection = this.lastViewState.getSelection(); final int selection = this.lastViewState.getSelection();
final String oldText = this.lastViewState.getText(); final String oldText = this.lastViewState.getText();
final StringBuilder newText = new StringBuilder(text.length() + oldText.length()); int newTextLength = text.length() + oldText.length();
final StringBuilder newText = new StringBuilder(newTextLength);
newText.append(oldText.substring(0, selection)); newText.append(oldText.substring(0, selection));
newText.append(text); newText.append(text);
newText.append(oldText.substring(selection)); newText.append(oldText.substring(selection));
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), text.length() + selection); int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength);
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection);
setViewState(result); setViewState(result);
return result; return result;
} }
@ -194,8 +213,12 @@ public class CalculatorEditorImpl implements CalculatorEditor {
} }
private int correctSelection(int selection, @NotNull String text) { private int correctSelection(int selection, @NotNull String text) {
return correctSelection(selection, text.length());
}
private int correctSelection(int selection, int textLength) {
int result = Math.max(selection, 0); int result = Math.max(selection, 0);
result = Math.min(result, text.length()); result = Math.min(result, textLength);
return result; return result;
} }
} }

View File

@ -3,6 +3,7 @@ package org.solovyev.android.calculator;
import jscl.AbstractJsclArithmeticException; import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase; import jscl.NumeralBase;
import jscl.NumeralBaseException; import jscl.NumeralBaseException;
import jscl.math.Expression;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.text.ParseInterruptedException; import jscl.text.ParseInterruptedException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -36,9 +37,6 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
@NotNull @NotNull
private final AtomicLong counter = new AtomicLong(FIRST_ID); private final AtomicLong counter = new AtomicLong(FIRST_ID);
@NotNull
private final Object lock = new Object();
@NotNull @NotNull
private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance(); private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
@ -208,13 +206,19 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
@NotNull JsclOperation operation, @NotNull JsclOperation operation,
@NotNull String expression, @NotNull String expression,
@Nullable MessageRegistry mr) { @Nullable MessageRegistry mr) {
synchronized (lock) {
PreparedExpression preparedExpression = null; PreparedExpression preparedExpression = null;
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation)); fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation));
try { try {
expression = expression.trim();
if ( StringUtils.isEmpty(expression) ) {
final CalculatorOutputImpl data = new CalculatorOutputImpl("", operation, Expression.valueOf(""));
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data);
} else {
preparedExpression = preprocessor.process(expression); preparedExpression = preprocessor.process(expression);
final String jsclExpression = preparedExpression.toString(); final String jsclExpression = preparedExpression.toString();
@ -232,23 +236,23 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
} catch (AbstractJsclArithmeticException e) { } catch (AbstractJsclArithmeticException e) {
handleException(sequenceId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression)); handleException(sequenceId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression));
} }
} catch (ArithmeticException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage())));
} catch (StackOverflowError e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error)));
} catch (jscl.text.ParseException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(e));
} catch (ParseInterruptedException e) {
// do nothing - we ourselves interrupt the calculations
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_cancelled, null);
} catch (CalculatorParseException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, e);
} finally {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_finished, null);
} }
} catch (ArithmeticException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage())));
} catch (StackOverflowError e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error)));
} catch (jscl.text.ParseException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(e));
} catch (ParseInterruptedException e) {
// do nothing - we ourselves interrupt the calculations
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_cancelled, null);
} catch (CalculatorParseException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, e);
} finally {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_finished, null);
} }
} }
@ -259,7 +263,7 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
return new CalculatorEvaluationEventDataImpl(CalculatorEventDataImpl.newInstance(nextEventDataId(calculationId)), operation, expression); return new CalculatorEvaluationEventDataImpl(CalculatorEventDataImpl.newInstance(nextEventDataId(calculationId)), operation, expression);
} }
private void handleException(@NotNull Long calculationId, private void handleException(@NotNull Long sequenceId,
@NotNull JsclOperation operation, @NotNull JsclOperation operation,
@NotNull String expression, @NotNull String expression,
@Nullable MessageRegistry mr, @Nullable MessageRegistry mr,
@ -270,11 +274,11 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
&& preparedExpression != null && preparedExpression != null
&& preparedExpression.isExistsUndefinedVar()) { && preparedExpression.isExistsUndefinedVar()) {
evaluate(calculationId, JsclOperation.simplify, expression, mr); evaluate(sequenceId, JsclOperation.simplify, expression, mr);
} else {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException));
} }
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException));
} }
private void handleException(@NotNull Long calculationId, private void handleException(@NotNull Long calculationId,
@ -323,7 +327,12 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
if (calculatorEventType == CalculatorEventType.editor_state_changed) { if (calculatorEventType == CalculatorEventType.editor_state_changed) {
final CalculatorEditorChangeEventData changeEventData = (CalculatorEditorChangeEventData) data; final CalculatorEditorChangeEventData changeEventData = (CalculatorEditorChangeEventData) data;
evaluate(JsclOperation.numeric, changeEventData.getNewState().getText(), calculatorEventData.getSequenceId()); final String newText = changeEventData.getNewState().getText();
final String oldText = changeEventData.getOldState().getText();
if ( !newText.equals(oldText) ) {
evaluate(JsclOperation.numeric, changeEventData.getNewState().getText(), calculatorEventData.getSequenceId());
}
} }
} }

View File

@ -0,0 +1,21 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.Nullable;
/**
* User: serso
* Date: 9/22/12
* Time: 1:08 PM
*/
public interface CalculatorKeyboard {
void digitButtonPressed(@Nullable String text);
void roundBracketsButtonPressed();
void pasteButtonPressed();
void clearButtonPressed();
void copyButtonPressed();
}

View File

@ -0,0 +1,97 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.common.text.StringUtils;
/**
* User: serso
* Date: 9/22/12
* Time: 1:08 PM
*/
public class CalculatorKeyboardImpl implements CalculatorKeyboard {
@NotNull
private final Calculator calculator;
public CalculatorKeyboardImpl(@NotNull Calculator calculator) {
this.calculator = calculator;
}
@Override
public void digitButtonPressed(@Nullable final String text) {
if (!StringUtils.isEmpty(text)) {
assert text != null;
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 = CalculatorLocatorImpl.getInstance().getCalculatorEditor();
editor.insert(textToBeInserted.toString(), cursorPositionOffset);
}
}
@Override
public void roundBracketsButtonPressed() {
final CalculatorEditor editor = CalculatorLocatorImpl.getInstance().getCalculatorEditor();
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 = CalculatorLocatorImpl.getInstance().getCalculatorClipboard().getText();
if (text != null) {
CalculatorLocatorImpl.getInstance().getCalculatorEditor().insert(text);
}
}
@Override
public void clearButtonPressed() {
CalculatorLocatorImpl.getInstance().getCalculatorEditor().clear();
}
@Override
public void copyButtonPressed() {
final CalculatorDisplayViewState displayViewState = CalculatorLocatorImpl.getInstance().getCalculatorDisplay().getViewState();
if (displayViewState.isValid()) {
final CharSequence text = displayViewState.getText();
if (!StringUtils.isEmpty(text)) {
CalculatorLocatorImpl.getInstance().getCalculatorClipboard().setText(text);
CalculatorLocatorImpl.getInstance().getCalculatorNotifier().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied));
}
}
}
}

View File

@ -1,25 +1,38 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 20.09.12 * Date: 20.09.12
* Time: 12:45 * Time: 12:45
*/ */
public interface CalculatorLocator { public interface CalculatorLocator {
@NotNull @NotNull
JCalculatorEngine getCalculatorEngine(); JCalculatorEngine getCalculatorEngine();
@NotNull @NotNull
Calculator getCalculator(); Calculator getCalculator();
@NotNull @NotNull
CalculatorDisplay getCalculatorDisplay(); CalculatorDisplay getCalculatorDisplay();
@NotNull @NotNull
CalculatorEditor getCalculatorEditor(); CalculatorEditor getCalculatorEditor();
void setCalculatorEngine(@NotNull JCalculatorEngine calculatorEngine); void setCalculatorEngine(@NotNull JCalculatorEngine calculatorEngine);
}
@NotNull
CalculatorKeyboard getCalculatorKeyboard();
@NotNull
CalculatorClipboard getCalculatorClipboard();
void setCalculatorClipboard(@NotNull CalculatorClipboard calculatorClipboard);
@NotNull
CalculatorNotifier getCalculatorNotifier();
void setCalculatorNotifier(@NotNull CalculatorNotifier calculatorNotifier);
}

View File

@ -21,6 +21,15 @@ public class CalculatorLocatorImpl implements CalculatorLocator {
@NotNull @NotNull
private final CalculatorDisplay calculatorDisplay = new CalculatorDisplayImpl(calculator); private final CalculatorDisplay calculatorDisplay = new CalculatorDisplayImpl(calculator);
@NotNull
private final CalculatorKeyboard calculatorKeyboard = new CalculatorKeyboardImpl(calculator);
@NotNull
private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier();
@NotNull
private CalculatorClipboard calculatorClipboard = new DummyCalculatorClipboard();
@NotNull @NotNull
private static final CalculatorLocator instance = new CalculatorLocatorImpl(); private static final CalculatorLocator instance = new CalculatorLocatorImpl();
@ -60,4 +69,32 @@ public class CalculatorLocatorImpl implements CalculatorLocator {
public CalculatorEditor getCalculatorEditor() { public CalculatorEditor getCalculatorEditor() {
return calculatorEditor; return calculatorEditor;
} }
@Override
@NotNull
public CalculatorKeyboard getCalculatorKeyboard() {
return calculatorKeyboard;
}
@Override
@NotNull
public CalculatorClipboard getCalculatorClipboard() {
return calculatorClipboard;
}
@Override
public void setCalculatorClipboard(@NotNull CalculatorClipboard calculatorClipboard) {
this.calculatorClipboard = calculatorClipboard;
}
@Override
@NotNull
public CalculatorNotifier getCalculatorNotifier() {
return calculatorNotifier;
}
@Override
public void setCalculatorNotifier(@NotNull CalculatorNotifier calculatorNotifier) {
this.calculatorNotifier = calculatorNotifier;
}
} }

View File

@ -1,7 +1,9 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.msg.AbstractMessage; import org.solovyev.common.msg.AbstractMessage;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType; import org.solovyev.common.msg.MessageType;
import java.util.List; import java.util.List;
@ -15,14 +17,29 @@ import java.util.ResourceBundle;
*/ */
public class CalculatorMessage extends AbstractMessage { public class CalculatorMessage extends AbstractMessage {
protected CalculatorMessage(@NotNull String messageCode, @NotNull MessageType messageType, @org.jetbrains.annotations.Nullable Object... parameters) { public CalculatorMessage(@NotNull String messageCode, @NotNull MessageType messageType, @Nullable Object... parameters) {
super(messageCode, messageType, parameters); super(messageCode, messageType, parameters);
} }
protected CalculatorMessage(@NotNull String messageCode, @NotNull MessageType messageType, @NotNull List<?> parameters) { public CalculatorMessage(@NotNull String messageCode, @NotNull MessageType messageType, @NotNull List<?> parameters) {
super(messageCode, messageType, parameters); super(messageCode, messageType, parameters);
} }
@NotNull
public static Message newInfoMessage(@NotNull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.info, parameters);
}
@NotNull
public static Message newWarningMessage(@NotNull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.warning, parameters);
}
@NotNull
public static Message newErrorMessage(@NotNull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.error, parameters);
}
@Override @Override
protected String getMessagePattern(@NotNull Locale locale) { protected String getMessagePattern(@NotNull Locale locale) {
final ResourceBundle rb = CalculatorMessages.getBundle(locale); final ResourceBundle rb = CalculatorMessages.getBundle(locale);

View File

@ -17,6 +17,7 @@ public final class CalculatorMessages {
@NotNull @NotNull
private static final Map<Locale, ResourceBundle> bundlesByLocale = new HashMap<Locale, ResourceBundle>(); private static final Map<Locale, ResourceBundle> bundlesByLocale = new HashMap<Locale, ResourceBundle>();
private CalculatorMessages() { private CalculatorMessages() {
throw new AssertionError(); throw new AssertionError();
} }
@ -40,30 +41,26 @@ public final class CalculatorMessages {
} }
/* Arithmetic error occurred: {0} */ /* Arithmetic error occurred: {0} */
@NotNull
public static final String msg_001 = "msg_1"; public static final String msg_001 = "msg_1";
/* Too complex expression*/ /* Too complex expression*/
@NotNull
public static final String msg_002 = "msg_2"; public static final String msg_002 = "msg_2";
/* Too long execution time - check the expression*/ /* Too long execution time - check the expression*/
@NotNull
public static final String msg_003 = "msg_3"; public static final String msg_003 = "msg_3";
/* Evaluation was cancelled*/ /* Evaluation was cancelled*/
@NotNull
public static final String msg_004 = "msg_4"; public static final String msg_004 = "msg_4";
/* No parameters are specified for function: {0}*/ /* No parameters are specified for function: {0}*/
@NotNull
public static final String msg_005 = "msg_5"; public static final String msg_005 = "msg_5";
/* Infinite loop is detected in expression*/ /* Infinite loop is detected in expression*/
@NotNull
public static final String msg_006 = "msg_6"; public static final String msg_006 = "msg_6";
/* Error */ /* Error */
@NotNull
public static final String syntax_error = "syntax_error"; public static final String syntax_error = "syntax_error";
/* Result copied to clipboard! */
public static final String result_copied = "result_copied";
} }

View File

@ -0,0 +1,14 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.msg.Message;
/**
* User: serso
* Date: 9/22/12
* Time: 1:52 PM
*/
public interface CalculatorNotifier {
void showMessage(@NotNull Message message);
}

View File

@ -0,0 +1,24 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
/**
* 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(@NotNull String text) {
}
@Override
public void setText(@NotNull CharSequence text) {
}
}

View File

@ -0,0 +1,16 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.msg.Message;
/**
* User: serso
* Date: 9/22/12
* Time: 2:00 PM
*/
public class DummyCalculatorNotifier implements CalculatorNotifier {
@Override
public void showMessage(@NotNull Message message) {
}
}

View File

@ -5,4 +5,5 @@ msg_4=Evaluation was cancelled
msg_5=No parameters are specified for function: {0} msg_5=No parameters are specified for function: {0}
msg_6=Infinite loop is detected in expression msg_6=Infinite loop is detected in expression
syntax_error=Error syntax_error=Error
result_copied=Result copied to clipboard!

View File

@ -0,0 +1,43 @@
package org.solovyev.android.calculator;
import android.app.Application;
import android.content.Context;
import android.text.ClipboardManager;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 9/22/12
* Time: 1:35 PM
*/
public class AndroidCalculatorClipboard implements CalculatorClipboard {
@NotNull
private final Context context;
public AndroidCalculatorClipboard(@NotNull Application application) {
this.context = application;
}
@Override
public String getText() {
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
if ( clipboard.hasText() ) {
return String.valueOf(clipboard.getText());
} else {
return null;
}
}
@Override
public void setText(@NotNull String text) {
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}
@Override
public void setText(@NotNull CharSequence text) {
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}
}

View File

@ -1,150 +1,137 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
*/ */
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.os.Handler; import android.os.Handler;
import android.text.Html; import android.text.Html;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import jscl.math.Generic; import org.jetbrains.annotations.NotNull;
import jscl.math.function.Constant; import org.solovyev.android.calculator.model.CalculatorEngine;
import jscl.math.function.IConstant; import org.solovyev.android.calculator.text.TextProcessor;
import org.jetbrains.annotations.NotNull; import org.solovyev.android.calculator.view.TextHighlighter;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.view.AutoResizeTextView;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.text.TextProcessor; /**
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; * User: serso
import org.solovyev.android.calculator.view.TextHighlighter; * Date: 9/17/11
import org.solovyev.android.menu.LabeledMenuItem; * Time: 10:58 PM
import org.solovyev.android.view.AutoResizeTextView; */
import org.solovyev.common.collections.CollectionsUtils; public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView {
import java.util.HashSet; /*
import java.util.Set; **********************************************************************
*
/** * STATIC FIELDS
* User: serso *
* Date: 9/17/11 **********************************************************************
* Time: 10:58 PM */
*/
public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView { @NotNull
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
/*
********************************************************************** /*
* **********************************************************************
* STATIC FIELDS *
* * FIELDS
********************************************************************** *
*/ **********************************************************************
*/
@NotNull
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine()); @NotNull
private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance();
/*
********************************************************************** @NotNull
* private final Handler handler = new Handler();
* FIELDS
* /*
********************************************************************** **********************************************************************
*/ *
* CONSTRUCTORS
@NotNull *
private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance(); **********************************************************************
*/
@NotNull
private final Object lock = new Object(); public AndroidCalculatorDisplayView(Context context) {
super(context);
@NotNull }
private final Handler handler = new Handler();
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) {
/* super(context, attrs);
********************************************************************** }
*
* CONSTRUCTORS public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) {
* super(context, attrs, defStyle);
********************************************************************** }
*/
/*
public AndroidCalculatorDisplayView(Context context) { **********************************************************************
super(context); *
} * METHODS
*
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) { **********************************************************************
super(context, attrs); */
}
public boolean isValid() {
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) { synchronized (this) {
super(context, attrs, defStyle); return this.state.isValid();
} }
}
/*
********************************************************************** @Override
* public void setState(@NotNull final CalculatorDisplayViewState state) {
* METHODS handler.postDelayed(new Runnable() {
* @Override
********************************************************************** public void run() {
*/ synchronized (AndroidCalculatorDisplayView.this) {
AndroidCalculatorDisplayView.this.state = state;
public boolean isValid() { if ( state.isValid() ) {
synchronized (lock) { setTextColor(getResources().getColor(R.color.default_text_color));
return this.state.isValid(); setText(state.getStringResult());
} redraw();
} } else {
setTextColor(getResources().getColor(R.color.display_error_text_color));
@Override setText(state.getErrorMessage());
public void setState(@NotNull final CalculatorDisplayViewState state) { redraw();
handler.postDelayed(new Runnable() { }
@Override }
public void run() { }
synchronized (lock) { }, 1);
AndroidCalculatorDisplayView.this.state = state; }
if ( state.isValid() ) {
setTextColor(getResources().getColor(R.color.default_text_color)); @NotNull
setText(state.getStringResult()); @Override
redraw(); public CalculatorDisplayViewState getState() {
} else { synchronized (this) {
setTextColor(getResources().getColor(R.color.display_error_text_color)); return this.state;
setText(state.getErrorMessage()); }
redraw(); }
}
} private synchronized void redraw() {
} if (isValid()) {
}, 1); String text = getText().toString();
}
Log.d(this.getClass().getName(), text);
@NotNull
@Override try {
public CalculatorDisplayViewState getState() { TextHighlighter.Result result = textHighlighter.process(text);
synchronized (lock) { text = result.toString();
return this.state; } catch (CalculatorParseException e) {
} Log.e(this.getClass().getName(), e.getMessage(), e);
} }
private synchronized void redraw() { Log.d(this.getClass().getName(), text);
if (isValid()) { super.setText(Html.fromHtml(text), BufferType.EDITABLE);
String text = getText().toString(); }
Log.d(this.getClass().getName(), text); // todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize())
setAddEllipsis(false);
try { setMinTextSize(10);
TextHighlighter.Result result = textHighlighter.process(text); resizeText();
text = result.toString(); }
} catch (CalculatorParseException e) { }
Log.e(this.getClass().getName(), e.getMessage(), e);
}
Log.d(this.getClass().getName(), text);
super.setText(Html.fromHtml(text), BufferType.EDITABLE);
}
// todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize())
setAddEllipsis(false);
setMinTextSize(10);
resizeText();
}
}

View File

@ -9,9 +9,8 @@ import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build; import android.os.Build;
import android.text.Html; import android.os.Handler;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.widget.EditText; import android.widget.EditText;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -36,7 +35,12 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine()); private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine());
@NotNull @NotNull
private CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance(); private volatile CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance();
private volatile boolean viewStateChange = false;
@NotNull
private final Handler handler = new Handler();
public AndroidCalculatorEditorView(Context context) { public AndroidCalculatorEditorView(Context context) {
super(context); super(context);
@ -82,7 +86,9 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
menu.removeItem(android.R.id.selectAll); menu.removeItem(android.R.id.selectAll);
} }
public synchronized void redraw() { // todo serso: fix redraw
// Now problem is that calculator editor cursor position might be different than position of cursor in view (as some extra spaces can be inserted fur to number formatting)
/*private synchronized void redraw() {
String text = getText().toString(); String text = getText().toString();
int selectionStart = getSelectionStart(); int selectionStart = getSelectionStart();
@ -111,7 +117,7 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
int length = getText().length(); int length = getText().length();
setSelection(Math.max(Math.min(length, selectionStart), 0), Math.max(Math.min(length, selectionEnd), 0)); setSelection(Math.max(Math.min(length, selectionStart), 0), Math.max(Math.min(length, selectionEnd), 0));
} }*/
public boolean isHighlightText() { public boolean isHighlightText() {
return highlightText; return highlightText;
@ -119,7 +125,7 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
public void setHighlightText(boolean highlightText) { public void setHighlightText(boolean highlightText) {
this.highlightText = highlightText; this.highlightText = highlightText;
redraw(); //redraw();
} }
@Override @Override
@ -134,9 +140,33 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
} }
@Override @Override
public void setState(@NotNull CalculatorEditorViewState viewState) { public void setState(@NotNull final CalculatorEditorViewState viewState) {
this.viewState = viewState; handler.postDelayed(new Runnable() {
this.setText(viewState.getText()); @Override
this.setSelection(viewState.getSelection()); public void run() {
final AndroidCalculatorEditorView editorView = AndroidCalculatorEditorView.this;
synchronized (editorView) {
try {
editorView.viewStateChange = true;
editorView.viewState = viewState;
editorView.setText(viewState.getText());
editorView.setSelection(viewState.getSelection());
//redraw();
} finally {
editorView.viewStateChange = false;
}
}
}
}, 1);
}
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
synchronized (this) {
if (!viewStateChange) {
super.onSelectionChanged(selStart, selEnd);
CalculatorLocatorImpl.getInstance().getCalculatorEditor().setSelection(selStart);
}
}
} }
} }

View File

@ -0,0 +1,27 @@
package org.solovyev.android.calculator;
import android.app.Application;
import android.content.Context;
import android.widget.Toast;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.msg.Message;
/**
* User: serso
* Date: 9/22/12
* Time: 2:00 PM
*/
public class AndroidCalculatorNotifier implements CalculatorNotifier {
@NotNull
private final Context context;
public AndroidCalculatorNotifier(@NotNull Application application) {
this.context = application;
}
@Override
public void showMessage(@NotNull Message message) {
Toast.makeText(context, message.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
}

View File

@ -14,14 +14,16 @@ import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Vibrator; import android.os.Vibrator;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.text.Html; import android.text.Html;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.*; import android.view.*;
import android.widget.*; import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import jscl.AngleUnit; import jscl.AngleUnit;
import jscl.NumeralBase; import jscl.NumeralBase;
import net.robotmedia.billing.BillingController; import net.robotmedia.billing.BillingController;
@ -47,9 +49,9 @@ import org.solovyev.android.view.ColorButton;
import org.solovyev.android.view.drag.*; import org.solovyev.android.view.drag.*;
import org.solovyev.common.Announcer; import org.solovyev.common.Announcer;
import org.solovyev.common.equals.EqualsTool; import org.solovyev.common.equals.EqualsTool;
import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.math.Point2d; import org.solovyev.common.math.Point2d;
import org.solovyev.common.text.StringUtils; import org.solovyev.common.text.StringUtils;
import org.solovyev.common.history.HistoryAction;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -137,7 +139,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE); vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
AndroidCalculatorHistoryImpl.instance.load(this, preferences); AndroidCalculatorHistoryImpl.instance.load(this, preferences);
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance); calculatorModel = CalculatorModel.instance.init(this, preferences);
dpclRegister.clear(); dpclRegister.clear();
@ -292,7 +294,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor { private class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor {
private final DigitButtonDragProcessor processor = new DigitButtonDragProcessor(calculatorModel); private final DigitButtonDragProcessor processor = new DigitButtonDragProcessor(CalculatorLocatorImpl.getInstance().getCalculatorKeyboard());
@Override @Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, public boolean processDragEvent(@NotNull DragDirection dragDirection,
@ -381,7 +383,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
} }
private synchronized void setOnDragListeners(@NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) { private synchronized void setOnDragListeners(@NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) {
final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(calculatorModel), dragPreferences), vibrator, preferences); final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(CalculatorLocatorImpl.getInstance().getCalculatorKeyboard()), dragPreferences), vibrator, preferences);
final List<Integer> dragButtonIds = new ArrayList<Integer>(); final List<Integer> dragButtonIds = new ArrayList<Integer>();
final List<Integer> buttonIds = new ArrayList<Integer>(); final List<Integer> buttonIds = new ArrayList<Integer>();
@ -535,12 +537,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void eraseButtonClickHandler(@NotNull View v) { public void eraseButtonClickHandler(@NotNull View v) {
calculatorModel.doTextOperation(new CalculatorModel.TextOperation() { CalculatorLocatorImpl.getInstance().getCalculatorEditor().erase();
@Override
public void doOperation(@NotNull CalculatorEditor editor) {
editor.erase();
}
});
} }
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
@ -560,16 +557,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void pasteButtonClickHandler(@NotNull View v) { public void pasteButtonClickHandler(@NotNull View v) {
calculatorModel.doTextOperation(new CalculatorModel.TextOperation() { CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().pasteButtonPressed();
@Override }
public void doOperation(@NotNull CalculatorEditor editor) {
final ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
if (clipboard.hasText()) {
editor.insert(String.valueOf(clipboard.getText()));
}
}
});
}
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void copyButtonClickHandler(@NotNull View v) { public void copyButtonClickHandler(@NotNull View v) {
@ -578,14 +567,14 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void clearButtonClickHandler(@NotNull View v) { public void clearButtonClickHandler(@NotNull View v) {
calculatorModel.clear(); CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().clearButtonPressed();
} }
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void digitButtonClickHandler(@NotNull View v) { public void digitButtonClickHandler(@NotNull View v) {
Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed()); Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed());
if (((ColorButton) v).isShowText()) { if (((ColorButton) v).isShowText()) {
calculatorModel.processDigitButtonAction(((ColorButton) v).getText().toString()); CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().digitButtonPressed(((ColorButton) v).getText().toString());
} }
} }
@ -657,7 +646,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
AndroidUtils.restartActivity(this); AndroidUtils.restartActivity(this);
} }
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance); calculatorModel = CalculatorModel.instance.init(this, preferences);
calculatorModel.evaluate(); calculatorModel.evaluate();
} }
@ -753,28 +742,15 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor { private static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor {
@Override @Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) { public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
boolean result = false; final boolean result;
if ( dragDirection == DragDirection.left ) { if ( dragDirection == DragDirection.left ) {
CalculatorModel.instance.doTextOperation(new CalculatorModel.TextOperation() { CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().roundBracketsButtonPressed();
@Override
public void doOperation(@NotNull CalculatorEditor editor) {
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);
}
});
result = true; result = true;
} else { } else {
result = new DigitButtonDragProcessor(CalculatorModel.instance).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); result = new DigitButtonDragProcessor(CalculatorLocatorImpl.getInstance().getCalculatorKeyboard()).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent);
} }
return result; return result;
} }
} }

View File

@ -1,94 +1,96 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import net.robotmedia.billing.BillingController; import net.robotmedia.billing.BillingController;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.ads.AdsController; import org.solovyev.android.ads.AdsController;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
/** /**
* User: serso * User: serso
* Date: 12/1/11 * Date: 12/1/11
* Time: 1:21 PM * Time: 1:21 PM
*/ */
public class CalculatorApplication extends android.app.Application { public class CalculatorApplication extends android.app.Application {
private static final String paypalDonateUrl = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=se%2esolovyev%40gmail%2ecom&lc=RU&item_name=Android%20Calculator&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted"; private static final String paypalDonateUrl = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=se%2esolovyev%40gmail%2ecom&lc=RU&item_name=Android%20Calculator&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted";
public static final String AD_FREE_PRODUCT_ID = "ad_free"; public static final String AD_FREE_PRODUCT_ID = "ad_free";
public static final String AD_FREE_P_KEY = "org.solovyev.android.calculator_ad_free"; public static final String AD_FREE_P_KEY = "org.solovyev.android.calculator_ad_free";
public static final String ADMOB_USER_ID = "a14f02cf9c80cbc"; public static final String ADMOB_USER_ID = "a14f02cf9c80cbc";
public static final String REMOTE_STACK_TRACE_URL = "http://calculatorpp.com/crash_reports/upload.php"; public static final String REMOTE_STACK_TRACE_URL = "http://calculatorpp.com/crash_reports/upload.php";
@NotNull @NotNull
private static CalculatorApplication instance; private static CalculatorApplication instance;
public CalculatorApplication() { public CalculatorApplication() {
instance = this; instance = this;
} }
@NotNull @NotNull
public static CalculatorApplication getInstance() { public static CalculatorApplication getInstance() {
return instance; return instance;
} }
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
CalculatorLocatorImpl.getInstance().setCalculatorEngine(CalculatorEngine.instance); CalculatorLocatorImpl.getInstance().setCalculatorEngine(CalculatorEngine.instance);
CalculatorLocatorImpl.getInstance().setCalculatorNotifier(new AndroidCalculatorNotifier(this));
AdsController.getInstance().init(ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() { CalculatorLocatorImpl.getInstance().setCalculatorClipboard(new AndroidCalculatorClipboard(this));
@Override AdsController.getInstance().init(ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() {
public byte[] getObfuscationSalt() {
return new byte[]{81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7, -11, 53, 126, 82}; @Override
} public byte[] getObfuscationSalt() {
return new byte[]{81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7, -11, 53, 126, 82};
@Override }
public String getPublicKey() {
return CalculatorSecurity.getPK(); @Override
} public String getPublicKey() {
}); return CalculatorSecurity.getPK();
}
CalculatorEngine.instance.init(this, PreferenceManager.getDefaultSharedPreferences(this)); });
} CalculatorEngine.instance.init(this, PreferenceManager.getDefaultSharedPreferences(this));
public static void showDonationDialog(@NotNull final Context context) { }
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
final View view = layoutInflater.inflate(R.layout.donate, null); public static void showDonationDialog(@NotNull final Context context) {
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
final TextView donate = (TextView) view.findViewById(R.id.donateText); final View view = layoutInflater.inflate(R.layout.donate, null);
donate.setMovementMethod(LinkMovementMethod.getInstance());
final TextView donate = (TextView) view.findViewById(R.id.donateText);
final AlertDialog.Builder builder = new AlertDialog.Builder(context) donate.setMovementMethod(LinkMovementMethod.getInstance());
.setCancelable(true)
.setNegativeButton(R.string.c_cancel, null) final AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setPositiveButton(R.string.c_donate, new DialogInterface.OnClickListener() { .setCancelable(true)
@Override .setNegativeButton(R.string.c_cancel, null)
public void onClick(DialogInterface dialog, int which) { .setPositiveButton(R.string.c_donate, new DialogInterface.OnClickListener() {
final Intent i = new Intent(Intent.ACTION_VIEW); @Override
i.setData(Uri.parse(paypalDonateUrl)); public void onClick(DialogInterface dialog, int which) {
context.startActivity(i); final Intent i = new Intent(Intent.ACTION_VIEW);
} i.setData(Uri.parse(paypalDonateUrl));
}) context.startActivity(i);
.setView(view); }
})
builder.create().show(); .setView(view);
}
builder.create().show();
public static void registerOnRemoteStackTrace() { }
//Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(null, REMOTE_STACK_TRACE_URL));
} public static void registerOnRemoteStackTrace() {
} //Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(null, REMOTE_STACK_TRACE_URL));
}
}

View File

@ -9,23 +9,17 @@ import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.text.ClipboardManager;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.CursorControl; import org.solovyev.android.CursorControl;
import org.solovyev.android.calculator.history.AndroidCalculatorHistoryImpl; import org.solovyev.android.calculator.history.AndroidCalculatorHistoryImpl;
import org.solovyev.android.calculator.history.CalculatorHistoryState; import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.history.HistoryControl; import org.solovyev.android.history.HistoryControl;
import org.solovyev.common.history.HistoryAction; import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.text.StringUtils;
/** /**
* User: serso * User: serso
@ -45,17 +39,13 @@ public enum CalculatorModel implements HistoryControl<CalculatorHistoryState>, C
@NotNull @NotNull
private final CalculatorDisplay display; private final CalculatorDisplay display;
@NotNull
private CalculatorEngine calculatorEngine;
private CalculatorModel() { private CalculatorModel() {
display = CalculatorLocatorImpl.getInstance().getCalculatorDisplay(); display = CalculatorLocatorImpl.getInstance().getCalculatorDisplay();
editor = CalculatorLocatorImpl.getInstance().getCalculatorEditor(); editor = CalculatorLocatorImpl.getInstance().getCalculatorEditor();
} }
public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) { public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences) {
Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity); Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity);
this.calculatorEngine = calculator;
final AndroidCalculatorEditorView editorView = (AndroidCalculatorEditorView) activity.findViewById(R.id.calculatorEditor); final AndroidCalculatorEditorView editorView = (AndroidCalculatorEditorView) activity.findViewById(R.id.calculatorEditor);
editorView.init(preferences); editorView.init(preferences);
@ -66,14 +56,6 @@ public enum CalculatorModel implements HistoryControl<CalculatorHistoryState>, C
displayView.setOnClickListener(new CalculatorDisplayOnClickListener(activity)); displayView.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
display.setView(displayView); display.setView(displayView);
final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState();
if (lastState == null) {
saveHistoryState();
} else {
setCurrentHistoryState(lastState);
}
return this; return this;
} }
@ -96,62 +78,13 @@ public enum CalculatorModel implements HistoryControl<CalculatorHistoryState>, C
public static void copyResult(@NotNull Context context, public static void copyResult(@NotNull Context context,
@NotNull final CalculatorDisplayViewState viewState) { @NotNull final CalculatorDisplayViewState viewState) {
if (viewState.isValid()) { CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().copyButtonPressed();
final CharSequence text = viewState.getText();
if (!StringUtils.isEmpty(text)) {
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
clipboard.setText(text.toString());
Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show();
}
}
} }
private void saveHistoryState() { private void saveHistoryState() {
AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState()); AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState());
} }
public void doTextOperation(@NotNull TextOperation operation) {
operation.doOperation(CalculatorLocatorImpl.getInstance().getCalculatorEditor());
}
public void processDigitButtonAction(@Nullable final String text) {
if (!StringUtils.isEmpty(text)) {
doTextOperation(new CalculatorModel.TextOperation() {
@Override
public void doOperation(@NotNull CalculatorEditor editor) {
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;
}
}
editor.insert(textToBeInserted.toString());
editor.moveSelection(cursorPositionOffset);
}
});
}
}
@Override @Override
public void setCursorOnStart() { public void setCursorOnStart() {
this.editor.setCursorOnStart(); this.editor.setCursorOnStart();
@ -182,16 +115,6 @@ public enum CalculatorModel implements HistoryControl<CalculatorHistoryState>, C
CalculatorLocatorImpl.getInstance().getCalculator().evaluate(JsclOperation.simplify, this.editor.getViewState().getText()); CalculatorLocatorImpl.getInstance().getCalculator().evaluate(JsclOperation.simplify, this.editor.getViewState().getText());
} }
public void clear() {
// todo serso:
}
public static interface TextOperation {
void doOperation(@NotNull CalculatorEditor editor);
}
@Override @Override
public void doHistoryAction(@NotNull HistoryAction historyAction) { public void doHistoryAction(@NotNull HistoryAction historyAction) {
synchronized (AndroidCalculatorHistoryImpl.instance) { synchronized (AndroidCalculatorHistoryImpl.instance) {

View File

@ -20,17 +20,17 @@ import org.solovyev.common.math.Point2d;
*/ */
public class DigitButtonDragProcessor implements SimpleOnDragListener.DragProcessor { public class DigitButtonDragProcessor implements SimpleOnDragListener.DragProcessor {
@NotNull @NotNull
private final CalculatorModel calculatorModel; private CalculatorKeyboard calculatorKeyboard;
public DigitButtonDragProcessor(@NotNull CalculatorModel calculatorModel) { public DigitButtonDragProcessor(@NotNull CalculatorKeyboard calculatorKeyboard) {
this.calculatorModel = calculatorModel; this.calculatorKeyboard = calculatorKeyboard;
} }
@Override @Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) { public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
assert dragButton instanceof DirectionDragButton; assert dragButton instanceof DirectionDragButton;
calculatorModel.processDigitButtonAction(((DirectionDragButton) dragButton).getText(dragDirection)); calculatorKeyboard.digitButtonPressed(((DirectionDragButton) dragButton).getText(dragDirection));
return true; return true;
} }

View File

@ -19,7 +19,7 @@ import com.google.ads.AdView;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.ads.AdsController; import org.solovyev.android.ads.AdsController;
import org.solovyev.android.calculator.CalculatorModel; import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.AndroidMathRegistry; import org.solovyev.android.calculator.model.AndroidMathRegistry;
import org.solovyev.android.menu.AMenuBuilder; import org.solovyev.android.menu.AMenuBuilder;
@ -106,7 +106,7 @@ public abstract class AbstractMathEntityListActivity<T extends MathEntity> exten
final int position, final int position,
final long id) { final long id) {
CalculatorModel.instance.processDigitButtonAction(((MathEntity) parent.getItemAtPosition(position)).getName()); CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().digitButtonPressed(((MathEntity) parent.getItemAtPosition(position)).getName());
AbstractMathEntityListActivity.this.finish(); AbstractMathEntityListActivity.this.finish();
} }

View File

@ -12,7 +12,7 @@ import android.os.Bundle;
import android.text.ClipboardManager; import android.text.ClipboardManager;
import jscl.math.function.Function; import jscl.math.function.Function;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorModel; import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.menu.LabeledMenuItem; import org.solovyev.android.menu.LabeledMenuItem;
@ -33,7 +33,7 @@ public class CalculatorFunctionsActivity extends AbstractMathEntityListActivity<
use(R.string.c_use) { use(R.string.c_use) {
@Override @Override
public void onClick(@NotNull Function data, @NotNull Context context) { public void onClick(@NotNull Function data, @NotNull Context context) {
CalculatorModel.instance.processDigitButtonAction(data.getName()); CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().digitButtonPressed(data.getName());
if (context instanceof Activity) { if (context instanceof Activity) {
((Activity) context).finish(); ((Activity) context).finish();
} }

View File

@ -5,7 +5,7 @@ import android.content.Context;
import android.text.ClipboardManager; import android.text.ClipboardManager;
import jscl.math.operator.Operator; import jscl.math.operator.Operator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorModel; import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.menu.LabeledMenuItem; import org.solovyev.android.menu.LabeledMenuItem;
@ -28,7 +28,7 @@ public class CalculatorOperatorsActivity extends AbstractMathEntityListActivity<
use(R.string.c_use) { use(R.string.c_use) {
@Override @Override
public void onClick(@NotNull Operator data, @NotNull Context context) { public void onClick(@NotNull Operator data, @NotNull Context context) {
CalculatorModel.instance.processDigitButtonAction(data.getName()); CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().digitButtonPressed(data.getName());
if (context instanceof Activity) { if (context instanceof Activity) {
((Activity) context).finish(); ((Activity) context).finish();
} }

View File

@ -21,7 +21,7 @@ import android.widget.Toast;
import jscl.math.function.IConstant; import jscl.math.function.IConstant;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.CalculatorModel; import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
@ -46,7 +46,7 @@ public class CalculatorVarsActivity extends AbstractMathEntityListActivity<ICons
use(R.string.c_use) { use(R.string.c_use) {
@Override @Override
public void onClick(@NotNull IConstant data, @NotNull Context context) { public void onClick(@NotNull IConstant data, @NotNull Context context) {
CalculatorModel.instance.processDigitButtonAction(data.getName()); CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().digitButtonPressed(data.getName());
if (context instanceof Activity) { if (context instanceof Activity) {
((Activity) context).finish(); ((Activity) context).finish();
} }

View File

@ -6,14 +6,10 @@ import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.*;
import org.solovyev.math.units.Unit; import org.solovyev.math.units.Unit;
import org.solovyev.math.units.UnitImpl; import org.solovyev.math.units.UnitImpl;
import org.solovyev.android.calculator.AndroidNumeralBase;
import org.solovyev.android.calculator.CalculatorModel;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.ToJsclTextProcessor;
import org.solovyev.common.MutableObject; import org.solovyev.common.MutableObject;
import org.solovyev.common.text.StringUtils; import org.solovyev.common.text.StringUtils;
@ -72,7 +68,7 @@ public class NumeralBaseConverterDialog {
toUnitsValue = ((AndroidNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue; toUnitsValue = ((AndroidNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue;
} }
CalculatorModel.instance.processDigitButtonAction(toUnitsValue); CalculatorLocatorImpl.getInstance().getCalculatorKeyboard().digitButtonPressed(toUnitsValue);
final AlertDialog alertDialog = alertDialogHolder.getObject(); final AlertDialog alertDialog = alertDialogHolder.getObject();
if (alertDialog != null) { if (alertDialog != null) {
alertDialog.dismiss(); alertDialog.dismiss();