Android project initiated
This commit is contained in:
commit
7d66404d00
18
AndroidManifest.xml
Normal file
18
AndroidManifest.xml
Normal file
@ -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>
|
BIN
bin/android_calculator.apk
Normal file
BIN
bin/android_calculator.apk
Normal file
Binary file not shown.
BIN
bin/classes.dex
Normal file
BIN
bin/classes.dex
Normal file
Binary file not shown.
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/Calculator.class
Normal file
BIN
bin/org/solovyev/android/calculator/Calculator.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/EditorHistoryState.class
Normal file
BIN
bin/org/solovyev/android/calculator/EditorHistoryState.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/HistoryAction.class
Normal file
BIN
bin/org/solovyev/android/calculator/HistoryAction.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/HistoryHelper.class
Normal file
BIN
bin/org/solovyev/android/calculator/HistoryHelper.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/JsclOperation.class
Normal file
BIN
bin/org/solovyev/android/calculator/JsclOperation.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/Preprocessor.class
Normal file
BIN
bin/org/solovyev/android/calculator/Preprocessor.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/R$attr.class
Normal file
BIN
bin/org/solovyev/android/calculator/R$attr.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/R$drawable.class
Normal file
BIN
bin/org/solovyev/android/calculator/R$drawable.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/R$id.class
Normal file
BIN
bin/org/solovyev/android/calculator/R$id.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/R$layout.class
Normal file
BIN
bin/org/solovyev/android/calculator/R$layout.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/R$string.class
Normal file
BIN
bin/org/solovyev/android/calculator/R$string.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/R$style.class
Normal file
BIN
bin/org/solovyev/android/calculator/R$style.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/R$styleable.class
Normal file
BIN
bin/org/solovyev/android/calculator/R$styleable.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/R.class
Normal file
BIN
bin/org/solovyev/android/calculator/R.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/calculator/SimpleHistoryHelper.class
Normal file
BIN
bin/org/solovyev/android/calculator/SimpleHistoryHelper.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
bin/org/solovyev/android/view/DragButton.class
Normal file
BIN
bin/org/solovyev/android/view/DragButton.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/view/DragDirection.class
Normal file
BIN
bin/org/solovyev/android/view/DragDirection.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/view/DragEvent.class
Normal file
BIN
bin/org/solovyev/android/view/DragEvent.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/view/OnDragListener.class
Normal file
BIN
bin/org/solovyev/android/view/OnDragListener.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/android/view/SimpleOnDragListener.class
Normal file
BIN
bin/org/solovyev/android/view/SimpleOnDragListener.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/util/StringUtils.class
Normal file
BIN
bin/org/solovyev/util/StringUtils.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/util/date/DateUtils.class
Normal file
BIN
bin/org/solovyev/util/date/DateUtils.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/util/math/MathEntity.class
Normal file
BIN
bin/org/solovyev/util/math/MathEntity.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/util/math/MathEntityType.class
Normal file
BIN
bin/org/solovyev/util/math/MathEntityType.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/util/math/MathUtils.class
Normal file
BIN
bin/org/solovyev/util/math/MathUtils.class
Normal file
Binary file not shown.
BIN
bin/org/solovyev/util/math/Point2d.class
Normal file
BIN
bin/org/solovyev/util/math/Point2d.class
Normal file
Binary file not shown.
BIN
bin/resources.ap_
Normal file
BIN
bin/resources.ap_
Normal file
Binary file not shown.
11
default.properties
Normal file
11
default.properties
Normal file
@ -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
|
5
find_bugs_excluded_filter.xml
Normal file
5
find_bugs_excluded_filter.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<FindBugsFilter>
|
||||||
|
<Match>
|
||||||
|
<Class name="org.solovyev.android.calculator.R" />
|
||||||
|
</Match>
|
||||||
|
</FindBugsFilter>
|
116
gen/org/solovyev/android/calculator/R.java
Normal file
116
gen/org/solovyev/android/calculator/R.java
Normal file
@ -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;
|
||||||
|
};
|
||||||
|
}
|
BIN
res/drawable-hdpi/icon.png
Normal file
BIN
res/drawable-hdpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
BIN
res/drawable-ldpi/icon.png
Normal file
BIN
res/drawable-ldpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
res/drawable-mdpi/icon.png
Normal file
BIN
res/drawable-mdpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
65
res/layout/main.xml
Normal file
65
res/layout/main.xml
Normal file
@ -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>
|
4
res/values-ru/strings.xml
Normal file
4
res/values-ru/strings.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name_caption">Калькулятор</string>
|
||||||
|
</resources>
|
7
res/values/attrs.xml
Normal file
7
res/values/attrs.xml
Normal file
@ -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>
|
5
res/values/strings.xml
Normal file
5
res/values/strings.xml
Normal file
@ -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>
|
15
res/values/styles.xml
Normal file
15
res/values/styles.xml
Normal file
@ -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>
|
196
src/org/solovyev/android/calculator/Calculator.java
Normal file
196
src/org/solovyev/android/calculator/Calculator.java
Normal file
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
src/org/solovyev/android/calculator/EditorHistoryState.java
Normal file
37
src/org/solovyev/android/calculator/EditorHistoryState.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
8
src/org/solovyev/android/calculator/HistoryAction.java
Normal file
8
src/org/solovyev/android/calculator/HistoryAction.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
public enum HistoryAction {
|
||||||
|
|
||||||
|
redo,
|
||||||
|
undo;
|
||||||
|
|
||||||
|
}
|
24
src/org/solovyev/android/calculator/HistoryHelper.java
Normal file
24
src/org/solovyev/android/calculator/HistoryHelper.java
Normal file
@ -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);
|
||||||
|
}
|
10
src/org/solovyev/android/calculator/JsclOperation.java
Normal file
10
src/org/solovyev/android/calculator/JsclOperation.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
public enum JsclOperation {
|
||||||
|
|
||||||
|
simplify,
|
||||||
|
elementary,
|
||||||
|
importCommands,
|
||||||
|
numeric;
|
||||||
|
|
||||||
|
}
|
31
src/org/solovyev/android/calculator/Preprocessor.java
Normal file
31
src/org/solovyev/android/calculator/Preprocessor.java
Normal file
@ -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 + "\");";
|
||||||
|
}
|
||||||
|
}
|
91
src/org/solovyev/android/calculator/SimpleHistoryHelper.java
Normal file
91
src/org/solovyev/android/calculator/SimpleHistoryHelper.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
168
src/org/solovyev/android/view/DragButton.java
Normal file
168
src/org/solovyev/android/view/DragButton.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
src/org/solovyev/android/view/DragDirection.java
Normal file
7
src/org/solovyev/android/view/DragDirection.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package org.solovyev.android.view;
|
||||||
|
|
||||||
|
public enum DragDirection {
|
||||||
|
|
||||||
|
up,
|
||||||
|
down;
|
||||||
|
}
|
33
src/org/solovyev/android/view/DragEvent.java
Normal file
33
src/org/solovyev/android/view/DragEvent.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
22
src/org/solovyev/android/view/OnDragListener.java
Normal file
22
src/org/solovyev/android/view/OnDragListener.java
Normal file
@ -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);
|
||||||
|
|
||||||
|
}
|
93
src/org/solovyev/android/view/SimpleOnDragListener.java
Normal file
93
src/org/solovyev/android/view/SimpleOnDragListener.java
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
}
|
17
src/org/solovyev/util/StringUtils.java
Normal file
17
src/org/solovyev/util/StringUtils.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
11
src/org/solovyev/util/date/DateUtils.java
Normal file
11
src/org/solovyev/util/date/DateUtils.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
src/org/solovyev/util/math/MathEntity.java
Normal file
37
src/org/solovyev/util/math/MathEntity.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
57
src/org/solovyev/util/math/MathEntityType.java
Normal file
57
src/org/solovyev/util/math/MathEntityType.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
39
src/org/solovyev/util/math/MathUtils.java
Normal file
39
src/org/solovyev/util/math/MathUtils.java
Normal file
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
src/org/solovyev/util/math/Point2d.java
Normal file
37
src/org/solovyev/util/math/Point2d.java
Normal file
@ -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 + "]";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user