This commit is contained in:
serso 2011-09-17 00:52:54 +04:00
parent 2e10cdf4ff
commit 37b0688a95
28 changed files with 482 additions and 143 deletions

View File

@ -15,7 +15,7 @@
<LinearLayout a:layout_weight="2" a:layout_width="match_parent" a:layout_height="0dp"> <LinearLayout a:layout_weight="2" a:layout_width="match_parent" a:layout_height="0dp">
<EditText <org.solovyev.android.calculator.CalculatorEditText
a:id="@+id/editText" a:id="@+id/editText"
style="@style/display_style" style="@style/display_style"
a:inputType="textMultiLine" a:inputType="textMultiLine"

View File

@ -15,7 +15,7 @@
<LinearLayout a:layout_weight="2" a:layout_width="match_parent" a:layout_height="0dp"> <LinearLayout a:layout_weight="2" a:layout_width="match_parent" a:layout_height="0dp">
<EditText <org.solovyev.android.calculator.CalculatorEditText
a:id="@+id/editText" a:id="@+id/editText"
style="@style/display_style" style="@style/display_style"
a:inputType="textMultiLine" a:inputType="textMultiLine"

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.Activity; import android.app.Activity;
@ -16,8 +21,6 @@ import bsh.EvalError;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.view.*; import org.solovyev.android.view.*;
import org.solovyev.common.utils.Point2d;
import org.solovyev.common.utils.StringUtils;
import org.solovyev.common.utils.history.HistoryAction; import org.solovyev.common.utils.history.HistoryAction;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -33,10 +36,10 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster {
private List<SimpleOnDragListener> onDragListeners = new ArrayList<SimpleOnDragListener>(); private List<SimpleOnDragListener> onDragListeners = new ArrayList<SimpleOnDragListener>();
@NotNull @NotNull
private CalculatorView view; private CalculatorView calculatorView;
@NotNull @NotNull
private CalculatorModel calculator; private CalculatorModel calculatorModel;
@NotNull @NotNull
private BroadcastReceiver preferencesChangesReceiver; private BroadcastReceiver preferencesChangesReceiver;
@ -50,26 +53,17 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster {
setContentView(R.layout.main); setContentView(R.layout.main);
try { try {
this.calculator = new CalculatorModel(); this.calculatorModel = new CalculatorModel();
} catch (EvalError evalError) { } catch (EvalError evalError) {
// todo serso: create serso runtime exception // todo serso: create serso runtime exception
throw new RuntimeException("Could not initialize interpreter!"); throw new RuntimeException("Could not initialize interpreter!");
} }
this.view = new CalculatorView(this, this.calculator); this.calculatorView = new CalculatorView(this, this.calculatorModel);
final DragButtonCalibrationActivity.Preferences dragPreferences = DragButtonCalibrationActivity.getPreferences(this); final DragButtonCalibrationActivity.Preferences dragPreferences = DragButtonCalibrationActivity.getPreferences(this);
final SimpleOnDragListener onDragListener = new SimpleOnDragListener(new SimpleOnDragListener.DragProcessor() { final SimpleOnDragListener onDragListener = new SimpleOnDragListener(new DigitButtonDragProcessor(calculatorView), dragPreferences);
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
assert dragButton instanceof DirectionDragButton;
view.processButtonAction(getActionText((DirectionDragButton) dragButton, dragDirection));
return true;
}
}, dragPreferences);
onDragListeners.add(onDragListener); onDragListeners.add(onDragListener);
// todo serso: check if there is more convenient method for doing this // todo serso: check if there is more convenient method for doing this
@ -90,27 +84,11 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster {
} }
} }
final SimpleOnDragListener historyOnDragListener = new SimpleOnDragListener(new HistoryDragProcessor(), dragPreferences); final SimpleOnDragListener historyOnDragListener = new SimpleOnDragListener(new HistoryDragProcessor<CalculatorHistoryState>(this.calculatorView), dragPreferences);
((DragButton) findViewById(R.id.historyButton)).setOnDragListener(historyOnDragListener); ((DragButton) findViewById(R.id.historyButton)).setOnDragListener(historyOnDragListener);
onDragListeners.add(historyOnDragListener); onDragListeners.add(historyOnDragListener);
final SimpleOnDragListener toPositionOnDragListener = new SimpleOnDragListener(new SimpleOnDragListener.DragProcessor() { final SimpleOnDragListener toPositionOnDragListener = new SimpleOnDragListener(new CursorDragProcessor(calculatorView), dragPreferences);
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragButton instanceof DirectionDragButton) {
String text = ((DirectionDragButton) dragButton).getText(dragDirection);
if ("".equals(text)) {
CalculatorActivity.this.view.setCursorOnStart();
} else if ("".equals(text)) {
CalculatorActivity.this.view.setCursorOnEnd();
}
}
return result;
}
}, dragPreferences);
((DragButton) findViewById(R.id.rightButton)).setOnDragListener(toPositionOnDragListener); ((DragButton) findViewById(R.id.rightButton)).setOnDragListener(toPositionOnDragListener);
((DragButton) findViewById(R.id.leftButton)).setOnDragListener(toPositionOnDragListener); ((DragButton) findViewById(R.id.leftButton)).setOnDragListener(toPositionOnDragListener);
onDragListeners.add(toPositionOnDragListener); onDragListeners.add(toPositionOnDragListener);
@ -145,12 +123,12 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster {
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void numericButtonClickHandler(@NotNull View v) { public void numericButtonClickHandler(@NotNull View v) {
this.view.evaluate(); this.calculatorView.evaluate();
} }
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void eraseButtonClickHandler(@NotNull View v) { public void eraseButtonClickHandler(@NotNull View v) {
view.doTextOperation(new CalculatorView.TextOperation() { calculatorView.doTextOperation(new CalculatorView.TextOperation() {
@Override @Override
public void doOperation(@NotNull EditText editor) { public void doOperation(@NotNull EditText editor) {
if (editor.getSelectionStart() > 0) { if (editor.getSelectionStart() > 0) {
@ -167,17 +145,17 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster {
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void moveLeftButtonClickHandler(@NotNull View v) { public void moveLeftButtonClickHandler(@NotNull View v) {
view.moveCursorLeft(); calculatorView.moveCursorLeft();
} }
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void moveRightButtonClickHandler(@NotNull View v) { public void moveRightButtonClickHandler(@NotNull View v) {
view.moveCursorRight(); calculatorView.moveCursorRight();
} }
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void pasteButtonClickHandler(@NotNull View v) { public void pasteButtonClickHandler(@NotNull View v) {
view.doTextOperation(new CalculatorView.TextOperation() { calculatorView.doTextOperation(new CalculatorView.TextOperation() {
@Override @Override
public void doOperation(@NotNull EditText editor) { public void doOperation(@NotNull EditText editor) {
final ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); final ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
@ -190,64 +168,19 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster {
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void clearButtonClickHandler(@NotNull View v) { public void clearButtonClickHandler(@NotNull View v) {
view.clear(); calculatorView.clear();
} }
@SuppressWarnings({"UnusedDeclaration"}) @SuppressWarnings({"UnusedDeclaration"})
public void digitButtonClickHandler(@NotNull View v) { public void digitButtonClickHandler(@NotNull View v) {
view.processButtonAction(((DirectionDragButton) v).getTextMiddle()); Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed());
} calculatorView.processDigitButtonAction(((DirectionDragButton) v).getTextMiddle());
private final class HistoryDragProcessor implements SimpleOnDragListener.DragProcessor {
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
boolean result = false;
Log.d(String.valueOf(dragButton.getId()), "History on drag event start: " + dragDirection);
assert dragButton instanceof DirectionDragButton;
String actionText = getActionText((DirectionDragButton) dragButton, dragDirection);
if (!StringUtils.isEmpty(actionText)) {
try {
result = true;
final HistoryAction historyAction = HistoryAction.valueOf(actionText);
view.doHistoryAction(historyAction);
} catch (IllegalArgumentException e) {
Log.e(String.valueOf(dragButton.getId()), "Unsupported history action: " + actionText);
}
}
return result;
}
}
@Nullable
private static String getActionText(@NotNull DirectionDragButton dragButton, @NotNull DragDirection direction) {
final String result;
switch (direction) {
case up:
result = dragButton.getTextUp();
break;
case down:
result = dragButton.getTextDown();
break;
default:
result = null;
break;
}
return result;
} }
@Override @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) { if (keyCode == KeyEvent.KEYCODE_BACK) {
view.doHistoryAction(HistoryAction.undo); calculatorView.doHistoryAction(HistoryAction.undo);
return true; return true;
} }
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.text.Html;
import android.util.AttributeSet;
import android.widget.EditText;
import android.widget.TextView;
import org.solovyev.common.definitions.Pair;
import org.solovyev.common.exceptions.SersoException;
import org.solovyev.common.utils.CollectionsUtils;
import org.solovyev.util.math.MathEntityType;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* User: serso
* Date: 9/17/11
* Time: 12:25 AM
*/
public class CalculatorEditText extends EditText {
public CalculatorEditText(Context context) {
super(context);
}
public CalculatorEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CalculatorEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setTextColor(ColorStateList colors) {
super.setTextColor(colors); //To change body of overridden methods use File | Settings | File Templates.
}
@Override
public void setText(CharSequence text, BufferType type) {
/*try {
final List<Pair<Integer, Integer>> groupSymbols = new ArrayList<Pair<Integer, Integer>>();
final Stack<Pair<Integer, Integer>> groupSymbolsStack = new Stack<Pair<Integer, Integer>>();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if (MathEntityType.openGroupSymbols.contains(ch)) {
groupSymbolsStack.push(new Pair<Integer, Integer>(i, null));
} else if (MathEntityType.closeGroupSymbols.contains(ch)) {
final Pair<Integer, Integer> pair = groupSymbolsStack.pop();
if (pair != null) {
pair.setSecond(i);
groupSymbols.add(0, pair);
} else {
throw new NoPairGroupSymbolException();
}
}
}
text = insertHtml(text, groupSymbols);
} catch (NoPairGroupSymbolException e) {
// do nothing
}*/
super.setText(text, type);
}
private class NoPairGroupSymbolException extends SersoException {
}
}

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@ -1,8 +1,16 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.util.Log;
import bsh.EvalError; import bsh.EvalError;
import bsh.Interpreter; import bsh.Interpreter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.exceptions.SersoException;
import org.solovyev.common.utils.MathUtils; import org.solovyev.common.utils.MathUtils;
/** /**
@ -24,19 +32,28 @@ public class CalculatorModel {
interpreter.eval(Preprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands")); interpreter.eval(Preprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands"));
} }
public String evaluate(@NotNull JsclOperation operation, @NotNull String expression ) throws EvalError { public String evaluate(@NotNull JsclOperation operation, @NotNull String expression ) throws EvalError, ParseException {
final String preprocessedString = Preprocessor.process(String.valueOf(expression)); final String preprocessedExpression = Preprocessor.process(expression);
String result = String.valueOf(interpreter.eval(Preprocessor.wrap(operation, preprocessedString))).trim(); Log.d(CalculatorModel.class.getName(), "Preprocessed expression: " + preprocessedExpression);
Object evaluationObject = interpreter.eval(Preprocessor.wrap(operation, preprocessedExpression));
String result = String.valueOf(evaluationObject).trim();
try { try {
final Double dResult = Double.valueOf(result); final Double dResult = Double.valueOf(result);
result = String.valueOf(MathUtils.round(dResult, NUMBER_OF_FRACTION_DIGITS)); result = String.valueOf(MathUtils.round(dResult, NUMBER_OF_FRACTION_DIGITS));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
// do nothing => it's normal if sometimes we don't have doubles as result throw new ParseException(e);
} }
return result; return result;
} }
public static class ParseException extends SersoException {
public ParseException(Throwable cause) {
super(cause);
}
}
} }

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.Intent; import android.content.Intent;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.Activity; import android.app.Activity;
@ -5,6 +10,7 @@ import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.text.ClipboardManager; import android.text.ClipboardManager;
import android.text.InputType; import android.text.InputType;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.EditText; import android.widget.EditText;
@ -13,6 +19,9 @@ import android.widget.Toast;
import bsh.EvalError; import bsh.EvalError;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.view.CursorControl;
import org.solovyev.android.view.HistoryControl;
import org.solovyev.common.math.calculators.Calculator;
import org.solovyev.common.utils.MutableObject; import org.solovyev.common.utils.MutableObject;
import org.solovyev.common.utils.StringUtils; import org.solovyev.common.utils.StringUtils;
import org.solovyev.common.utils.history.HistoryAction; import org.solovyev.common.utils.history.HistoryAction;
@ -25,10 +34,13 @@ import org.solovyev.util.math.MathEntityType;
* Date: 9/12/11 * Date: 9/12/11
* Time: 11:15 PM * Time: 11:15 PM
*/ */
public class CalculatorView implements CursorControl{ public class CalculatorView implements CursorControl, HistoryControl<CalculatorHistoryState> {
// millis to wait before evaluation after user edit action
public static final int EVAL_DELAY_MILLIS = 1000;
@NotNull @NotNull
private final EditText editor; private final CalculatorEditText editor;
@NotNull @NotNull
private final TextView display; private final TextView display;
@ -37,18 +49,18 @@ public class CalculatorView implements CursorControl{
private final Activity activity; private final Activity activity;
@NotNull @NotNull
private final CalculatorModel calculator; private final CalculatorModel calculatorModel;
@NotNull @NotNull
private HistoryHelper<CalculatorHistoryState> history; private HistoryHelper<CalculatorHistoryState> history;
public CalculatorView(@NotNull final Activity activity, @NotNull CalculatorModel calculator) { public CalculatorView(@NotNull final Activity activity, @NotNull CalculatorModel calculator) {
this.activity = activity; this.activity = activity;
this.calculator = calculator; this.calculatorModel = calculator;
final InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); final InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
this.editor = (EditText) activity.findViewById(R.id.editText); this.editor = (CalculatorEditText) activity.findViewById(R.id.editText);
this.editor.setInputType(InputType.TYPE_NULL); this.editor.setInputType(InputType.TYPE_NULL);
imm.hideSoftInputFromWindow(this.editor.getWindowToken(), 0); imm.hideSoftInputFromWindow(this.editor.getWindowToken(), 0);
@ -117,13 +129,14 @@ public class CalculatorView implements CursorControl{
if (history.isUndoAvailable()) { if (history.isUndoAvailable()) {
history.undo(getCurrentHistoryState()); history.undo(getCurrentHistoryState());
} }
saveHistoryState(); saveHistoryState();
} }
} }
} }
}); });
new Handler().postDelayed(currentRunner.getObject(), 500); new Handler().postDelayed(currentRunner.getObject(), EVAL_DELAY_MILLIS);
saveHistoryState(); saveHistoryState();
} }
@ -136,15 +149,24 @@ public class CalculatorView implements CursorControl{
final Activity localActivity = activity; final Activity localActivity = activity;
try { try {
localDisplay.setText(calculator.evaluate(JsclOperation.numeric, expression)); Log.d(CalculatorView.class.getName(), "Trying to evaluate: " + expression);
} catch (EvalError evalError) { localDisplay.setText(calculatorModel.evaluate(JsclOperation.numeric, expression));
if (showError) { } catch (EvalError e) {
Toast.makeText(localActivity, R.string.syntax_error, Toast.LENGTH_SHORT).show(); handleEvaluationException(expression, showError, localDisplay, localActivity, e);
} } catch (CalculatorModel.ParseException e) {
handleEvaluationException(expression, showError, localDisplay, localActivity, e);
} }
} }
} }
private void handleEvaluationException(@NotNull String expression, boolean showError, @NotNull TextView localDisplay, @NotNull Activity localActivity, @NotNull Exception e) {
Log.d(CalculatorView.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e.getMessage());
localDisplay.setText("");
if (showError) {
Toast.makeText(localActivity, R.string.syntax_error, Toast.LENGTH_SHORT).show();
}
}
public void clear() { public void clear() {
if (!StringUtils.isEmpty(editor.getText()) || !StringUtils.isEmpty(editor.getText())) { if (!StringUtils.isEmpty(editor.getText()) || !StringUtils.isEmpty(editor.getText())) {
editor.getText().clear(); editor.getText().clear();
@ -157,7 +179,7 @@ public class CalculatorView implements CursorControl{
evaluate(editor.getText().toString(), true); evaluate(editor.getText().toString(), true);
} }
public void processButtonAction(@Nullable final String text) { public void processDigitButtonAction(@Nullable final String text) {
//Toast.makeText(CalculatorActivity.this, text, Toast.LENGTH_SHORT).show(); //Toast.makeText(CalculatorActivity.this, text, Toast.LENGTH_SHORT).show();
if (!StringUtils.isEmpty(text)) { if (!StringUtils.isEmpty(text)) {
@ -199,6 +221,7 @@ public class CalculatorView implements CursorControl{
} }
@Override
public void doHistoryAction(@NotNull HistoryAction historyAction) { public void doHistoryAction(@NotNull HistoryAction historyAction) {
if (history.isActionAvailable(historyAction)) { if (history.isActionAvailable(historyAction)) {
final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState()); final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState());
@ -208,6 +231,7 @@ public class CalculatorView implements CursorControl{
} }
} }
@Override
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
setValuesFromHistory(this.editor, editorHistoryState.getEditorState()); setValuesFromHistory(this.editor, editorHistoryState.getEditorState());
setValuesFromHistory(this.display, editorHistoryState.getDisplayState()); setValuesFromHistory(this.display, editorHistoryState.getDisplayState());
@ -220,6 +244,7 @@ public class CalculatorView implements CursorControl{
} }
} }
@Override
@NotNull @NotNull
public CalculatorHistoryState getCurrentHistoryState() { public CalculatorHistoryState getCurrentHistoryState() {
return new CalculatorHistoryState(getEditorHistoryState(this.editor), getEditorHistoryState(this.display)); return new CalculatorHistoryState(getEditorHistoryState(this.editor), getEditorHistoryState(this.display));

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator;
import android.view.MotionEvent;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.view.*;
import org.solovyev.common.utils.Point2d;
/**
* User: serso
* Date: 9/16/11
* Time: 11:45 PM
*/
public class CursorDragProcessor implements SimpleOnDragListener.DragProcessor{
@NotNull
private final CursorControl cursorControl;
public CursorDragProcessor(@NotNull CursorControl cursorControl) {
this.cursorControl = cursorControl;
}
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragButton instanceof DirectionDragButton) {
String text = ((DirectionDragButton) dragButton).getText(dragDirection);
if ("".equals(text)) {
cursorControl.setCursorOnStart();
} else if ("".equals(text)) {
cursorControl.setCursorOnEnd();
}
}
return result;
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator;
import android.view.MotionEvent;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.view.DirectionDragButton;
import org.solovyev.android.view.DragButton;
import org.solovyev.android.view.DragDirection;
import org.solovyev.android.view.SimpleOnDragListener;
import org.solovyev.common.utils.Point2d;
/**
* User: serso
* Date: 9/16/11
* Time: 11:48 PM
*/
public class DigitButtonDragProcessor implements SimpleOnDragListener.DragProcessor {
@NotNull
private final CalculatorView calculatorView;
public DigitButtonDragProcessor(@NotNull CalculatorView calculatorView) {
this.calculatorView = calculatorView;
}
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
assert dragButton instanceof DirectionDragButton;
calculatorView.processDigitButtonAction(((DirectionDragButton) dragButton).getDirectionText(dragDirection));
return true;
}
}

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.Activity; import android.app.Activity;
@ -203,20 +208,20 @@ public class DragButtonCalibrationActivity extends Activity {
case angle: case angle:
switch (dragDirection) { switch (dragDirection) {
case up: case up:
defaultMin = 150f; defaultMin = 130f;
defaultMax = 180f; defaultMax = 180f;
break; break;
case down: case down:
defaultMin = 0f; defaultMin = 0f;
defaultMax = 30f; defaultMax = 50f;
break; break;
default: default:
defaultMin = DEFAULT_VALUE; defaultMin = 0;
defaultMax = DEFAULT_VALUE; defaultMax = 0;
} }
break; break;
case distance: case distance:
defaultMin = 50f; defaultMin = 10f;
defaultMax = 150f; defaultMax = 150f;
break; break;
case duration: case duration:

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View File

@ -0,0 +1,17 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator;
import android.app.Activity;
/**
* User: serso
* Date: 9/16/11
* Time: 11:52 PM
*/
public class HelpActivity extends Activity {
// todo serso: implement
}

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
public enum JsclOperation { public enum JsclOperation {

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -57,9 +62,12 @@ public class Preprocessor {
if (mathTypeBefore != MathEntityType.binary_operation && if (mathTypeBefore != MathEntityType.binary_operation &&
mathTypeBefore != MathEntityType.unary_operation && mathTypeBefore != MathEntityType.unary_operation &&
!MathEntityType.openGroupSymbols.contains(chBefore)) { mathTypeBefore != MathEntityType.function &&
!MathEntityType.openGroupSymbols.contains(chBefore)) {
if (mathType == MathEntityType.constant || MathEntityType.openGroupSymbols.contains(ch)) { if (mathType == MathEntityType.constant ) {
sb.append("*");
} else if ( MathEntityType.openGroupSymbols.contains(ch) && mathTypeBefore != null ) {
sb.append("*"); sb.append("*");
} else if (mathType == MathEntityType.digit && mathTypeBefore != MathEntityType.digit && mathTypeBefore != MathEntityType.dot) { } else if (mathType == MathEntityType.digit && mathTypeBefore != MathEntityType.digit && mathTypeBefore != MathEntityType.dot) {
sb.append("*"); sb.append("*");

View File

@ -14,6 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view; package org.solovyev.android.view;
import android.content.Context; import android.content.Context;
@ -102,7 +107,7 @@ public class ColorButton extends Button {
measureText(); measureText();
} }
private void drawMagicFlame(int duration, Canvas canvas) { public void drawMagicFlame(int duration, Canvas canvas) {
int alpha = 255 - 255 * duration / CLICK_FEEDBACK_DURATION; int alpha = 255 - 255 * duration / CLICK_FEEDBACK_DURATION;
int color = CLICK_FEEDBACK_COLOR | (alpha << 24); int color = CLICK_FEEDBACK_COLOR | (alpha << 24);
@ -121,8 +126,6 @@ public class ColorButton extends Button {
drawMagicFlame(animDuration, canvas); drawMagicFlame(animDuration, canvas);
postInvalidateDelayed(CLICK_FEEDBACK_INTERVAL); postInvalidateDelayed(CLICK_FEEDBACK_INTERVAL);
} }
} else if (isPressed()) {
drawMagicFlame(0, canvas);
} }
CharSequence text = getText(); CharSequence text = getText();

View File

@ -1,4 +1,9 @@
package org.solovyev.android.calculator; /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view;
/** /**
* User: serso * User: serso

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view; package org.solovyev.android.view;
import android.content.Context; import android.content.Context;
@ -41,6 +46,27 @@ public class DirectionDragButton extends DragButton {
init(context, attrs); init(context, attrs);
} }
@Nullable
public String getDirectionText(@NotNull DragDirection direction) {
final String result;
switch (direction) {
case up:
result = this.getTextUp();
break;
case down:
result = this.getTextDown();
break;
default:
result = null;
break;
}
return result;
}
private void init(@NotNull Context context, @NotNull AttributeSet attrs) { private void init(@NotNull Context context, @NotNull AttributeSet attrs) {

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view; package org.solovyev.android.view;
import android.content.Context; import android.content.Context;
@ -71,24 +76,24 @@ public class DragButton extends ColorButton {
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
// stop tracking // stop tracking
if (localStartPoint != null && localOnDragListener.onDrag(DragButton.this, new DragEvent(localStartPoint, event))) { if (localStartPoint != null && localOnDragListener.onDrag(DragButton.this, new DragEvent(localStartPoint, event))) {
if (localOnDragListener.isSuppressOnClickEvent()) { if (localOnDragListener.isSuppressOnClickEvent()) {
// prevent on click action // prevent on click action
setPressed(false); setPressed(false);
}
// sometimes setPressed(false); doesn't work so to prevent onClick action button disables
if (v instanceof Button) {
final Button button = (Button) v;
if (v instanceof Button) { button.setEnabled(false);
final Button button = (Button)v;
button.setEnabled(false); new Handler().postDelayed(new Runnable() {
public void run() {
new Handler().postDelayed(new Runnable() { button.setEnabled(true);
public void run() { }
button.setEnabled(true); }, 300);
} }
}, 500);
} }
} }

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view; package org.solovyev.android.view;
public enum DragDirection { public enum DragDirection {

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view; package org.solovyev.android.view;
import android.view.MotionEvent; import android.view.MotionEvent;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view; package org.solovyev.android.view;
import android.widget.TextView; import android.widget.TextView;

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.utils.history.HistoryAction;
/**
* User: serso
* Date: 9/16/11
* Time: 11:42 PM
*/
public interface HistoryControl<T> {
void doHistoryAction(@NotNull HistoryAction historyAction);
void setCurrentHistoryState(@NotNull T editorHistoryState);
@NotNull
T getCurrentHistoryState();
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view;
import android.util.Log;
import android.view.MotionEvent;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.view.*;
import org.solovyev.common.utils.Point2d;
import org.solovyev.common.utils.StringUtils;
import org.solovyev.common.utils.history.HistoryAction;
/**
* User: serso
* Date: 9/16/11
* Time: 11:36 PM
*/
public class HistoryDragProcessor<T> implements SimpleOnDragListener.DragProcessor {
@NotNull
private final HistoryControl<T> historyControl;
public HistoryDragProcessor(@NotNull HistoryControl<T> historyControl) {
this.historyControl = historyControl;
}
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
boolean result = false;
Log.d(String.valueOf(dragButton.getId()), "History on drag event start: " + dragDirection);
assert dragButton instanceof DirectionDragButton;
String actionText = ((DirectionDragButton) dragButton).getDirectionText(dragDirection);
if (!StringUtils.isEmpty(actionText)) {
try {
result = true;
final HistoryAction historyAction = HistoryAction.valueOf(actionText);
historyControl.doHistoryAction(historyAction);
} catch (IllegalArgumentException e) {
Log.e(String.valueOf(dragButton.getId()), "Unsupported history action: " + actionText);
}
}
return result;
}
}

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view; package org.solovyev.android.view;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.view; package org.solovyev.android.view;
import android.util.Log; import android.util.Log;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.util.math; package org.solovyev.util.math;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.util.math; package org.solovyev.util.math;
import java.util.ArrayList; import java.util.ArrayList;
@ -48,21 +53,7 @@ public enum MathEntityType {
MathEntityType result = null; MathEntityType result = null;
if ( s.length() == 1 ) { if ( s.length() == 1 ) {
char ch = s.charAt(0); result = getType(s.charAt(0));
if ( Character.isDigit(ch) ) {
result = MathEntityType.digit;
} else if ( unaryOperations.contains(ch) ) {
result = MathEntityType.unary_operation;
} else if ( binaryOperations.contains(ch) ) {
result = MathEntityType.binary_operation;
} else if ( singleGroupSymbols.contains(ch) ) {
result = MathEntityType.group_symbol;
} else if ( constants.contains(ch) ) {
result = MathEntityType.constant;
} else if ( dots.contains(ch) ) {
result = MathEntityType.dot;
}
} }
if ( result == null ) { if ( result == null ) {
@ -76,4 +67,24 @@ public enum MathEntityType {
return result; return result;
} }
@Nullable
public static MathEntityType getType(char ch) {
MathEntityType result = null;
if ( Character.isDigit(ch) ) {
result = MathEntityType.digit;
} else if ( unaryOperations.contains(ch) ) {
result = MathEntityType.unary_operation;
} else if ( binaryOperations.contains(ch) ) {
result = MathEntityType.binary_operation;
} else if ( singleGroupSymbols.contains(ch) ) {
result = MathEntityType.group_symbol;
} else if ( constants.contains(ch) ) {
result = MathEntityType.constant;
} else if ( dots.contains(ch) ) {
result = MathEntityType.dot;
}
return result;
}
} }