Android project initiated
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<manifest xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.solovyev.android.calculator"
|
||||||
|
versionCode="1"
|
||||||
|
versionName="1.0">
|
||||||
|
<a:uses-sdk a:minSdkVersion="8"/>
|
||||||
|
|
||||||
|
<a:application a:icon="@drawable/icon" a:label="@string/app_name_caption">
|
||||||
|
<a:activity a:name=".Calculator" a:label="@string/app_name_caption">
|
||||||
|
<a:intent-filter>
|
||||||
|
<a:action a:name="android.intent.action.MAIN" />
|
||||||
|
<a:category a:name="android.intent.category.LAUNCHER" />
|
||||||
|
</a:intent-filter>
|
||||||
|
</a:activity>
|
||||||
|
|
||||||
|
</a:application>
|
||||||
|
</manifest>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,11 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system use,
|
||||||
|
# "build.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-8
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<FindBugsFilter>
|
||||||
|
<Match>
|
||||||
|
<Class name="org.solovyev.android.calculator.R" />
|
||||||
|
</Match>
|
||||||
|
</FindBugsFilter>
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/* 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 drawable {
|
||||||
|
public static final int icon=0x7f020000;
|
||||||
|
}
|
||||||
|
public static final class id {
|
||||||
|
public static final int curlyBracketsButton=0x7f060013;
|
||||||
|
public static final int editText=0x7f060000;
|
||||||
|
public static final int eigthDigitButton=0x7f06000f;
|
||||||
|
public static final int equalsButton=0x7f060011;
|
||||||
|
public static final int fiveDigitButton=0x7f060009;
|
||||||
|
public static final int fourDigitButton=0x7f060008;
|
||||||
|
public static final int historyButton=0x7f060018;
|
||||||
|
public static final int minusButton=0x7f06000c;
|
||||||
|
public static final int muliplicationButton=0x7f060005;
|
||||||
|
public static final int nineDigitButton=0x7f060010;
|
||||||
|
public static final int numericButton=0x7f060016;
|
||||||
|
public static final int oneDigitButton=0x7f060002;
|
||||||
|
public static final int piButton=0x7f060019;
|
||||||
|
public static final int plusButton=0x7f060006;
|
||||||
|
public static final int pointDigitButton=0x7f060015;
|
||||||
|
public static final int resultEditText=0x7f060001;
|
||||||
|
public static final int roundBracketsButton=0x7f060007;
|
||||||
|
public static final int sevenDigitButton=0x7f06000e;
|
||||||
|
public static final int simplifyButton=0x7f060017;
|
||||||
|
public static final int sixDigitButton=0x7f06000a;
|
||||||
|
public static final int sqrtButton=0x7f060012;
|
||||||
|
public static final int squareBracketsButton=0x7f06000d;
|
||||||
|
public static final int subtractionButton=0x7f06000b;
|
||||||
|
public static final int threeDigitButton=0x7f060004;
|
||||||
|
public static final int twoDigitButton=0x7f060003;
|
||||||
|
public static final int zeroDigitButton=0x7f060014;
|
||||||
|
}
|
||||||
|
public static final class layout {
|
||||||
|
public static final int main=0x7f030000;
|
||||||
|
}
|
||||||
|
public static final class string {
|
||||||
|
public static final int app_name_caption=0x7f040000;
|
||||||
|
public static final int syntax_error=0x7f040001;
|
||||||
|
}
|
||||||
|
public static final class style {
|
||||||
|
public static final int digitButtonStyle=0x7f050001;
|
||||||
|
public static final int editTextInputStyle=0x7f050000;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:calc="http://schemas.android.com/apk/res/org.solovyev.android.calculator"
|
||||||
|
|
||||||
|
a:orientation="vertical"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:layout_height="fill_parent">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
a:id="@+id/editText"
|
||||||
|
style="@style/editTextInputStyle"
|
||||||
|
a:maxLines="5"
|
||||||
|
a:minLines="5"
|
||||||
|
a:gravity="top|left"
|
||||||
|
a:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
a:typeface="monospace"
|
||||||
|
a:singleLine="false" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
a:id="@+id/resultEditText"
|
||||||
|
style="@style/editTextInputStyle"
|
||||||
|
a:gravity="top|left"
|
||||||
|
a:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
a:typeface="monospace"
|
||||||
|
a:editable="false"
|
||||||
|
a:focusable="false"/>
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:layout_height="fill_parent">
|
||||||
|
<TableRow>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/oneDigitButton" a:text="1" calc:textUp="sin" calc:textDown="asin" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/twoDigitButton" a:text="2" calc:textUp="cos" calc:textDown="acos" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/threeDigitButton" a:text="3" calc:textUp="tg" calc:textDown="atg" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/muliplicationButton" a:text="*" calc:textUp="^" calc:textDown="^2" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/plusButton" a:text="+" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/roundBracketsButton" a:text="()" calc:textUp="(" calc:textDown=")" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/fourDigitButton" a:text="4" calc:textUp="exp" calc:textDown="mod" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/fiveDigitButton" a:text="5" calc:textUp="log" calc:textDown="ln" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/sixDigitButton" a:text="6" calc:textUp="!" calc:textDown="" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/subtractionButton" a:text="/" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/minusButton" a:text="-" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/squareBracketsButton" a:text="[]" calc:textUp="[" calc:textDown="]" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/sevenDigitButton" a:text="7" calc:textUp="" calc:textDown="" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/eigthDigitButton" a:text="8" calc:textUp="" calc:textDown="" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/nineDigitButton" a:text="9" calc:textUp="" calc:textDown="" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/equalsButton" a:text="=" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/sqrtButton" a:text="sqrt" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/curlyBracketsButton" a:text="{}" calc:textUp="{" calc:textDown="}" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/zeroDigitButton" a:text="0" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/pointDigitButton" a:text="." calc:textDown="," style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/numericButton" a:text="numeric" style="@style/digitButtonStyle" a:onClick="numericButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/simplifyButton" a:text="simplify" style="@style/digitButtonStyle" a:onClick="simplifyButtonClickHandler"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/historyButton" calc:textUp="undo" calc:textDown="redo" style="@style/digitButtonStyle"/>
|
||||||
|
<org.solovyev.android.view.DragButton a:id="@+id/piButton" a:text="pi" calc:textUp="e" style="@style/digitButtonStyle" a:onClick="digitButtonClickHandler"/>
|
||||||
|
</TableRow>
|
||||||
|
</TableLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name_caption">Калькулятор</string>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="DragButton">
|
||||||
|
<attr name="textUp" format="string" />
|
||||||
|
<attr name="textDown" format="string" />
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name_caption">Calculator</string>
|
||||||
|
<string name="syntax_error">Syntax error</string>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="editTextInputStyle">
|
||||||
|
<item name="android:layout_width">fill_parent</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:typeface">monospace</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="digitButtonStyle">
|
||||||
|
<item name="android:width">50dp</item>
|
||||||
|
<item name="android:height">50dp</item>
|
||||||
|
<item name="android:typeface">monospace</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.R;
|
||||||
|
import org.solovyev.android.view.DragButton;
|
||||||
|
import org.solovyev.android.view.DragEvent;
|
||||||
|
import org.solovyev.android.view.OnDragListener;
|
||||||
|
import org.solovyev.android.view.SimpleOnDragListener;
|
||||||
|
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.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
public class Calculator extends Activity {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private EditText editText;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private EditText resultEditText;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Interpreter interpreter;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private HistoryHelper<EditorHistoryState> historyHelper;
|
||||||
|
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.main);
|
||||||
|
|
||||||
|
this.editText = (EditText) findViewById(R.id.editText);
|
||||||
|
|
||||||
|
this.resultEditText = (EditText) findViewById(R.id.resultEditText);
|
||||||
|
|
||||||
|
final SimpleOnDragListener onDragListener = new SimpleOnDragListener();
|
||||||
|
|
||||||
|
// 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(Calculator.class.getName(), e.getMessage());
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
Log.e(Calculator.class.getName(), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
((DragButton) findViewById(R.id.historyButton)).setOnDragListener(new HistoryOnDragListener());
|
||||||
|
|
||||||
|
this.interpreter = new Interpreter();
|
||||||
|
|
||||||
|
try {
|
||||||
|
interpreter.eval(Preprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands"));
|
||||||
|
} catch (EvalError e) {
|
||||||
|
Log.e(Calculator.class.getName(), e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.historyHelper = new SimpleHistoryHelper<EditorHistoryState>();
|
||||||
|
this.historyHelper.addState(getCurrentHistoryState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void elementaryButtonClickHandler(@NotNull View v) {
|
||||||
|
eval(JsclOperation.elementary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void numericButtonClickHandler(@NotNull View v) {
|
||||||
|
eval(JsclOperation.numeric);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void simplifyButtonClickHandler(@NotNull View v) {
|
||||||
|
eval(JsclOperation.simplify);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void eval(@NotNull JsclOperation operation) {
|
||||||
|
try {
|
||||||
|
final String preprocessedString = Preprocessor.process(String.valueOf(editText.getText()));
|
||||||
|
resultEditText.setText(String.valueOf(interpreter.eval(Preprocessor.wrap(operation, preprocessedString))));
|
||||||
|
} catch (EvalError e) {
|
||||||
|
Log.e(Calculator.class.getName(), e.getMessage());
|
||||||
|
resultEditText.setText(R.string.syntax_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void digitButtonClickHandler(@NotNull View v) {
|
||||||
|
processButtonAction(v, ((DragButton) v).getTextMiddle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class HistoryOnDragListener implements OnDragListener {
|
||||||
|
@Override
|
||||||
|
public void onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||||
|
Log.d(String.valueOf(dragButton.getId()), "History on drag event start: " + event.getDirection());
|
||||||
|
|
||||||
|
String actionText = getActionText(dragButton, event);
|
||||||
|
if (!StringUtils.isEmpty(actionText)) {
|
||||||
|
try {
|
||||||
|
final HistoryAction historyAction = HistoryAction.valueOf(actionText);
|
||||||
|
if ( historyHelper.isActionAvailable(historyAction) ){
|
||||||
|
final EditorHistoryState newState = historyHelper.doAction(historyAction, getCurrentHistoryState());
|
||||||
|
if (newState != null) {
|
||||||
|
setCurrentHistoryState(newState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log.e(String.valueOf(dragButton.getId()), "Unsupported history action: " + actionText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static String getActionText(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||||
|
final String result;
|
||||||
|
|
||||||
|
switch(event.getDirection()) {
|
||||||
|
case up:
|
||||||
|
result = dragButton.getTextUp();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case down:
|
||||||
|
result = dragButton.getTextDown();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
result = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentHistoryState(@Nullable EditorHistoryState editorHistoryState) {
|
||||||
|
this.editText.setText(editorHistoryState.getText());
|
||||||
|
this.editText.setSelection(editorHistoryState.getCursorPosition(), editorHistoryState.getCursorPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public EditorHistoryState getCurrentHistoryState() {
|
||||||
|
final EditorHistoryState result = new EditorHistoryState();
|
||||||
|
|
||||||
|
result.setText(String.valueOf(this.editText.getText()));
|
||||||
|
result.setCursorPosition(this.editText.getSelectionStart());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processButtonAction(@NotNull View v, @Nullable String text) {
|
||||||
|
//Toast.makeText(Calculator.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);
|
||||||
|
this.historyHelper.addState(getCurrentHistoryState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
public enum HistoryAction {
|
||||||
|
|
||||||
|
redo,
|
||||||
|
undo;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
public enum JsclOperation {
|
||||||
|
|
||||||
|
simplify,
|
||||||
|
elementary,
|
||||||
|
importCommands,
|
||||||
|
numeric;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (ch == '[' || ch == '{') {
|
||||||
|
sb.append('(');
|
||||||
|
} else if (ch == ']' || ch == '}') {
|
||||||
|
sb.append(')');
|
||||||
|
} else if ( ch == ',' ) {
|
||||||
|
sb.append('.');
|
||||||
|
} else {
|
||||||
|
sb.append(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String wrap (@NotNull JsclOperation operation, @NotNull String s) {
|
||||||
|
return operation.name() + "(\"" + s + "\");";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package org.solovyev.android.view;
|
||||||
|
|
||||||
|
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.MathUtils;
|
||||||
|
import org.solovyev.util.math.Point2d;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
public class DragButton extends Button {
|
||||||
|
|
||||||
|
// max time in ms to register drag event
|
||||||
|
private long maxTime = 700;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Point2d startPoint = null;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private OnDragListener onDragListener;
|
||||||
|
|
||||||
|
private final OnTouchListener onTouchListener = new OnTouchListenerImpl();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String textUp;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String textDown;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String textMiddle;
|
||||||
|
|
||||||
|
public DragButton(Context context, @NotNull AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DragButton(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
init(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(@NotNull Context context, @NotNull AttributeSet attrs) {
|
||||||
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DragButton);
|
||||||
|
|
||||||
|
final int N = a.getIndexCount();
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
int attr = a.getIndex(i);
|
||||||
|
switch (attr) {
|
||||||
|
case R.styleable.DragButton_textUp:
|
||||||
|
this.textUp = a.getString(attr);
|
||||||
|
break;
|
||||||
|
case R.styleable.DragButton_textDown:
|
||||||
|
this.textDown = a.getString(attr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// backup text
|
||||||
|
this.textMiddle = String.valueOf(getText());
|
||||||
|
|
||||||
|
setText(Html.fromHtml(getStyledUpDownText(this.textUp) + "<br><b>" + StringUtils.getNotEmpty(this.textMiddle, " ") + "</b><br>" + getStyledUpDownText(this.textDown)));
|
||||||
|
|
||||||
|
// change top padding in order to show all text
|
||||||
|
setPadding(getPaddingLeft(), -7, getPaddingRight(), getPaddingBottom());
|
||||||
|
|
||||||
|
setOnTouchListener(this.onTouchListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStyledUpDownText(@Nullable String text) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.append("<font color='#585858'><small><small>");
|
||||||
|
sb.append(StringUtils.getNotEmpty(text, " "));
|
||||||
|
sb.append("</small></small></font>");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnDragListener(@Nullable OnDragListener onDragListener) {
|
||||||
|
this.onDragListener = onDragListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public OnDragListener getOnDragListener() {
|
||||||
|
return onDragListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextUp(String textUp) {
|
||||||
|
this.textUp = textUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTextUp() {
|
||||||
|
return textUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextDown(String textDown) {
|
||||||
|
this.textDown = textDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTextDown() {
|
||||||
|
return textDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextMiddle(String textMiddle) {
|
||||||
|
this.textMiddle = textMiddle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTextMiddle() {
|
||||||
|
return textMiddle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
|
||||||
|
if (onDragListener != 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_MOVE:
|
||||||
|
if (event.getEventTime() - event.getDownTime() > maxTime) {
|
||||||
|
// do not allow very long touch movements
|
||||||
|
startPoint = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
// stop tracking
|
||||||
|
|
||||||
|
if (onDragListener.onDrag(DragButton.this, new DragEvent(startPoint, event))) {
|
||||||
|
if (onDragListener.isSuppressOnClickEvent()) {
|
||||||
|
// prevent on click action
|
||||||
|
setPressed(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startPoint = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.solovyev.android.view;
|
||||||
|
|
||||||
|
public enum DragDirection {
|
||||||
|
|
||||||
|
up,
|
||||||
|
down;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public MotionEvent getMotionEvent() {
|
||||||
|
return motionEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Point2d getStartPoint() {
|
||||||
|
return startPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package org.solovyev.android.view;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.util.StringUtils;
|
||||||
|
import org.solovyev.util.math.MathUtils;
|
||||||
|
import org.solovyev.util.math.Point2d;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
public class SimpleOnDragListener implements OnDragListener {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Point2d axis = new Point2d(0, 1);
|
||||||
|
|
||||||
|
private float minDragDist = 20f;
|
||||||
|
|
||||||
|
private float maxDragDist = 80f;
|
||||||
|
|
||||||
|
// max angle (in degrees!) between start and end point vector and axis
|
||||||
|
// vector to register drag event
|
||||||
|
private double maxAngle = 30;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||||
|
logDragEvent(dragButton, event);
|
||||||
|
|
||||||
|
processButtonAction(dragButton, getActionText(dragButton, event));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSuppressOnClickEvent() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method creates drag event in case if all conditions are satisfied
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* motion event
|
||||||
|
*
|
||||||
|
* @return filled drag event object only if drag event is possible, null
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
protected DragEvent getDragEvent(@NotNull MotionEvent event) {
|
||||||
|
DragEvent result = null;
|
||||||
|
|
||||||
|
if (startPoint != null) {
|
||||||
|
final Point2d endPoint = new Point2d(event.getX(), event.getY());
|
||||||
|
float distance = MathUtils.getDistance(startPoint, endPoint);
|
||||||
|
|
||||||
|
if (minDragDist < distance && distance < maxDragDist) {
|
||||||
|
double angle = Math.toDegrees(MathUtils.getAngle(startPoint, MathUtils.sum(startPoint, axis), endPoint));
|
||||||
|
|
||||||
|
final DragDirection direction;
|
||||||
|
if (angle < maxAngle) {
|
||||||
|
direction = DragDirection.down;
|
||||||
|
} else if (180 - angle < maxAngle) {
|
||||||
|
direction = DragDirection.up;
|
||||||
|
} else {
|
||||||
|
direction = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction != null) {
|
||||||
|
if ( direction == DragDirection.up && StringUtils.isEmpty(textUp) ) {
|
||||||
|
// no action if text is empty
|
||||||
|
} else if (direction == DragDirection.down && StringUtils.isEmpty(textDown)) {
|
||||||
|
// no action if text is empty
|
||||||
|
} else {
|
||||||
|
result = new DragEvent(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.solovyev.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class StringUtils {
|
||||||
|
|
||||||
|
public static boolean isEmpty ( @Nullable String s ){
|
||||||
|
return s == null || s.length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static String getNotEmpty ( @Nullable String s, @NotNull String defaultValue ){
|
||||||
|
return isEmpty(s) ? defaultValue : s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.solovyev.util.date;
|
||||||
|
|
||||||
|
public class DateUtils {
|
||||||
|
|
||||||
|
public static long MS_IN_SECONDS = 1000l;
|
||||||
|
|
||||||
|
public static long msToSeconds (long ms) {
|
||||||
|
return ms / 1000l;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package org.solovyev.util.math;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public enum MathEntityType {
|
||||||
|
|
||||||
|
digit,
|
||||||
|
function,
|
||||||
|
unary_operation,
|
||||||
|
binary_operation,
|
||||||
|
group_symbols,
|
||||||
|
group_symbol;
|
||||||
|
|
||||||
|
private static final List<Character> unaryOperations = Arrays.asList('-', '=', '!');
|
||||||
|
|
||||||
|
private static final List<Character> binaryOperations = Arrays.asList('-', '+', '*', '/', '^' );
|
||||||
|
|
||||||
|
private static final List<String> functions = Arrays.asList("sin", "asin", "cos", "acos", "tg", "atg", "exp", "log", "ln", "mod", "sqrt");
|
||||||
|
|
||||||
|
private static final List<String> groupSymbols = Arrays.asList("[]", "()", "{}");
|
||||||
|
|
||||||
|
private static final List<Character> singleGroupSymbols = Arrays.asList('[', ']', '(', ')', '{', '}');
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( result == null ) {
|
||||||
|
if ( functions.contains(s) ) {
|
||||||
|
result = MathEntityType.function;
|
||||||
|
} else if ( groupSymbols.contains(s) ) {
|
||||||
|
result = MathEntityType.group_symbols;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package org.solovyev.util.math;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class MathUtils {
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
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 + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user