drag button calibration

This commit is contained in:
serso 2011-07-16 23:25:12 +04:00
parent aa512ed335
commit 70ff5a109e
15 changed files with 532 additions and 161 deletions

View File

@ -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>

View File

@ -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.

View 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
View 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>

View File

@ -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>

View File

@ -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
View 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>

View File

@ -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!");
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -3,5 +3,7 @@ package org.solovyev.android.view;
public enum DragDirection {
up,
down;
down,
left,
right;
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}