drag button calibration
This commit is contained in:
parent
aa512ed335
commit
70ff5a109e
@ -4,15 +4,20 @@
|
||||
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>
|
||||
<uses-sdk a:minSdkVersion="8"/>
|
||||
|
||||
</a:application>
|
||||
<application a:icon="@drawable/icon" a:label="@string/c_app_name">
|
||||
|
||||
<activity a:name=".CalculatorActivity" a:label="@string/c_app_name">
|
||||
<intent-filter>
|
||||
<action a:name="android.intent.action.MAIN" />
|
||||
<category a:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity a:name=".CalculatorPreferencesActivity" a:label="@string/c_app_settings"/>
|
||||
<activity a:name=".DragButtonCalibrationActivity" a:label="@string/c_prefs_drag_button_calibration"/>
|
||||
|
||||
</application>
|
||||
</manifest>
|
@ -30,43 +30,63 @@ containing a value of this type.
|
||||
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 int calibrationButton=0x7f080000;
|
||||
public static final int calibrationStart=0x7f080001;
|
||||
public static final int curlyBracketsButton=0x7f080015;
|
||||
public static final int editText=0x7f080002;
|
||||
public static final int eigthDigitButton=0x7f080011;
|
||||
public static final int equalsButton=0x7f080013;
|
||||
public static final int fiveDigitButton=0x7f08000b;
|
||||
public static final int fourDigitButton=0x7f08000a;
|
||||
public static final int historyButton=0x7f08001a;
|
||||
public static final int menu_item_help=0x7f08001d;
|
||||
public static final int menu_item_settings=0x7f08001c;
|
||||
public static final int minusButton=0x7f08000e;
|
||||
public static final int muliplicationButton=0x7f080007;
|
||||
public static final int nineDigitButton=0x7f080012;
|
||||
public static final int numericButton=0x7f080018;
|
||||
public static final int oneDigitButton=0x7f080004;
|
||||
public static final int piButton=0x7f08001b;
|
||||
public static final int plusButton=0x7f080008;
|
||||
public static final int pointDigitButton=0x7f080017;
|
||||
public static final int resultEditText=0x7f080003;
|
||||
public static final int roundBracketsButton=0x7f080009;
|
||||
public static final int sevenDigitButton=0x7f080010;
|
||||
public static final int simplifyButton=0x7f080019;
|
||||
public static final int sixDigitButton=0x7f08000c;
|
||||
public static final int sqrtButton=0x7f080014;
|
||||
public static final int squareBracketsButton=0x7f08000f;
|
||||
public static final int subtractionButton=0x7f08000d;
|
||||
public static final int threeDigitButton=0x7f080006;
|
||||
public static final int twoDigitButton=0x7f080005;
|
||||
public static final int zeroDigitButton=0x7f080016;
|
||||
}
|
||||
public static final class layout {
|
||||
public static final int main=0x7f030000;
|
||||
public static final int drag_button_calibration=0x7f030000;
|
||||
public static final int main=0x7f030001;
|
||||
}
|
||||
public static final class menu {
|
||||
public static final int main_menu=0x7f070000;
|
||||
}
|
||||
public static final class string {
|
||||
public static final int app_name_caption=0x7f040000;
|
||||
public static final int syntax_error=0x7f040001;
|
||||
public static final int c_app_name=0x7f050000;
|
||||
public static final int c_app_settings=0x7f050001;
|
||||
public static final int c_down=0x7f050008;
|
||||
public static final int c_help=0x7f050004;
|
||||
public static final int c_prefs_drag_button_calibration=0x7f050006;
|
||||
public static final int c_prefs_drag_button_calibration_summary=0x7f050007;
|
||||
public static final int c_prefs_main_category=0x7f050005;
|
||||
public static final int c_restart=0x7f05000a;
|
||||
public static final int c_settings=0x7f050003;
|
||||
public static final int c_up=0x7f050009;
|
||||
public static final int syntax_error=0x7f050002;
|
||||
}
|
||||
public static final class style {
|
||||
public static final int digitButtonStyle=0x7f050001;
|
||||
public static final int editTextInputStyle=0x7f050000;
|
||||
public static final int digitButtonStyle=0x7f060001;
|
||||
public static final int editTextInputStyle=0x7f060000;
|
||||
}
|
||||
public static final class xml {
|
||||
public static final int preferences=0x7f040000;
|
||||
}
|
||||
public static final class styleable {
|
||||
/** Attributes that can be used with a DragButton.
|
||||
|
27
res/layout/drag_button_calibration.xml
Normal file
27
res/layout/drag_button_calibration.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?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:padding="6dp"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="fill_parent">
|
||||
|
||||
|
||||
<org.solovyev.android.view.DragButton a:id="@+id/calibrationButton"
|
||||
a:text=""
|
||||
calc:textUp="@string/c_up"
|
||||
calc:textDown="@string/c_down"
|
||||
style="@style/digitButtonStyle"
|
||||
a:layout_width="50dp"
|
||||
a:layout_height="50dp"
|
||||
a:gravity="center_vertical" />
|
||||
|
||||
<Button a:id="@+id/calibrationStart"
|
||||
a:text="@string/c_restart"
|
||||
a:layout_width="wrap_content"
|
||||
a:layout_height="wrap_content"
|
||||
a:onClick="restartClickHandler"
|
||||
a:gravity="bottom"/>
|
||||
</LinearLayout>
|
9
res/menu/main_menu.xml
Normal file
9
res/menu/main_menu.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<menu xmlns:a="http://schemas.android.com/apk/res/android">
|
||||
<item a:id="@+id/menu_item_settings"
|
||||
a:title="@string/c_settings"/>
|
||||
|
||||
<item a:id="@+id/menu_item_help"
|
||||
a:title="@string/c_help"/>
|
||||
</menu>
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name_caption">Калькулятор</string>
|
||||
<string name="c_app_name">Калькулятор</string>
|
||||
</resources>
|
||||
|
@ -1,5 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name_caption">Calculator</string>
|
||||
<string name="c_app_name">Calculator</string>
|
||||
<string name="c_app_settings">Calculator</string>
|
||||
<string name="syntax_error">Syntax error</string>
|
||||
<string name="c_settings">Settings</string>
|
||||
<string name="c_help">Help</string>
|
||||
<string name="c_prefs_main_category">Main settings</string>
|
||||
<string name="c_prefs_drag_button_calibration">Drag button calibration</string>
|
||||
<string name="c_prefs_drag_button_calibration_summary">Allows to calibrate drag button behaviour</string>
|
||||
<string name="c_down">Down</string>
|
||||
<string name="c_up">Up</string>
|
||||
<string name="c_restart">Restart</string>
|
||||
</resources>
|
||||
|
20
res/xml/preferences.xml
Normal file
20
res/xml/preferences.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory a:title="@string/c_prefs_main_category">
|
||||
|
||||
|
||||
<Preference
|
||||
a:title="@string/c_prefs_drag_button_calibration"
|
||||
a:summary="@string/c_prefs_drag_button_calibration_summary"
|
||||
a:key="dragButtonCalibration"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
a:title="Checkbox Preference"
|
||||
a:defaultValue="false"
|
||||
a:summary="This preference can be true or false"
|
||||
a:key="checkboxPref"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
@ -3,13 +3,11 @@ package org.solovyev.android.calculator;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.*;
|
||||
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.android.view.*;
|
||||
import org.solovyev.util.StringUtils;
|
||||
import org.solovyev.util.math.MathEntityType;
|
||||
|
||||
@ -19,14 +17,14 @@ import bsh.Interpreter;
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
public class Calculator extends Activity {
|
||||
public class CalculatorActivity extends Activity {
|
||||
|
||||
@NotNull
|
||||
private EditText editText;
|
||||
|
||||
|
||||
@NotNull
|
||||
private EditText resultEditText;
|
||||
|
||||
@ -35,18 +33,36 @@ public class Calculator extends Activity {
|
||||
|
||||
@NotNull
|
||||
private HistoryHelper<EditorHistoryState> historyHelper;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
|
||||
/**
|
||||
* 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();
|
||||
final SimpleOnDragListener onDragListener = new SimpleOnDragListener(new SimpleOnDragListener.DragProcessor() {
|
||||
@Override
|
||||
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
|
||||
boolean result = isDirectionSupported(dragButton, dragDirection);
|
||||
|
||||
if (result) {
|
||||
processButtonAction(dragButton, getActionText(dragButton, dragDirection));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isDirectionSupported(@NotNull DragButton dragButton, @NotNull DragDirection direction) {
|
||||
return !StringUtils.isEmpty(getActionText(dragButton, direction));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// todo serso: check if there is more convenient method for doing this
|
||||
final R.id ids = new R.id();
|
||||
@ -59,31 +75,31 @@ public class Calculator extends Activity {
|
||||
((DragButton) view).setOnDragListener(onDragListener);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(Calculator.class.getName(), e.getMessage());
|
||||
Log.e(CalculatorActivity.class.getName(), e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(Calculator.class.getName(), e.getMessage());
|
||||
Log.e(CalculatorActivity.class.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
((DragButton) findViewById(R.id.historyButton)).setOnDragListener(new HistoryOnDragListener());
|
||||
|
||||
((DragButton) findViewById(R.id.historyButton)).setOnDragListener(new SimpleOnDragListener(new HistoryDragProcessor()));
|
||||
|
||||
this.interpreter = new Interpreter();
|
||||
|
||||
try {
|
||||
interpreter.eval(Preprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands"));
|
||||
} catch (EvalError e) {
|
||||
Log.e(Calculator.class.getName(), e.getMessage());
|
||||
Log.e(CalculatorActivity.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);
|
||||
}
|
||||
@ -97,25 +113,30 @@ public class Calculator extends Activity {
|
||||
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());
|
||||
Log.e(CalculatorActivity.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);
|
||||
private final class HistoryDragProcessor implements SimpleOnDragListener.DragProcessor {
|
||||
|
||||
@Override
|
||||
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
|
||||
boolean result = false;
|
||||
|
||||
Log.d(String.valueOf(dragButton.getId()), "History on drag event start: " + dragDirection);
|
||||
|
||||
String actionText = getActionText(dragButton, dragDirection);
|
||||
if (!StringUtils.isEmpty(actionText)) {
|
||||
try {
|
||||
result = true;
|
||||
|
||||
final HistoryAction historyAction = HistoryAction.valueOf(actionText);
|
||||
if ( historyHelper.isActionAvailable(historyAction) ){
|
||||
if (historyHelper.isActionAvailable(historyAction)) {
|
||||
final EditorHistoryState newState = historyHelper.doAction(historyAction, getCurrentHistoryState());
|
||||
if (newState != null) {
|
||||
setCurrentHistoryState(newState);
|
||||
@ -125,51 +146,53 @@ public class Calculator extends Activity {
|
||||
Log.e(String.valueOf(dragButton.getId()), "Unsupported history action: " + actionText);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getActionText(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||
private static String getActionText(@NotNull DragButton dragButton, @NotNull DragDirection direction) {
|
||||
final String result;
|
||||
|
||||
switch(event.getDirection()) {
|
||||
|
||||
switch (direction) {
|
||||
case up:
|
||||
result = dragButton.getTextUp();
|
||||
break;
|
||||
|
||||
|
||||
case down:
|
||||
result = dragButton.getTextDown();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
result = null;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setCurrentHistoryState(@Nullable EditorHistoryState editorHistoryState) {
|
||||
|
||||
public void setCurrentHistoryState(@NotNull 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();
|
||||
//Toast.makeText(CalculatorActivity.this, text, Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
final MathEntityType type = MathEntityType.getType(text);
|
||||
|
||||
|
||||
int cursorPositionOffset = 0;
|
||||
|
||||
if (type != null) {
|
||||
@ -187,10 +210,43 @@ public class Calculator extends Activity {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.editText.getText().insert(this.editText.getSelectionStart(), text);
|
||||
this.editText.setSelection(this.editText.getSelectionStart() + cursorPositionOffset, this.editText.getSelectionEnd() + cursorPositionOffset);
|
||||
this.historyHelper.addState(getCurrentHistoryState());
|
||||
this.historyHelper.addState(getCurrentHistoryState());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
final MenuInflater menuInflater = getMenuInflater();
|
||||
menuInflater.inflate(R.menu.main_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
boolean result;
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_item_settings:
|
||||
showSettings();
|
||||
result = true;
|
||||
case R.id.menu_item_help:
|
||||
showHelp();
|
||||
result = true;
|
||||
default:
|
||||
result = super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void showSettings() {
|
||||
startActivity(new Intent(this, CalculatorPreferencesActivity.class));
|
||||
}
|
||||
|
||||
private void showHelp() {
|
||||
Log.d(CalculatorActivity.class + "showHelp()", "Show help!");
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
import org.apache.http.Header;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.util.List;
|
||||
import java.util.prefs.PreferencesFactory;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 7/16/11
|
||||
* Time: 6:37 PM
|
||||
*/
|
||||
public class CalculatorPreferencesActivity extends PreferenceActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
final Preference dragButtonCalibration = findPreference("dragButtonCalibration");
|
||||
dragButtonCalibration.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
startActivity(new Intent(CalculatorPreferencesActivity.this, DragButtonCalibrationActivity.class));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle state) {
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.view.*;
|
||||
import org.solovyev.util.math.MathUtils;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 7/16/11
|
||||
* Time: 7:28 PM
|
||||
*/
|
||||
public class DragButtonCalibrationActivity extends Activity {
|
||||
|
||||
|
||||
@NotNull
|
||||
private DragDirection dragDirection = DragDirection.up;
|
||||
|
||||
private final List<DragData> dragHistory = new ArrayList<DragData>();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.drag_button_calibration);
|
||||
|
||||
final DragButton calibrationButton = (DragButton) findViewById(R.id.calibrationButton);
|
||||
calibrationButton.setOnDragListener(new CalibrationOnDragListener());
|
||||
|
||||
createDragDirection();
|
||||
}
|
||||
|
||||
private void createDragDirection() {
|
||||
dragDirection = Math.random() > 0.5 ? DragDirection.up : DragDirection.down;
|
||||
|
||||
Toast.makeText(this, dragDirection.name(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public void restartClickHandler(View v) {
|
||||
createDragDirection();
|
||||
}
|
||||
|
||||
|
||||
private class CalibrationOnDragListener implements OnDragListener {
|
||||
|
||||
@Override
|
||||
public boolean isSuppressOnClickEvent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||
final Point2d startPoint = event.getStartPoint();
|
||||
final MotionEvent motionEvent = event.getMotionEvent();
|
||||
|
||||
// init end point
|
||||
final Point2d endPoint = new Point2d(motionEvent.getX(), motionEvent.getY());
|
||||
|
||||
float distance = MathUtils.getDistance(startPoint, endPoint);
|
||||
|
||||
double angle = Math.toDegrees(MathUtils.getAngle(startPoint, MathUtils.sum(startPoint, SimpleOnDragListener.axis), endPoint));
|
||||
|
||||
assert dragDirection == DragDirection.up || dragDirection == DragDirection.down;
|
||||
if (dragDirection == DragDirection.up) {
|
||||
angle = 180 - angle;
|
||||
}
|
||||
|
||||
dragHistory.add(new DragData(distance, angle, dragDirection));
|
||||
|
||||
createDragDirection();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
final List<Double> angleValues = new ArrayList<Double>();
|
||||
final List<Double> distanceValues = new ArrayList<Double>();
|
||||
for (DragData dragData : dragHistory) {
|
||||
angleValues.add(dragData.getAngle());
|
||||
distanceValues.add((double) dragData.getDistance());
|
||||
}
|
||||
|
||||
double angleMean = MathUtils.countMean(angleValues);
|
||||
double angleDeviation = MathUtils.countStandardDeviation(angleMean, angleValues);
|
||||
|
||||
double distanceMean = MathUtils.countMean(distanceValues);
|
||||
double distanceDeviation = MathUtils.countStandardDeviation(distanceMean, distanceValues);
|
||||
|
||||
Toast.makeText(this, "Angle: m=" + angleMean + ", d=" + angleDeviation, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(this, "Distance: m=" + distanceMean + ", d=" + distanceDeviation, Toast.LENGTH_SHORT).show();
|
||||
|
||||
}
|
||||
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
|
||||
private class DragData {
|
||||
|
||||
private float distance;
|
||||
|
||||
private double angle;
|
||||
|
||||
@NotNull
|
||||
private DragDirection direction;
|
||||
|
||||
private DragData(float distance, double angle, @NotNull DragDirection direction) {
|
||||
this.distance = distance;
|
||||
this.angle = angle;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public float getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public double getAngle() {
|
||||
return angle;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DragDirection getDirection() {
|
||||
return direction;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package org.solovyev.android.view;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.common.utils.StringsUtils;
|
||||
import org.solovyev.util.StringUtils;
|
||||
import org.solovyev.util.math.MathUtils;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
@ -93,26 +94,29 @@ public class DragButton extends Button {
|
||||
return onDragListener;
|
||||
}
|
||||
|
||||
public void setTextUp(String textUp) {
|
||||
public void setTextUp(@Nullable String textUp) {
|
||||
this.textUp = textUp;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTextUp() {
|
||||
return textUp;
|
||||
}
|
||||
|
||||
public void setTextDown(String textDown) {
|
||||
public void setTextDown(@Nullable String textDown) {
|
||||
this.textDown = textDown;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTextDown() {
|
||||
return textDown;
|
||||
}
|
||||
|
||||
public void setTextMiddle(String textMiddle) {
|
||||
public void setTextMiddle(@Nullable String textMiddle) {
|
||||
this.textMiddle = textMiddle;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTextMiddle() {
|
||||
return textMiddle;
|
||||
}
|
||||
@ -129,7 +133,11 @@ public class DragButton extends Button {
|
||||
public boolean onTouch(@NotNull View v, @NotNull MotionEvent event) {
|
||||
// processing on touch event
|
||||
|
||||
if (onDragListener != null) {
|
||||
// in order to avoid possible NPEs
|
||||
final Point2d localStartPoint = startPoint;
|
||||
final OnDragListener localOnDragListener = onDragListener;
|
||||
|
||||
if (localOnDragListener != null) {
|
||||
// only if onDrag() listener specified
|
||||
|
||||
Log.d(String.valueOf(getId()), "onTouch() for: " + getId() + " . Motion event: " + event);
|
||||
@ -150,8 +158,8 @@ public class DragButton extends Button {
|
||||
case MotionEvent.ACTION_UP:
|
||||
// stop tracking
|
||||
|
||||
if (onDragListener.onDrag(DragButton.this, new DragEvent(startPoint, event))) {
|
||||
if (onDragListener.isSuppressOnClickEvent()) {
|
||||
if (localStartPoint != null && localOnDragListener.onDrag(DragButton.this, new DragEvent(localStartPoint, event))) {
|
||||
if (localOnDragListener.isSuppressOnClickEvent()) {
|
||||
// prevent on click action
|
||||
setPressed(false);
|
||||
}
|
||||
|
@ -3,5 +3,7 @@ package org.solovyev.android.view;
|
||||
public enum DragDirection {
|
||||
|
||||
up,
|
||||
down;
|
||||
down,
|
||||
left,
|
||||
right;
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ import org.solovyev.util.math.Point2d;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class DragEvent {
|
||||
|
||||
|
||||
@NotNull
|
||||
private final Point2d startPoint;
|
||||
|
||||
|
||||
@NotNull
|
||||
private final MotionEvent motionEvent;
|
||||
|
||||
@ -18,16 +18,21 @@ public class DragEvent {
|
||||
this.motionEvent = motionEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return motion event started at start point
|
||||
*/
|
||||
@NotNull
|
||||
public MotionEvent getMotionEvent() {
|
||||
return motionEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return start point of dragging
|
||||
*/
|
||||
@NotNull
|
||||
public Point2d getStartPoint() {
|
||||
return startPoint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
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;
|
||||
|
||||
@ -12,8 +10,8 @@ import android.view.MotionEvent;
|
||||
public class SimpleOnDragListener implements OnDragListener {
|
||||
|
||||
@NotNull
|
||||
private final Point2d axis = new Point2d(0, 1);
|
||||
|
||||
public static final Point2d axis = new Point2d(0, 1);
|
||||
|
||||
private float minDragDist = 20f;
|
||||
|
||||
private float maxDragDist = 80f;
|
||||
@ -21,73 +19,79 @@ public class SimpleOnDragListener implements OnDragListener {
|
||||
// max angle (in degrees!) between start and end point vector and axis
|
||||
// vector to register drag event
|
||||
private double maxAngle = 30;
|
||||
|
||||
@NotNull
|
||||
private DragProcessor dragProcessor;
|
||||
|
||||
public SimpleOnDragListener() {
|
||||
}
|
||||
|
||||
public SimpleOnDragListener(@NotNull DragProcessor dragProcessor) {
|
||||
this.dragProcessor = dragProcessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||
boolean result = false;
|
||||
|
||||
logDragEvent(dragButton, event);
|
||||
|
||||
processButtonAction(dragButton, getActionText(dragButton, event));
|
||||
|
||||
final Point2d startPoint = event.getStartPoint();
|
||||
final MotionEvent motionEvent = event.getMotionEvent();
|
||||
|
||||
// init end point
|
||||
final Point2d endPoint = new Point2d(motionEvent.getX(), motionEvent.getY());
|
||||
|
||||
float distance = MathUtils.getDistance(startPoint, endPoint);
|
||||
|
||||
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) {
|
||||
result = dragProcessor.processDragEvent(direction, dragButton, startPoint, motionEvent);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@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");
|
||||
final Point2d startPoint = event.getStartPoint();
|
||||
final MotionEvent motionEvent = event.getMotionEvent();
|
||||
final Point2d endPoint = new Point2d(motionEvent.getX(), motionEvent.getY());
|
||||
|
||||
Log.d(String.valueOf(dragButton.getId()), "Start point: " + startPoint + ", End point: " + endPoint);
|
||||
Log.d(String.valueOf(dragButton.getId()), "Distance: " + MathUtils.getDistance(startPoint, endPoint));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Angle: " + Math.toDegrees(MathUtils.getAngle(startPoint, MathUtils.sum(startPoint, axis), endPoint)));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Axis: " + axis + " Vector: " + MathUtils.subtract(endPoint, startPoint));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Total time: " + (motionEvent.getEventTime() - motionEvent.getDownTime()) + " ms");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DragProcessor getDragProcessor() {
|
||||
return dragProcessor;
|
||||
}
|
||||
|
||||
public void setDragProcessor(@NotNull DragProcessor dragProcessor) {
|
||||
this.dragProcessor = dragProcessor;
|
||||
}
|
||||
|
||||
public interface DragProcessor {
|
||||
|
||||
boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent);
|
||||
}
|
||||
}
|
@ -2,17 +2,19 @@ package org.solovyev.util.math;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MathUtils {
|
||||
|
||||
public static float getDistance(@NotNull Point2d startPoint,
|
||||
@NotNull Point2d endPoint) {
|
||||
@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());
|
||||
}
|
||||
@ -23,7 +25,7 @@ public class MathUtils {
|
||||
}
|
||||
|
||||
public static float getAngle(@NotNull Point2d startPoint,
|
||||
@NotNull Point2d axisEndPoint, @NotNull Point2d endPoint) {
|
||||
@NotNull Point2d axisEndPoint, @NotNull Point2d endPoint) {
|
||||
final Point2d axisVector = subtract(axisEndPoint, startPoint);
|
||||
final Point2d vector = subtract(endPoint, startPoint);
|
||||
|
||||
@ -36,4 +38,24 @@ public class MathUtils {
|
||||
return (float) Math.acos((-a_2 + b_2 + c_2) / (2 * b * c));
|
||||
}
|
||||
|
||||
public static double countMean(@NotNull List<Double> objects) {
|
||||
|
||||
double sum = 0d;
|
||||
for (Double object : objects) {
|
||||
sum += object;
|
||||
}
|
||||
|
||||
return objects.size() == 0 ? 0d : (sum / objects.size());
|
||||
}
|
||||
|
||||
public static double countStandardDeviation(@NotNull Double mean, @NotNull List<Double> objects) {
|
||||
double sum = 0d;
|
||||
|
||||
for (Double object : objects) {
|
||||
sum += Math.pow(object - mean, 2);
|
||||
}
|
||||
|
||||
return objects.size() == 0 ? 0d : Math.sqrt(sum / objects.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user