abouttreesummaryrefslogcommitdiff
path: root/srcs/juloo.keyboard2/Gesture.java
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/juloo.keyboard2/Gesture.java')
-rw-r--r--srcs/juloo.keyboard2/Gesture.java141
1 files changed, 141 insertions, 0 deletions
diff --git a/srcs/juloo.keyboard2/Gesture.java b/srcs/juloo.keyboard2/Gesture.java
new file mode 100644
index 0000000..5ee666b
--- /dev/null
+++ b/srcs/juloo.keyboard2/Gesture.java
@@ -0,0 +1,141 @@
+package juloo.keyboard2;
+
+public final class Gesture
+{
+ /** The pointer direction that caused the last state change.
+ Integer from 0 to 15 (included). */
+ int current_dir;
+
+ State state;
+
+ public Gesture(int starting_direction)
+ {
+ current_dir = starting_direction;
+ state = State.Swiped;
+ }
+
+ enum State
+ {
+ Cancelled,
+ Swiped,
+ Rotating_clockwise,
+ Rotating_anticlockwise,
+ Ended_swipe,
+ Ended_center,
+ Ended_clockwise,
+ Ended_anticlockwise
+ }
+
+ enum Name
+ {
+ None,
+ Swipe,
+ Roundtrip,
+ Circle,
+ Anticircle
+ }
+
+ /** Angle to travel before a rotation gesture starts. A threshold too low
+ would be too easy to reach while doing back and forth gestures, as the
+ quadrants are very small. In the same unit as [current_dir] */
+ static final int ROTATION_THRESHOLD = 2;
+
+ /** Return the currently recognized gesture. Return [null] if no gesture is
+ recognized. Might change everytime [changed_direction] return [true]. */
+ public Name get_gesture()
+ {
+ switch (state)
+ {
+ case Cancelled:
+ return Name.None;
+ case Swiped:
+ case Ended_swipe:
+ return Name.Swipe;
+ case Ended_center:
+ return Name.Roundtrip;
+ case Rotating_clockwise:
+ case Ended_clockwise:
+ return Name.Circle;
+ case Rotating_anticlockwise:
+ case Ended_anticlockwise:
+ return Name.Anticircle;
+ }
+ return Name.None; // Unreachable
+ }
+
+ public boolean is_in_progress()
+ {
+ switch (state)
+ {
+ case Swiped:
+ case Rotating_clockwise:
+ case Rotating_anticlockwise:
+ return true;
+ }
+ return false;
+ }
+
+ public int current_direction() { return current_dir; }
+
+ /** The pointer changed direction. Return [true] if the gesture changed
+ state and [get_gesture] return a different value. */
+ public boolean changed_direction(int direction)
+ {
+ int d = dir_diff(current_dir, direction);
+ boolean clockwise = d > 0;
+ switch (state)
+ {
+ case Swiped:
+ if (Math.abs(d) < ROTATION_THRESHOLD)
+ return false;
+ // Start a rotation
+ state = (clockwise) ?
+ State.Rotating_clockwise : State.Rotating_anticlockwise;
+ current_dir = direction;
+ return true;
+ // Check that rotation is not reversing
+ case Rotating_clockwise:
+ case Rotating_anticlockwise:
+ current_dir = direction;
+ if ((state == State.Rotating_clockwise) == clockwise)
+ return false;
+ state = State.Cancelled;
+ return true;
+ }
+ return false;
+ }
+
+ /** Return [true] if [get_gesture] will return a different value. */
+ public boolean moved_to_center()
+ {
+ switch (state)
+ {
+ case Swiped: state = State.Ended_center; return true;
+ case Rotating_clockwise: state = State.Ended_clockwise; return false;
+ case Rotating_anticlockwise: state = State.Ended_anticlockwise; return false;
+ }
+ return false;
+ }
+
+ /** Will not change the gesture state. */
+ public void pointer_up()
+ {
+ switch (state)
+ {
+ case Swiped: state = State.Ended_swipe; break;
+ case Rotating_clockwise: state = State.Ended_clockwise; break;
+ case Rotating_anticlockwise: state = State.Ended_anticlockwise; break;
+ }
+ }
+
+ static int dir_diff(int d1, int d2)
+ {
+ final int n = 16;
+ // Shortest-path in modulo arithmetic
+ if (d1 == d2)
+ return 0;
+ int left = (d1 - d2 + n) % n;
+ int right = (d2 - d1 + n) % n;
+ return (left < right) ? -left : right;
+ }
+}