some weird moving
This commit is contained in:
parent
7702fa3db9
commit
44be3bffa4
@ -1,153 +0,0 @@
|
||||
/* AUTO-GENERATED FILE. DO NOT MODIFY.
|
||||
*
|
||||
* This class was automatically generated by the
|
||||
* aapt tool from the resource data it found. It
|
||||
* should not be modified by hand.
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
public final class R {
|
||||
public static final class attr {
|
||||
/** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
|
||||
<p>This may also be a reference to a resource (in the form
|
||||
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
||||
theme attribute (in the form
|
||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||
containing a value of this type.
|
||||
*/
|
||||
public static final int textDown=0x7f010001;
|
||||
/** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
|
||||
<p>This may also be a reference to a resource (in the form
|
||||
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
||||
theme attribute (in the form
|
||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||
containing a value of this type.
|
||||
*/
|
||||
public static final int textUp=0x7f010000;
|
||||
}
|
||||
public static final class color {
|
||||
public static final int button_text=0x7f050001;
|
||||
public static final int magic_flame=0x7f050000;
|
||||
}
|
||||
public static final class drawable {
|
||||
public static final int blue_button=0x7f020000;
|
||||
public static final int button=0x7f020001;
|
||||
public static final int down=0x7f020002;
|
||||
public static final int icon=0x7f020003;
|
||||
public static final int light_blue_button=0x7f020004;
|
||||
public static final int not_ok=0x7f020005;
|
||||
public static final int ok=0x7f020006;
|
||||
public static final int up=0x7f020007;
|
||||
}
|
||||
public static final class id {
|
||||
public static final int calibrationArrowLeft=0x7f090001;
|
||||
public static final int calibrationArrowRight=0x7f090004;
|
||||
public static final int calibrationButtonLeft=0x7f090002;
|
||||
public static final int calibrationButtonRight=0x7f090003;
|
||||
public static final int calibrationStart=0x7f090005;
|
||||
public static final int clearButton=0x7f09001d;
|
||||
public static final int divisionButton=0x7f090010;
|
||||
public static final int editText=0x7f090006;
|
||||
public static final int eigthDigitButton=0x7f090012;
|
||||
public static final int equalsButton=0x7f090007;
|
||||
public static final int eraseButton=0x7f090019;
|
||||
public static final int fiveDigitButton=0x7f09000e;
|
||||
public static final int fourDigitButton=0x7f09000d;
|
||||
public static final int leftButton=0x7f09001a;
|
||||
public static final int menu_item_help=0x7f09001f;
|
||||
public static final int menu_item_settings=0x7f09001e;
|
||||
public static final int muliplicationButton=0x7f09000c;
|
||||
public static final int nineDigitButton=0x7f090013;
|
||||
public static final int oneDigitButton=0x7f090009;
|
||||
public static final int pasteButton=0x7f09001c;
|
||||
public static final int plusButton=0x7f090014;
|
||||
public static final int resultEditText=0x7f090008;
|
||||
public static final int rightButton=0x7f09001b;
|
||||
public static final int roundBracketsButton=0x7f090015;
|
||||
public static final int sevenDigitButton=0x7f090011;
|
||||
public static final int simplePad=0x7f090000;
|
||||
public static final int sixDigitButton=0x7f09000f;
|
||||
public static final int squareBracketsButton=0x7f090017;
|
||||
public static final int subtractionButton=0x7f090018;
|
||||
public static final int threeDigitButton=0x7f09000b;
|
||||
public static final int twoDigitButton=0x7f09000a;
|
||||
public static final int zeroDigitButton=0x7f090016;
|
||||
}
|
||||
public static final class layout {
|
||||
public static final int drag_button_calibration=0x7f030000;
|
||||
public static final int main=0x7f030001;
|
||||
}
|
||||
public static final class menu {
|
||||
public static final int main_menu=0x7f080000;
|
||||
}
|
||||
public static final class string {
|
||||
public static final int c_app_name=0x7f060000;
|
||||
public static final int c_app_settings=0x7f060001;
|
||||
public static final int c_down=0x7f060008;
|
||||
public static final int c_help=0x7f060004;
|
||||
public static final int c_prefs_drag_button_calibration=0x7f060006;
|
||||
public static final int c_prefs_drag_button_calibration_summary=0x7f060007;
|
||||
public static final int c_prefs_main_category=0x7f060005;
|
||||
public static final int c_restart=0x7f06000a;
|
||||
public static final int c_settings=0x7f060003;
|
||||
public static final int c_up=0x7f060009;
|
||||
public static final int syntax_error=0x7f060002;
|
||||
}
|
||||
public static final class style {
|
||||
public static final int button_small_style=0x7f070004;
|
||||
public static final int button_style=0x7f070001;
|
||||
public static final int controlButtonStyle=0x7f070003;
|
||||
public static final int digitButtonStyle=0x7f070002;
|
||||
public static final int display_style=0x7f070005;
|
||||
public static final int editTextInputStyle=0x7f070000;
|
||||
}
|
||||
public static final class xml {
|
||||
public static final int preferences=0x7f040000;
|
||||
}
|
||||
public static final class styleable {
|
||||
/** Attributes that can be used with a DragButton.
|
||||
<p>Includes the following attributes:</p>
|
||||
<table>
|
||||
<colgroup align="left" />
|
||||
<colgroup align="left" />
|
||||
<tr><th>Attribute</th><th>Description</th></tr>
|
||||
<tr><td><code>{@link #DragButton_textDown org.solovyev.android.calculator:textDown}</code></td><td></td></tr>
|
||||
<tr><td><code>{@link #DragButton_textUp org.solovyev.android.calculator:textUp}</code></td><td></td></tr>
|
||||
</table>
|
||||
@see #DragButton_textDown
|
||||
@see #DragButton_textUp
|
||||
*/
|
||||
public static final int[] DragButton = {
|
||||
0x7f010000, 0x7f010001
|
||||
};
|
||||
/**
|
||||
<p>This symbol is the offset where the {@link org.solovyev.android.calculator.R.attr#textDown}
|
||||
attribute's value can be found in the {@link #DragButton} array.
|
||||
|
||||
|
||||
<p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
|
||||
<p>This may also be a reference to a resource (in the form
|
||||
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
||||
theme attribute (in the form
|
||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||
containing a value of this type.
|
||||
@attr name android:textDown
|
||||
*/
|
||||
public static final int DragButton_textDown = 1;
|
||||
/**
|
||||
<p>This symbol is the offset where the {@link org.solovyev.android.calculator.R.attr#textUp}
|
||||
attribute's value can be found in the {@link #DragButton} array.
|
||||
|
||||
|
||||
<p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
|
||||
<p>This may also be a reference to a resource (in the form
|
||||
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
|
||||
theme attribute (in the form
|
||||
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
|
||||
containing a value of this type.
|
||||
@attr name android:textUp
|
||||
*/
|
||||
public static final int DragButton_textUp = 0;
|
||||
};
|
||||
}
|
@ -1,426 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.text.ClipboardManager;
|
||||
import android.text.InputType;
|
||||
import android.util.TypedValue;
|
||||
import android.view.*;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.view.*;
|
||||
import org.solovyev.util.StringUtils;
|
||||
import org.solovyev.util.math.MathEntityType;
|
||||
|
||||
import bsh.EvalError;
|
||||
import bsh.Interpreter;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.EditText;
|
||||
import org.solovyev.util.math.MathUtils;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
public class CalculatorActivity extends Activity implements FontSizeAdjuster {
|
||||
|
||||
private static final int HVGA_WIDTH_PIXELS = 320;
|
||||
|
||||
@NotNull
|
||||
private EditText editText;
|
||||
|
||||
@NotNull
|
||||
private TextView resultEditText;
|
||||
|
||||
@NotNull
|
||||
private Interpreter interpreter;
|
||||
|
||||
@NotNull
|
||||
private HistoryHelper<CalculatorHistoryState> historyHelper;
|
||||
|
||||
@NotNull
|
||||
private BroadcastReceiver preferencesChangesReceiver;
|
||||
|
||||
@NotNull
|
||||
private List<SimpleOnDragListener> onDragListeners = new ArrayList<SimpleOnDragListener>();
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
|
||||
this.editText = (EditText) findViewById(R.id.editText);
|
||||
this.editText.setInputType(InputType.TYPE_NULL);
|
||||
imm.hideSoftInputFromWindow(this.editText.getWindowToken(), 0);
|
||||
|
||||
this.resultEditText = (TextView) findViewById(R.id.resultEditText);
|
||||
this.resultEditText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final CharSequence text = ((TextView) v).getText();
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
Toast.makeText(CalculatorActivity.this, "Result copied to clipboard!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
final DragButtonCalibrationActivity.Preferences dragPreferences = DragButtonCalibrationActivity.getPreferences(this);
|
||||
|
||||
final SimpleOnDragListener onDragListener = new SimpleOnDragListener(new SimpleOnDragListener.DragProcessor() {
|
||||
@Override
|
||||
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
|
||||
assert dragButton instanceof DirectionDragButton;
|
||||
processButtonAction(dragButton, getActionText((DirectionDragButton) dragButton, dragDirection));
|
||||
return true;
|
||||
}
|
||||
|
||||
}, dragPreferences);
|
||||
|
||||
onDragListeners.add(onDragListener);
|
||||
|
||||
// todo serso: check if there is more convenient method for doing this
|
||||
final R.id ids = new R.id();
|
||||
for (Field field : R.id.class.getDeclaredFields()) {
|
||||
int modifiers = field.getModifiers();
|
||||
if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
|
||||
try {
|
||||
final View view = findViewById(field.getInt(ids));
|
||||
if (view instanceof DragButton) {
|
||||
((DragButton) view).setOnDragListener(onDragListener);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(CalculatorActivity.class.getName(), e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(CalculatorActivity.class.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final SimpleOnDragListener historyOnDragListener = new SimpleOnDragListener(new HistoryDragProcessor(), dragPreferences);
|
||||
((DragButton) findViewById(R.id.clearButton)).setOnDragListener(historyOnDragListener);
|
||||
((DragButton) findViewById(R.id.pasteButton)).setOnDragListener(historyOnDragListener);
|
||||
onDragListeners.add(historyOnDragListener);
|
||||
|
||||
final SimpleOnDragListener toPositionOnDragListener = new SimpleOnDragListener(new SimpleOnDragListener.DragProcessor() {
|
||||
@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.editText.setSelection(0);
|
||||
} else if ("↠".equals(text)) {
|
||||
CalculatorActivity.this.editText.setSelection(CalculatorActivity.this.editText.getText().length());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}, dragPreferences);
|
||||
((DragButton) findViewById(R.id.rightButton)).setOnDragListener(toPositionOnDragListener);
|
||||
((DragButton) findViewById(R.id.leftButton)).setOnDragListener(toPositionOnDragListener);
|
||||
onDragListeners.add(toPositionOnDragListener);
|
||||
|
||||
this.interpreter = new Interpreter();
|
||||
|
||||
try {
|
||||
interpreter.eval(Preprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands"));
|
||||
} catch (EvalError e) {
|
||||
Log.e(CalculatorActivity.class.getName(), e.getMessage());
|
||||
}
|
||||
|
||||
this.historyHelper = new SimpleHistoryHelper<CalculatorHistoryState>();
|
||||
saveHistoryState();
|
||||
|
||||
this.preferencesChangesReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
if (DragButtonCalibrationActivity.INTENT_ACTION.equals(intent.getAction())) {
|
||||
final DragButtonCalibrationActivity.Preferences preferences = DragButtonCalibrationActivity.getPreferences(CalculatorActivity.this);
|
||||
for (SimpleOnDragListener dragListener : onDragListeners) {
|
||||
dragListener.setPreferences(preferences);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
registerReceiver(this.preferencesChangesReceiver, new IntentFilter(DragButtonCalibrationActivity.INTENT_ACTION));
|
||||
}
|
||||
|
||||
private void saveHistoryState() {
|
||||
historyHelper.addState(getCurrentHistoryState());
|
||||
}
|
||||
|
||||
public void elementaryButtonClickHandler(@NotNull View v) {
|
||||
eval(JsclOperation.elementary, true);
|
||||
}
|
||||
|
||||
public void numericButtonClickHandler(@NotNull View v) {
|
||||
eval(JsclOperation.numeric, true);
|
||||
}
|
||||
|
||||
public void eraseButtonClickHandler(@NotNull View v) {
|
||||
if (editText.getSelectionStart() > 0) {
|
||||
editText.getText().delete(editText.getSelectionStart() - 1, editText.getSelectionStart());
|
||||
saveHistoryState();
|
||||
}
|
||||
}
|
||||
|
||||
public void simplifyButtonClickHandler(@NotNull View v) {
|
||||
eval(JsclOperation.simplify, true);
|
||||
}
|
||||
|
||||
public void moveLeftButtonClickHandler(@NotNull View v) {
|
||||
if (editText.getSelectionStart() > 0) {
|
||||
editText.setSelection(editText.getSelectionStart() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void moveRightButtonClickHandler(@NotNull View v) {
|
||||
if (editText.getSelectionStart() < editText.getText().length()) {
|
||||
editText.setSelection(editText.getSelectionStart() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void pasteButtonClickHandler(@NotNull View v) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
if ( clipboard.hasText() ) {
|
||||
editText.getText().insert(editText.getSelectionStart(), clipboard.getText());
|
||||
eval(JsclOperation.numeric, false);
|
||||
saveHistoryState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clearButtonClickHandler(@NotNull View v) {
|
||||
if (!StringUtils.isEmpty(editText.getText()) || !StringUtils.isEmpty(resultEditText.getText())) {
|
||||
editText.getText().clear();
|
||||
resultEditText.setText("");
|
||||
saveHistoryState();
|
||||
}
|
||||
}
|
||||
|
||||
private void eval(@NotNull JsclOperation operation, boolean showError) {
|
||||
try {
|
||||
final String preprocessedString = Preprocessor.process(String.valueOf(editText.getText()));
|
||||
|
||||
String result = String.valueOf(interpreter.eval(Preprocessor.wrap(operation, preprocessedString))).trim();
|
||||
|
||||
try {
|
||||
final Double dResult = Double.valueOf(result);
|
||||
result = String.valueOf(MathUtils.round(dResult, 5));
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
|
||||
resultEditText.setText(result);
|
||||
|
||||
// result editor might be changed (but main editor - no) => make undo and add new state with saved result
|
||||
CalculatorHistoryState currentHistoryState = getCurrentHistoryState();
|
||||
if (this.historyHelper.isUndoAvailable()) {
|
||||
this.historyHelper.undo(currentHistoryState);
|
||||
}
|
||||
|
||||
this.historyHelper.addState(currentHistoryState);
|
||||
|
||||
} catch (EvalError e) {
|
||||
if (showError) {
|
||||
Toast.makeText(CalculatorActivity.this, R.string.syntax_error, Toast.LENGTH_SHORT).show();
|
||||
Log.e(CalculatorActivity.class.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void digitButtonClickHandler(@NotNull View v) {
|
||||
processButtonAction(v, ((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);
|
||||
doHistoryAction(historyAction);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(String.valueOf(dragButton.getId()), "Unsupported history action: " + actionText);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void doHistoryAction(@NotNull HistoryAction historyAction) {
|
||||
if (historyHelper.isActionAvailable(historyAction)) {
|
||||
final CalculatorHistoryState newState = historyHelper.doAction(historyAction, getCurrentHistoryState());
|
||||
if (newState != null) {
|
||||
setCurrentHistoryState(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
|
||||
setValuesFromHistory(this.editText, editorHistoryState.getEditorState());
|
||||
setValuesFromHistory(this.resultEditText, editorHistoryState.getResultEditorState());
|
||||
}
|
||||
|
||||
private void setValuesFromHistory(@NotNull TextView editText, EditorHistoryState editorHistoryState) {
|
||||
editText.setText(editorHistoryState.getText());
|
||||
if (editText instanceof EditText) {
|
||||
((EditText) editText).setSelection(editorHistoryState.getCursorPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CalculatorHistoryState getCurrentHistoryState() {
|
||||
return new CalculatorHistoryState(getEditorHistoryState(this.editText), getEditorHistoryState(this.resultEditText));
|
||||
}
|
||||
|
||||
private EditorHistoryState getEditorHistoryState(@NotNull TextView textView) {
|
||||
final EditorHistoryState result = new EditorHistoryState();
|
||||
|
||||
result.setText(String.valueOf(textView.getText()));
|
||||
result.setCursorPosition(textView.getSelectionStart());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void processButtonAction(@NotNull View v, @Nullable String text) {
|
||||
//Toast.makeText(CalculatorActivity.this, text, Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
final MathEntityType type = MathEntityType.getType(text);
|
||||
|
||||
int cursorPositionOffset = 0;
|
||||
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case function:
|
||||
text += "()";
|
||||
cursorPositionOffset = -1;
|
||||
break;
|
||||
case group_symbols:
|
||||
cursorPositionOffset = -1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.editText.getText().insert(this.editText.getSelectionStart(), text);
|
||||
this.editText.setSelection(this.editText.getSelectionStart() + cursorPositionOffset, this.editText.getSelectionEnd() + cursorPositionOffset);
|
||||
saveHistoryState();
|
||||
eval(JsclOperation.numeric, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
doHistoryAction(HistoryAction.undo);
|
||||
return true;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// todo serso: inflate menu as soon as it will implemented in proper way
|
||||
/* final MenuInflater menuInflater = getMenuInflater();
|
||||
menuInflater.inflate(R.menu.main_menu, menu);*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
boolean result;
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_item_settings:
|
||||
showSettings();
|
||||
result = true;
|
||||
case R.id.menu_item_help:
|
||||
showHelp();
|
||||
result = true;
|
||||
default:
|
||||
result = super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void showSettings() {
|
||||
startActivity(new Intent(this, CalculatorPreferencesActivity.class));
|
||||
}
|
||||
|
||||
private void showHelp() {
|
||||
Log.d(CalculatorActivity.class + "showHelp()", "Show help!");
|
||||
}
|
||||
|
||||
/**
|
||||
* The font sizes in the layout files are specified for a HVGA display.
|
||||
* Adjust the font sizes accordingly if we are running on a different
|
||||
* display.
|
||||
*/
|
||||
@Override
|
||||
public void adjustFontSize(@NotNull TextView view) {
|
||||
float fontPixelSize = view.getTextSize();
|
||||
Display display = getWindowManager().getDefaultDisplay();
|
||||
int h = Math.min(display.getWidth(), display.getHeight());
|
||||
float ratio = (float) h / HVGA_WIDTH_PIXELS;
|
||||
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontPixelSize * ratio);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/11/11
|
||||
* Time: 12:16 AM
|
||||
*/
|
||||
public class CalculatorHistoryState {
|
||||
|
||||
@NotNull
|
||||
private EditorHistoryState editorState;
|
||||
|
||||
@NotNull
|
||||
private EditorHistoryState resultEditorState;
|
||||
|
||||
public CalculatorHistoryState(@NotNull EditorHistoryState editorState, @NotNull EditorHistoryState resultEditorState) {
|
||||
this.editorState = editorState;
|
||||
this.resultEditorState = resultEditorState;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public EditorHistoryState getEditorState() {
|
||||
return editorState;
|
||||
}
|
||||
|
||||
public void setEditorState(@NotNull EditorHistoryState editorState) {
|
||||
this.editorState = editorState;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public EditorHistoryState getResultEditorState() {
|
||||
return resultEditorState;
|
||||
}
|
||||
|
||||
public void setResultEditorState(@NotNull EditorHistoryState resultEditorState) {
|
||||
this.resultEditorState = resultEditorState;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 7/16/11
|
||||
* Time: 6:37 PM
|
||||
*/
|
||||
public class CalculatorPreferencesActivity extends PreferenceActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
final Preference dragButtonCalibration = findPreference("dragButtonCalibration");
|
||||
dragButtonCalibration.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
startActivity(new Intent(CalculatorPreferencesActivity.this, DragButtonCalibrationActivity.class));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle state) {
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
}
|
@ -1,393 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.view.*;
|
||||
import org.solovyev.common.collections.ManyValuedHashMap;
|
||||
import org.solovyev.common.collections.ManyValuedMap;
|
||||
import org.solovyev.common.utils.Interval;
|
||||
import org.solovyev.util.math.MathUtils;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 7/16/11
|
||||
* Time: 7:28 PM
|
||||
*/
|
||||
public class DragButtonCalibrationActivity extends Activity {
|
||||
|
||||
@NotNull
|
||||
private final List<DragData> dragHistory = new ArrayList<DragData>();
|
||||
|
||||
private final Map<DragButton, CalibrationArrow> map = new HashMap<DragButton, CalibrationArrow>();
|
||||
|
||||
public static final String PREFERENCES = "dragButtonPreferences";
|
||||
|
||||
public static final String PREFERENCES_FIRST_RUN = "firstRun";
|
||||
|
||||
public static final String PREFERENCES_MIN = "min";
|
||||
public static final String PREFERENCES_MAX = "max";
|
||||
|
||||
private static final float DEFAULT_VALUE = -999;
|
||||
private static final int MIN_HISTORY_FOR_CALIBRATION = 10;
|
||||
public static final String INTENT_ACTION = "org.solovyev.android.calculator.DragButtonPreferencesChanged";
|
||||
|
||||
public static enum PreferenceType {
|
||||
angle,
|
||||
distance,
|
||||
duration
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.drag_button_calibration);
|
||||
|
||||
createCalibrationButton(R.id.calibrationButtonRight, R.id.calibrationArrowRight);
|
||||
createCalibrationButton(R.id.calibrationButtonLeft, R.id.calibrationArrowLeft);
|
||||
}
|
||||
|
||||
private void createCalibrationButton(int buttonId, int arrowId) {
|
||||
final DragButton calibrationButton = (DragButton) findViewById(buttonId);
|
||||
calibrationButton.setOnDragListener(new CalibrationOnDragListener());
|
||||
|
||||
ImageView imageView = (ImageView) findViewById(arrowId);
|
||||
CalibrationArrow calibrationArrow = new CalibrationArrow(imageView);
|
||||
|
||||
createDragDirection(0, calibrationArrow);
|
||||
|
||||
map.put(calibrationButton, calibrationArrow);
|
||||
}
|
||||
|
||||
private void createDragDirection(long timeout, @NotNull final CalibrationArrow calibrationArrow) {
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
public void run() {
|
||||
calibrationArrow.dragDirection = Math.random() > 0.5 ? DragDirection.up : DragDirection.down;
|
||||
|
||||
calibrationArrow.calibrationArrow.setImageResource(calibrationArrow.dragDirection == DragDirection.down ? R.drawable.down : R.drawable.up);
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
public void restartClickHandler(View v) {
|
||||
for (CalibrationArrow calibrationArrow : map.values()) {
|
||||
createDragDirection(0, calibrationArrow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class CalibrationOnDragListener implements OnDragListener {
|
||||
|
||||
@Override
|
||||
public boolean isSuppressOnClickEvent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||
final Point2d startPoint = event.getStartPoint();
|
||||
final MotionEvent motionEvent = event.getMotionEvent();
|
||||
|
||||
// init end point
|
||||
final Point2d endPoint = new Point2d(motionEvent.getX(), motionEvent.getY());
|
||||
|
||||
float distance = MathUtils.getDistance(startPoint, endPoint);
|
||||
|
||||
double angle = Math.toDegrees(MathUtils.getAngle(startPoint, MathUtils.sum(startPoint, SimpleOnDragListener.axis), endPoint));
|
||||
|
||||
final CalibrationArrow calibrationArrow = map.get(dragButton);
|
||||
final DragDirection dragDirection = calibrationArrow.dragDirection;
|
||||
|
||||
assert dragDirection == DragDirection.up || dragDirection == DragDirection.down;
|
||||
|
||||
double deviationAngle = angle;
|
||||
if (dragDirection == DragDirection.up) {
|
||||
deviationAngle = 180 - deviationAngle;
|
||||
}
|
||||
|
||||
if (deviationAngle > 45) {
|
||||
calibrationArrow.calibrationArrow.setImageResource(R.drawable.not_ok);
|
||||
} else {
|
||||
calibrationArrow.calibrationArrow.setImageResource(R.drawable.ok);
|
||||
dragHistory.add(new DragData(dragDirection, distance, angle, (motionEvent.getEventTime() - motionEvent.getDownTime())));
|
||||
}
|
||||
|
||||
createDragDirection(500, calibrationArrow);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
|
||||
if (dragHistory.size() > MIN_HISTORY_FOR_CALIBRATION) {
|
||||
final ManyValuedMap<DragDirection, Double> anglesByDirection = new ManyValuedHashMap<DragDirection, Double>();
|
||||
final ManyValuedMap<DragDirection, Double> distancesByDirection = new ManyValuedHashMap<DragDirection, Double>();
|
||||
final ManyValuedMap<DragDirection, Double> timesByDirection = new ManyValuedHashMap<DragDirection, Double>();
|
||||
for (DragData dragData : dragHistory) {
|
||||
anglesByDirection.put(dragData.getDirection(), dragData.getAngle());
|
||||
distancesByDirection.put(dragData.getDirection(), (double) dragData.getDistance());
|
||||
timesByDirection.put(dragData.getDirection(), dragData.getTime());
|
||||
}
|
||||
|
||||
final Map<DragDirection, MathUtils.StatData> angleStatData = getStatDataByDirection(anglesByDirection);
|
||||
final Map<DragDirection, MathUtils.StatData> distanceStatData = getStatDataByDirection(distancesByDirection);
|
||||
final Map<DragDirection, MathUtils.StatData> timeStatData = getStatDataByDirection(timesByDirection);
|
||||
|
||||
Log.d(this.getClass().getName(), "Angle statistics: ");
|
||||
logStatData(angleStatData);
|
||||
|
||||
Log.d(this.getClass().getName(), "Distance statistics: ");
|
||||
logStatData(distanceStatData);
|
||||
|
||||
Log.d(this.getClass().getName(), "Time statistics: ");
|
||||
logStatData(timeStatData);
|
||||
|
||||
final SharedPreferences settings = getSharedPreferences(PREFERENCES, 0);
|
||||
final SharedPreferences.Editor editor = settings.edit();
|
||||
|
||||
setPreferences(angleStatData, editor, PreferenceType.angle);
|
||||
setPreferences(distanceStatData, editor, PreferenceType.distance);
|
||||
setPreferences(timeStatData, editor, PreferenceType.duration);
|
||||
|
||||
editor.commit();
|
||||
|
||||
sendOrderedBroadcast(new Intent(INTENT_ACTION), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
private void setPreferences(@NotNull Map<DragDirection, MathUtils.StatData> statData, @NotNull SharedPreferences.Editor editor, @NotNull PreferenceType preferenceType) {
|
||||
for (Map.Entry<DragDirection, MathUtils.StatData> entry : statData.entrySet()) {
|
||||
final float min = (float) entry.getValue().getMean() - 2 * (float) entry.getValue().getStandardDeviation();
|
||||
final float max = (float) entry.getValue().getMean() + 2 * (float) entry.getValue().getStandardDeviation();
|
||||
editor.putFloat(preferenceType.name() + "_" + entry.getKey().name() + "_" + PREFERENCES_MIN, Math.max(0, min));
|
||||
editor.putFloat(preferenceType.name() + "_" + entry.getKey().name() + "_" + PREFERENCES_MAX, max);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Preferences getPreferences(@NotNull Context context) {
|
||||
SharedPreferences preferences = context.getSharedPreferences(PREFERENCES, MODE_PRIVATE);
|
||||
|
||||
final Preferences result = new Preferences();
|
||||
|
||||
for (PreferenceType preferenceType : PreferenceType.values()) {
|
||||
for (DragDirection dragDirection : DragDirection.values()) {
|
||||
|
||||
final float defaultMin;
|
||||
final float defaultMax;
|
||||
switch (preferenceType) {
|
||||
case angle:
|
||||
switch (dragDirection) {
|
||||
case up:
|
||||
defaultMin = 150f;
|
||||
defaultMax = 180f;
|
||||
break;
|
||||
case down:
|
||||
defaultMin = 0f;
|
||||
defaultMax = 30f;
|
||||
break;
|
||||
default:
|
||||
defaultMin = DEFAULT_VALUE;
|
||||
defaultMax = DEFAULT_VALUE;
|
||||
}
|
||||
break;
|
||||
case distance:
|
||||
defaultMin = 60f;
|
||||
defaultMax = 140f;
|
||||
break;
|
||||
case duration:
|
||||
defaultMin = 100f;
|
||||
defaultMax = 300f;
|
||||
break;
|
||||
default:
|
||||
defaultMin = DEFAULT_VALUE;
|
||||
defaultMax = DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
final float min = preferences.getFloat(preferenceType.name() + "_" + dragDirection.name() + "_" + PREFERENCES_MIN, defaultMin);
|
||||
final float max = preferences.getFloat(preferenceType.name() + "_" + dragDirection.name() + "_" + PREFERENCES_MAX, defaultMax);
|
||||
|
||||
if (min != DEFAULT_VALUE && max != DEFAULT_VALUE) {
|
||||
final DragPreference directionPreference = new DragPreference(dragDirection, new Interval(min, max));
|
||||
|
||||
Preference preference = result.getPreferencesMap().get(preferenceType);
|
||||
if (preference == null) {
|
||||
preference = new Preference(preferenceType);
|
||||
result.getPreferencesMap().put(preferenceType, preference);
|
||||
}
|
||||
|
||||
preference.getDirectionPreferences().put(dragDirection, directionPreference);
|
||||
|
||||
} else {
|
||||
Log.e(DragButtonCalibrationActivity.class.getName(), "New preference type added: default preferences should be defined!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class DragPreference {
|
||||
|
||||
@NotNull
|
||||
private DragDirection direction;
|
||||
|
||||
@NotNull
|
||||
private Interval interval;
|
||||
|
||||
|
||||
public DragPreference(@NotNull DragDirection direction, @NotNull Interval interval) {
|
||||
this.direction = direction;
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DragDirection getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setDirection(@NotNull DragDirection direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Interval getInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
public void setInterval(@NotNull Interval interval) {
|
||||
this.interval = interval;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Preference {
|
||||
|
||||
@NotNull
|
||||
private PreferenceType preferenceType;
|
||||
|
||||
@NotNull
|
||||
private Map<DragDirection, DragPreference> directionPreferences = new HashMap<DragDirection, DragPreference>();
|
||||
|
||||
|
||||
public Preference(@NotNull PreferenceType preferenceType) {
|
||||
this.preferenceType = preferenceType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PreferenceType getPreferenceType() {
|
||||
return preferenceType;
|
||||
}
|
||||
|
||||
public void setPreferenceType(@NotNull PreferenceType preferenceType) {
|
||||
this.preferenceType = preferenceType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Map<DragDirection, DragPreference> getDirectionPreferences() {
|
||||
return directionPreferences;
|
||||
}
|
||||
|
||||
public void setDirectionPreferences(@NotNull Map<DragDirection, DragPreference> directionPreferences) {
|
||||
this.directionPreferences = directionPreferences;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Preferences {
|
||||
|
||||
private final Map<PreferenceType, Preference> preferencesMap = new HashMap<PreferenceType, Preference>();
|
||||
|
||||
public Map<PreferenceType, Preference> getPreferencesMap() {
|
||||
return preferencesMap;
|
||||
}
|
||||
}
|
||||
|
||||
private void logStatData(@NotNull Map<DragDirection, MathUtils.StatData> statData) {
|
||||
for (Map.Entry<DragDirection, MathUtils.StatData> entry : statData.entrySet()) {
|
||||
Log.d(this.getClass().getName(), entry.getKey() + "-> m: " + entry.getValue().getMean() + ", d: " + entry.getValue().getStandardDeviation());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<DragDirection, MathUtils.StatData> getStatDataByDirection(@NotNull ManyValuedMap<DragDirection, Double> valuesByDirection) {
|
||||
final Map<DragDirection, MathUtils.StatData> result = new HashMap<DragDirection, MathUtils.StatData>();
|
||||
|
||||
for (Map.Entry<DragDirection, List<Double>> entry : valuesByDirection.entrySet()) {
|
||||
result.put(entry.getKey(), MathUtils.getStatData(entry.getValue()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private class DragData {
|
||||
|
||||
private float distance;
|
||||
|
||||
private double angle;
|
||||
|
||||
private double time;
|
||||
|
||||
@NotNull
|
||||
private DragDirection direction;
|
||||
|
||||
private DragData(@NotNull DragDirection direction, float distance, double angle, double time) {
|
||||
this.distance = distance;
|
||||
this.angle = angle;
|
||||
this.direction = direction;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public float getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public double getAngle() {
|
||||
return angle;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DragDirection getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public double getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
private class CalibrationArrow {
|
||||
@NotNull
|
||||
private ImageView calibrationArrow;
|
||||
|
||||
@NotNull
|
||||
private DragDirection dragDirection = DragDirection.up;
|
||||
|
||||
private CalibrationArrow(@NotNull ImageView calibrationArrow) {
|
||||
this.calibrationArrow = calibrationArrow;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class EditorHistoryState {
|
||||
|
||||
private int cursorPosition;
|
||||
|
||||
@Nullable
|
||||
private String text;
|
||||
|
||||
public EditorHistoryState() {
|
||||
}
|
||||
|
||||
public EditorHistoryState( int cursorPosition, @Nullable String text ) {
|
||||
this.cursorPosition = cursorPosition;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setCursorPosition(int cursorPosition) {
|
||||
this.cursorPosition = cursorPosition;
|
||||
}
|
||||
|
||||
public int getCursorPosition() {
|
||||
return cursorPosition;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
public enum HistoryAction {
|
||||
|
||||
redo,
|
||||
undo;
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface HistoryHelper<T> {
|
||||
|
||||
boolean isUndoAvailable();
|
||||
|
||||
@Nullable
|
||||
T undo (@Nullable T currentState);
|
||||
|
||||
boolean isRedoAvailable();
|
||||
|
||||
@Nullable
|
||||
T redo (@Nullable T currentState);
|
||||
|
||||
boolean isActionAvailable(@NotNull HistoryAction historyAction);
|
||||
|
||||
@Nullable
|
||||
T doAction(@NotNull HistoryAction historyAction, @Nullable T currentState);
|
||||
|
||||
void addState(@Nullable T currentState);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
public enum JsclOperation {
|
||||
|
||||
simplify,
|
||||
elementary,
|
||||
importCommands,
|
||||
numeric;
|
||||
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.util.math.MathEntityType;
|
||||
|
||||
public class Preprocessor {
|
||||
|
||||
@NotNull
|
||||
public static String process(@NotNull String s) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
|
||||
checkMultiplicationSignBeforeFunction(sb, s, i);
|
||||
|
||||
if (ch == '[' || ch == '{') {
|
||||
sb.append('(');
|
||||
} else if (ch == ']' || ch == '}') {
|
||||
sb.append(')');
|
||||
} else if (ch == 'π') {
|
||||
sb.append("pi");
|
||||
} else if (ch == '×' || ch == '∙') {
|
||||
sb.append("*");
|
||||
} else if (s.startsWith("ln", i)) {
|
||||
sb.append("log");
|
||||
i += 1;
|
||||
} else if (s.startsWith("tg", i)) {
|
||||
sb.append("tan");
|
||||
i += 1;
|
||||
} else if (s.startsWith("atg", i)) {
|
||||
sb.append("atan");
|
||||
i += 2;
|
||||
} else if (s.startsWith("e(", i)) {
|
||||
sb.append("exp(");
|
||||
i += 1;
|
||||
} else if (ch == 'e') {
|
||||
sb.append("exp(1)");
|
||||
} else if (ch == '√') {
|
||||
sb.append("sqrt");
|
||||
} else {
|
||||
sb.append(ch);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void checkMultiplicationSignBeforeFunction(@NotNull StringBuilder sb, @NotNull String s, int i) {
|
||||
if (i > 0) {
|
||||
// get character before function
|
||||
char chBefore = s.charAt(i - 1);
|
||||
char ch = s.charAt(i);
|
||||
|
||||
final MathEntityType mathTypeBefore = MathEntityType.getType(String.valueOf(chBefore));
|
||||
final MathEntityType mathType = MathEntityType.getType(String.valueOf(ch));
|
||||
|
||||
if (mathTypeBefore != MathEntityType.binary_operation &&
|
||||
mathTypeBefore != MathEntityType.unary_operation &&
|
||||
!MathEntityType.openGroupSymbols.contains(chBefore)) {
|
||||
|
||||
if (mathType == MathEntityType.constant) {
|
||||
sb.append("*");
|
||||
} else if (mathType == MathEntityType.digit && mathTypeBefore != MathEntityType.digit && mathTypeBefore != MathEntityType.dot) {
|
||||
sb.append("*");
|
||||
} else {
|
||||
for (String function : MathEntityType.functions) {
|
||||
if (s.startsWith(function, i)) {
|
||||
sb.append("*");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String wrap(@NotNull JsclOperation operation, @NotNull String s) {
|
||||
return operation.name() + "(\"" + s + "\");";
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SimpleHistoryHelper<T> implements HistoryHelper<T> {
|
||||
|
||||
private List<T> history = new ArrayList<T>();
|
||||
|
||||
private int currentStateIndex = -1;
|
||||
|
||||
@Override
|
||||
public T undo(@Nullable T currentState) {
|
||||
if ( !isUndoAvailable() ) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
currentStateIndex--;
|
||||
|
||||
return history.get(currentStateIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T redo(@Nullable T currentState) {
|
||||
if (!isRedoAvailable()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
currentStateIndex++;
|
||||
return history.get(currentStateIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addState(@Nullable T currentState) {
|
||||
if (currentStateIndex == history.size() - 1) {
|
||||
currentStateIndex++;
|
||||
history.add(currentState);
|
||||
} else {
|
||||
assert currentStateIndex < history.size() - 1 : "Invalid history state index!";
|
||||
currentStateIndex++;
|
||||
history.set(currentStateIndex, currentState);
|
||||
while( history.size() > currentStateIndex + 1 ) {
|
||||
history.remove(history.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUndoAvailable() {
|
||||
return currentStateIndex > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRedoAvailable() {
|
||||
return currentStateIndex < history.size() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActionAvailable(@NotNull HistoryAction historyAction) {
|
||||
boolean result = false;
|
||||
|
||||
switch (historyAction) {
|
||||
case undo:
|
||||
result = isUndoAvailable();
|
||||
break;
|
||||
case redo:
|
||||
result = isRedoAvailable();
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T doAction(@NotNull HistoryAction historyAction, @Nullable T currentState) {
|
||||
T result = null;
|
||||
|
||||
switch (historyAction) {
|
||||
case undo:
|
||||
result = undo(currentState);
|
||||
break;
|
||||
case redo:
|
||||
result = redo(currentState);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.Button;
|
||||
import android.view.MotionEvent;
|
||||
import android.content.res.Resources;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
/**
|
||||
* NOTE: copied from com.android.calculator2.ColorButton
|
||||
*/
|
||||
|
||||
/**
|
||||
* Button with click-animation effect.
|
||||
*/
|
||||
public class ColorButton extends Button {
|
||||
int CLICK_FEEDBACK_COLOR;
|
||||
static final int CLICK_FEEDBACK_INTERVAL = 10;
|
||||
static final int CLICK_FEEDBACK_DURATION = 350;
|
||||
|
||||
@NotNull
|
||||
private Point2d textPosition;
|
||||
private long mAnimStart;
|
||||
private Paint mFeedbackPaint;
|
||||
|
||||
public ColorButton(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, true);
|
||||
}
|
||||
|
||||
public ColorButton(Context context, AttributeSet attrs, boolean init) {
|
||||
super(context, attrs);
|
||||
if (init) {
|
||||
init(context);
|
||||
}
|
||||
}
|
||||
|
||||
protected void init(Context context) {
|
||||
Resources res = getResources();
|
||||
|
||||
CLICK_FEEDBACK_COLOR = res.getColor(org.solovyev.android.calculator.R.color.magic_flame);
|
||||
mFeedbackPaint = new Paint();
|
||||
mFeedbackPaint.setStyle(Style.STROKE);
|
||||
mFeedbackPaint.setStrokeWidth(2);
|
||||
getPaint().setColor(res.getColor(org.solovyev.android.calculator.R.color.button_text));
|
||||
|
||||
mAnimStart = -1;
|
||||
|
||||
if (context instanceof FontSizeAdjuster) {
|
||||
((FontSizeAdjuster) context).adjustFontSize(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSizeChanged(int w, int h, int oldW, int oldH) {
|
||||
measureText();
|
||||
}
|
||||
|
||||
protected void measureText() {
|
||||
Paint paint = getPaint();
|
||||
|
||||
if (getText() != null) {
|
||||
textPosition = getTextPosition(paint, getText());
|
||||
}
|
||||
}
|
||||
|
||||
private Point2d getTextPosition(@NotNull Paint paint, @NotNull CharSequence text) {
|
||||
final Point2d result = new Point2d();
|
||||
|
||||
result.setX((getWidth() - paint.measureText(text.toString())) / 2);
|
||||
|
||||
float height = getHeight() - paint.ascent() - paint.descent();
|
||||
|
||||
result.setY(height / 2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTextChanged(CharSequence text, int start, int before, int after) {
|
||||
measureText();
|
||||
}
|
||||
|
||||
private void drawMagicFlame(int duration, Canvas canvas) {
|
||||
int alpha = 255 - 255 * duration / CLICK_FEEDBACK_DURATION;
|
||||
int color = CLICK_FEEDBACK_COLOR | (alpha << 24);
|
||||
|
||||
mFeedbackPaint.setColor(color);
|
||||
canvas.drawRect(1, 1, getWidth() - 1, getHeight() - 1, mFeedbackPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
if (mAnimStart != -1) {
|
||||
int animDuration = (int) (System.currentTimeMillis() - mAnimStart);
|
||||
|
||||
if (animDuration >= CLICK_FEEDBACK_DURATION) {
|
||||
mAnimStart = -1;
|
||||
} else {
|
||||
drawMagicFlame(animDuration, canvas);
|
||||
postInvalidateDelayed(CLICK_FEEDBACK_INTERVAL);
|
||||
}
|
||||
} else if (isPressed()) {
|
||||
drawMagicFlame(0, canvas);
|
||||
}
|
||||
|
||||
CharSequence text = getText();
|
||||
if (text != null && textPosition != null) {
|
||||
canvas.drawText(text, 0, text.length(), textPosition.getX(), textPosition.getY(), getPaint());
|
||||
}
|
||||
}
|
||||
|
||||
public void animateClickFeedback() {
|
||||
mAnimStart = System.currentTimeMillis();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
boolean result = super.onTouchEvent(event);
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
animateClickFeedback();
|
||||
break;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.util.StringUtils;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 7/17/11
|
||||
* Time: 10:25 PM
|
||||
*/
|
||||
public class DirectionDragButton extends DragButton {
|
||||
|
||||
@Nullable
|
||||
private String textUp;
|
||||
|
||||
@Nullable
|
||||
private String textDown;
|
||||
|
||||
@Nullable
|
||||
private String textMiddle;
|
||||
|
||||
@NotNull
|
||||
private Point2d textUpPosition;
|
||||
|
||||
@NotNull
|
||||
private Point2d textDownPosition;
|
||||
|
||||
@NotNull
|
||||
private TextPaint upDownTextPaint;
|
||||
|
||||
public DirectionDragButton(Context context, @NotNull AttributeSet attrs) {
|
||||
super(context, attrs, false);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
|
||||
private void init(@NotNull Context context, @NotNull AttributeSet attrs) {
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, org.solovyev.android.calculator.R.styleable.DragButton);
|
||||
|
||||
final int N = a.getIndexCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
int attr = a.getIndex(i);
|
||||
switch (attr) {
|
||||
case org.solovyev.android.calculator.R.styleable.DragButton_textUp:
|
||||
this.textUp = a.getString(attr);
|
||||
break;
|
||||
case org.solovyev.android.calculator.R.styleable.DragButton_textDown:
|
||||
this.textDown = a.getString(attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// backup text
|
||||
this.textMiddle = String.valueOf(getText());
|
||||
|
||||
super.init(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void measureText() {
|
||||
super.measureText();
|
||||
|
||||
final Paint basePaint = getPaint();
|
||||
initUpDownTextPaint(basePaint);
|
||||
|
||||
if (textUp != null) {
|
||||
textUpPosition = getTextPosition(upDownTextPaint, basePaint, textUp, 1);
|
||||
}
|
||||
|
||||
if (textDown != null) {
|
||||
textDownPosition = getTextPosition(upDownTextPaint, basePaint, textDown, -1);
|
||||
}
|
||||
|
||||
if ( textDownPosition != null && textUpPosition != null ) {
|
||||
if ( textDownPosition.getX() > textUpPosition.getX() ) {
|
||||
textDownPosition.setX(textUpPosition.getX());
|
||||
} else {
|
||||
textUpPosition.setX(textDownPosition.getX());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Point2d getTextPosition(@NotNull Paint paint, @NotNull Paint basePaint, @NotNull CharSequence text, float direction) {
|
||||
final Point2d result = new Point2d();
|
||||
|
||||
float width = paint.measureText(text.toString() + " ");
|
||||
result.setX(getWidth() - width);
|
||||
|
||||
float selfHeight = paint.ascent() + paint.descent();
|
||||
|
||||
basePaint.measureText(StringUtils.getNotEmpty(getText(), "|"));
|
||||
|
||||
float height = getHeight() - basePaint.ascent() - basePaint.descent();
|
||||
if (direction < 0) {
|
||||
result.setY(height / 2 - direction * height / 3 + selfHeight);
|
||||
} else {
|
||||
result.setY(height / 2 - direction * height / 3);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
initUpDownTextPaint(null);
|
||||
|
||||
if (textUp != null && textUpPosition != null) {
|
||||
canvas.drawText(textUp, 0, textUp.length(), textUpPosition.getX(), textUpPosition.getY(), upDownTextPaint);
|
||||
}
|
||||
|
||||
if (textDown != null && textDownPosition != null) {
|
||||
canvas.drawText(textDown, 0, textDown.length(), textDownPosition.getX(), textDownPosition.getY(), upDownTextPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void initUpDownTextPaint(@Nullable Paint paint) {
|
||||
if (paint == null) {
|
||||
paint = getPaint();
|
||||
}
|
||||
|
||||
upDownTextPaint = new TextPaint(paint);
|
||||
upDownTextPaint.setAlpha(150);
|
||||
upDownTextPaint.setTextSize(paint.getTextSize() / 2);
|
||||
}
|
||||
|
||||
private String getStyledUpDownText(@Nullable String text) {
|
||||
return StringUtils.getNotEmpty(text, " ");
|
||||
}
|
||||
|
||||
public void setTextUp(@Nullable String textUp) {
|
||||
this.textUp = textUp;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTextUp() {
|
||||
return textUp;
|
||||
}
|
||||
|
||||
public void setTextDown(@Nullable String textDown) {
|
||||
this.textDown = textDown;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTextDown() {
|
||||
return textDown;
|
||||
}
|
||||
|
||||
public void setTextMiddle(@Nullable String textMiddle) {
|
||||
this.textMiddle = textMiddle;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTextMiddle() {
|
||||
return textMiddle;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText(@NotNull DragDirection direction) {
|
||||
final String result;
|
||||
|
||||
if (direction == DragDirection.up) {
|
||||
result = getTextUp();
|
||||
} else if ( direction == DragDirection.down ) {
|
||||
result = getTextDown();
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
public class DragButton extends ColorButton {
|
||||
|
||||
@Nullable
|
||||
private Point2d startPoint = null;
|
||||
|
||||
@Nullable
|
||||
private OnDragListener onDragListener;
|
||||
|
||||
private final OnTouchListener onTouchListener = new OnTouchListenerImpl();
|
||||
|
||||
public DragButton(Context context, @NotNull AttributeSet attrs) {
|
||||
this(context, attrs, true);
|
||||
}
|
||||
|
||||
public DragButton(Context context, @NotNull AttributeSet attrs, boolean init) {
|
||||
super(context, attrs, false);
|
||||
setOnTouchListener(this.onTouchListener);
|
||||
if ( init ) {
|
||||
super.init(context);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnDragListener(@Nullable OnDragListener onDragListener) {
|
||||
this.onDragListener = onDragListener;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OnDragListener getOnDragListener() {
|
||||
return onDragListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* OnTouchListener implementation that fires onDrag()
|
||||
*
|
||||
* @author serso
|
||||
*
|
||||
*/
|
||||
private final class OnTouchListenerImpl implements OnTouchListener {
|
||||
|
||||
@Override
|
||||
public boolean onTouch(@NotNull View v, @NotNull MotionEvent event) {
|
||||
// processing on touch event
|
||||
|
||||
// in order to avoid possible NPEs
|
||||
final Point2d localStartPoint = startPoint;
|
||||
final OnDragListener localOnDragListener = onDragListener;
|
||||
|
||||
if (localOnDragListener != null) {
|
||||
// only if onDrag() listener specified
|
||||
|
||||
Log.d(String.valueOf(getId()), "onTouch() for: " + getId() + " . Motion event: " + event);
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
// start tracking: set start point
|
||||
startPoint = new Point2d(event.getX(), event.getY());
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
// stop tracking
|
||||
|
||||
if (localStartPoint != null && localOnDragListener.onDrag(DragButton.this, new DragEvent(localStartPoint, event))) {
|
||||
if (localOnDragListener.isSuppressOnClickEvent()) {
|
||||
// prevent on click action
|
||||
setPressed(false);
|
||||
}
|
||||
}
|
||||
|
||||
startPoint = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
public enum DragDirection {
|
||||
|
||||
up,
|
||||
down,
|
||||
left,
|
||||
right;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class DragEvent {
|
||||
|
||||
@NotNull
|
||||
private final Point2d startPoint;
|
||||
|
||||
@NotNull
|
||||
private final MotionEvent motionEvent;
|
||||
|
||||
public DragEvent(@NotNull Point2d startPoint, @NotNull MotionEvent motionEvent) {
|
||||
this.startPoint = startPoint;
|
||||
this.motionEvent = motionEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return motion event started at start point
|
||||
*/
|
||||
@NotNull
|
||||
public MotionEvent getMotionEvent() {
|
||||
return motionEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return start point of dragging
|
||||
*/
|
||||
@NotNull
|
||||
public Point2d getStartPoint() {
|
||||
return startPoint;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import android.widget.TextView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/10/11
|
||||
* Time: 7:21 PM
|
||||
*/
|
||||
public interface FontSizeAdjuster {
|
||||
|
||||
void adjustFontSize(@NotNull TextView textView);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public interface OnDragListener {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return 'true': if drag event has taken place (i.e. onDrag() method returned true) then click action will be suppresed
|
||||
*/
|
||||
boolean isSuppressOnClickEvent();
|
||||
|
||||
/**
|
||||
* @param dragButton drag button object for which onDrag listener was set
|
||||
* @param event drag event
|
||||
*
|
||||
* @return 'true' if drag event occurred, 'false' otherwise
|
||||
*/
|
||||
boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event);
|
||||
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.DragButtonCalibrationActivity;
|
||||
import org.solovyev.common.utils.Interval;
|
||||
import org.solovyev.util.math.MathUtils;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SimpleOnDragListener implements OnDragListener {
|
||||
|
||||
@NotNull
|
||||
public static final Point2d axis = new Point2d(0, 1);
|
||||
|
||||
@NotNull
|
||||
private DragProcessor dragProcessor;
|
||||
|
||||
@NotNull
|
||||
private DragButtonCalibrationActivity.Preferences preferences;
|
||||
|
||||
public SimpleOnDragListener(@NotNull DragButtonCalibrationActivity.Preferences preferences) {
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
public SimpleOnDragListener(@NotNull DragProcessor dragProcessor, @NotNull DragButtonCalibrationActivity.Preferences preferences) {
|
||||
this.dragProcessor = dragProcessor;
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
public void setPreferences(@NotNull DragButtonCalibrationActivity.Preferences preferences) {
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||
boolean result = false;
|
||||
|
||||
logDragEvent(dragButton, event);
|
||||
|
||||
final Point2d startPoint = event.getStartPoint();
|
||||
final MotionEvent motionEvent = event.getMotionEvent();
|
||||
|
||||
// init end point
|
||||
final Point2d endPoint = new Point2d(motionEvent.getX(), motionEvent.getY());
|
||||
|
||||
final float distance = MathUtils.getDistance(startPoint, endPoint);
|
||||
final double angle = Math.toDegrees(MathUtils.getAngle(startPoint, MathUtils.sum(startPoint, axis), endPoint));
|
||||
final double duration = motionEvent.getEventTime() - motionEvent.getDownTime();
|
||||
|
||||
final DragButtonCalibrationActivity.Preference distancePreferences = preferences.getPreferencesMap().get(DragButtonCalibrationActivity.PreferenceType.distance);
|
||||
final DragButtonCalibrationActivity.Preference anglePreferences = preferences.getPreferencesMap().get(DragButtonCalibrationActivity.PreferenceType.angle);
|
||||
|
||||
DragDirection direction = null;
|
||||
for (Map.Entry<DragDirection, DragButtonCalibrationActivity.DragPreference> directionEntry : distancePreferences.getDirectionPreferences().entrySet()) {
|
||||
|
||||
if (isInInterval(directionEntry.getValue().getInterval(), distance)) {
|
||||
for (Map.Entry<DragDirection, DragButtonCalibrationActivity.DragPreference> angleEntry : anglePreferences.getDirectionPreferences().entrySet()) {
|
||||
if (isInInterval(angleEntry.getValue().getInterval(), (float)angle)) {
|
||||
direction = angleEntry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (direction != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (direction != null) {
|
||||
final DragButtonCalibrationActivity.Preference durationPreferences = preferences.getPreferencesMap().get(DragButtonCalibrationActivity.PreferenceType.duration);
|
||||
|
||||
final DragButtonCalibrationActivity.DragPreference durationDragPreferences = durationPreferences.getDirectionPreferences().get(direction);
|
||||
|
||||
if (isInInterval(durationDragPreferences.getInterval(), (float)duration)) {
|
||||
result = dragProcessor.processDragEvent(direction, dragButton, startPoint, motionEvent);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isInInterval(@NotNull Interval interval, float value) {
|
||||
return interval.getStart() - MathUtils.MIN_AMOUNT <= value && value <= interval.getEnd() + MathUtils.MIN_AMOUNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppressOnClickEvent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void logDragEvent(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||
final Point2d startPoint = event.getStartPoint();
|
||||
final MotionEvent motionEvent = event.getMotionEvent();
|
||||
final Point2d endPoint = new Point2d(motionEvent.getX(), motionEvent.getY());
|
||||
|
||||
Log.d(String.valueOf(dragButton.getId()), "Start point: " + startPoint + ", End point: " + endPoint);
|
||||
Log.d(String.valueOf(dragButton.getId()), "Distance: " + MathUtils.getDistance(startPoint, endPoint));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Angle: " + Math.toDegrees(MathUtils.getAngle(startPoint, MathUtils.sum(startPoint, axis), endPoint)));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Axis: " + axis + " Vector: " + MathUtils.subtract(endPoint, startPoint));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Total time: " + (motionEvent.getEventTime() - motionEvent.getDownTime()) + " ms");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DragProcessor getDragProcessor() {
|
||||
return dragProcessor;
|
||||
}
|
||||
|
||||
public void setDragProcessor(@NotNull DragProcessor dragProcessor) {
|
||||
this.dragProcessor = dragProcessor;
|
||||
}
|
||||
|
||||
public interface DragProcessor {
|
||||
|
||||
boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package org.solovyev.util;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class StringUtils {
|
||||
|
||||
public static boolean isEmpty ( @Nullable CharSequence s ){
|
||||
return s == null || s.length() == 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getNotEmpty ( @Nullable CharSequence s, @NotNull String defaultValue ){
|
||||
return isEmpty(s) ? defaultValue : s.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
package org.solovyev.util.date;
|
||||
|
||||
public class DateUtils {
|
||||
|
||||
public static long MS_IN_SECONDS = 1000l;
|
||||
|
||||
public static long msToSeconds (long ms) {
|
||||
return ms / 1000l;
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package org.solovyev.util.math;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum MathEntity {
|
||||
|
||||
minus("-"),
|
||||
equals("="),
|
||||
factorial("!"),
|
||||
plus("+"),
|
||||
multiply("*"),
|
||||
divide("/"),
|
||||
power("^"),
|
||||
sin("sin"),
|
||||
asin("asin"),
|
||||
cos("cos"),
|
||||
acos("acos"),
|
||||
tg("tg"),
|
||||
atg("atg"),
|
||||
exp("exp"),
|
||||
log("log"),
|
||||
ln("ln"),
|
||||
mod("mod"),
|
||||
sqrt("sqrt");
|
||||
|
||||
@NotNull
|
||||
private final String text;
|
||||
|
||||
private MathEntity (@NotNull String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
package org.solovyev.util.math;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public enum MathEntityType {
|
||||
|
||||
digit,
|
||||
constant,
|
||||
dot,
|
||||
function,
|
||||
unary_operation,
|
||||
binary_operation,
|
||||
group_symbols,
|
||||
group_symbol;
|
||||
|
||||
public static final List<Character> constants = Arrays.asList('e', 'π');
|
||||
|
||||
public static final List<Character> dots = Arrays.asList('.', ',');
|
||||
|
||||
public static final List<Character> unaryOperations = Arrays.asList('-', '=', '!');
|
||||
|
||||
public static final List<Character> binaryOperations = Arrays.asList('-', '+', '*', '×', '∙', '/', '^' );
|
||||
|
||||
public static final List<String> functions = Arrays.asList("sin", "asin", "cos", "acos", "tg", "atg", "log", "ln", "mod", "√");
|
||||
|
||||
public static final List<String> groupSymbols = Arrays.asList("[]", "()", "{}");
|
||||
|
||||
public static final List<Character> openGroupSymbols = Arrays.asList('[', '(', '{');
|
||||
|
||||
public static final List<Character> closeGroupSymbols = Arrays.asList(']', ')', '}');
|
||||
|
||||
public static final List<Character> singleGroupSymbols;
|
||||
static {
|
||||
final List<Character> list = new ArrayList<Character>();
|
||||
list.addAll(openGroupSymbols);
|
||||
list.addAll(closeGroupSymbols);
|
||||
singleGroupSymbols = Collections.unmodifiableList(list);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static MathEntityType getType( @NotNull String s ) {
|
||||
MathEntityType result = null;
|
||||
|
||||
if ( s.length() == 1 ) {
|
||||
char ch = 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 ( functions.contains(s) ) {
|
||||
result = MathEntityType.function;
|
||||
} else if ( groupSymbols.contains(s) ) {
|
||||
result = MathEntityType.group_symbols;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
package org.solovyev.util.math;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MathUtils {
|
||||
|
||||
public static final float MIN_AMOUNT = 0.05f;
|
||||
|
||||
public static double round(@NotNull Double value, int numberOfFractionDigits) {
|
||||
double roundFactor = Math.pow(10, numberOfFractionDigits);
|
||||
|
||||
if (value < Double.MAX_VALUE / roundFactor) {
|
||||
return ((double)Math.round(value * roundFactor)) / roundFactor;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public static float getDistance(@NotNull Point2d startPoint,
|
||||
@NotNull Point2d endPoint) {
|
||||
return getNorm(subtract(endPoint, startPoint));
|
||||
}
|
||||
|
||||
public static Point2d subtract(@NotNull Point2d p1, @NotNull Point2d p2) {
|
||||
return new Point2d(p1.getX() - p2.getX(), p1.getY() - p2.getY());
|
||||
}
|
||||
|
||||
public static Point2d sum(@NotNull Point2d p1, @NotNull Point2d p2) {
|
||||
return new Point2d(p1.getX() + p2.getX(), p1.getY() + p2.getY());
|
||||
}
|
||||
|
||||
public static float getNorm(@NotNull Point2d point) {
|
||||
return (float) Math.pow(
|
||||
Math.pow(point.getX(), 2) + Math.pow(point.getY(), 2), 0.5);
|
||||
}
|
||||
|
||||
public static float getAngle(@NotNull Point2d startPoint,
|
||||
@NotNull Point2d axisEndPoint, @NotNull Point2d endPoint) {
|
||||
final Point2d axisVector = subtract(axisEndPoint, startPoint);
|
||||
final Point2d vector = subtract(endPoint, startPoint);
|
||||
|
||||
double a_2 = Math.pow(getDistance(vector, axisVector), 2);
|
||||
double b = getNorm(vector);
|
||||
double b_2 = Math.pow(b, 2);
|
||||
double c = getNorm(axisVector);
|
||||
double c_2 = Math.pow(c, 2);
|
||||
|
||||
return (float) Math.acos((-a_2 + b_2 + c_2) / (2 * b * c));
|
||||
}
|
||||
|
||||
public static double countMean(@NotNull List<Double> objects) {
|
||||
|
||||
double sum = 0d;
|
||||
for (Double object : objects) {
|
||||
sum += object;
|
||||
}
|
||||
|
||||
return objects.size() == 0 ? 0d : (sum / objects.size());
|
||||
}
|
||||
|
||||
public static double countStandardDeviation(@NotNull Double mean, @NotNull List<Double> objects) {
|
||||
double sum = 0d;
|
||||
|
||||
for (Double object : objects) {
|
||||
sum += Math.pow(object - mean, 2);
|
||||
}
|
||||
|
||||
return objects.size() == 0 ? 0d : Math.sqrt(sum / objects.size());
|
||||
}
|
||||
|
||||
public static StatData getStatData(@NotNull List<Double> objects) {
|
||||
|
||||
final double mean = countMean(objects);
|
||||
final double standardDeviation = countStandardDeviation(mean, objects);
|
||||
|
||||
return new StatData(mean, standardDeviation);
|
||||
}
|
||||
|
||||
public static class StatData {
|
||||
|
||||
private final double mean;
|
||||
|
||||
private final double standardDeviation;
|
||||
|
||||
public StatData(double mean, double standardDeviation) {
|
||||
this.mean = mean;
|
||||
this.standardDeviation = standardDeviation;
|
||||
}
|
||||
|
||||
public double getMean() {
|
||||
return mean;
|
||||
}
|
||||
|
||||
public double getStandardDeviation() {
|
||||
return standardDeviation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package org.solovyev.util.math;
|
||||
|
||||
public class Point2d {
|
||||
|
||||
private float x = 0;
|
||||
|
||||
private float y = 0;
|
||||
|
||||
public Point2d() {
|
||||
}
|
||||
|
||||
public Point2d( float x, float y ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(float x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(float y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Point2d [x=" + x + ", y=" + y + "]";
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user