package org.geogebra.web.html5.gui.util;
import com.google.gwt.user.client.Timer;
/**
* Class used in view controllers to handle long touches.
*/
public class LongTouchTimer extends Timer {
private static final int SHOW_CONTEXT_MENU_DELAY = 500;
private static final int MOVE_THRESHOLD = 10;
/**
* Interface for handling long touches.
*/
public interface LongTouchHandler {
/**
* Handles the long touch event.
*
* @param x
* the x coordinate of the long touch
* @param y
* the y coordinate of the long touch
*/
public void handleLongTouch(int x, int y);
}
private LongTouchHandler handler;
private int x;
private int y;
private boolean longTouchHappened = false;
public LongTouchTimer() {
this(null);
}
/**
* @param handler
* used when the timer elapsed.
*/
public LongTouchTimer(LongTouchHandler handler) {
this.handler = handler;
this.x = 0;
this.y = 0;
longTouchHappened = false;
}
@Override
public void run() {
if (handler == null) {
return;
}
longTouchHappened = true;
handler.handleLongTouch(x, y);
}
/**
* Schedules the timer with a default delay value.
*
* @param handler
* the handler to use when the timer fires
* @param x
* the x coordinate passed to the handler
* @param y
* the y coordinate passed to the handler
*/
public void schedule(LongTouchHandler handler, int x, int y) {
longTouchHappened = false;
schedule(handler, x, y, SHOW_CONTEXT_MENU_DELAY);
}
/**
* Schedules the timer with {@code delayMillis} ms.
*
* @param handler
* the handler to use when the timer fires
* @param x
* the x coordinate passed to the handler
* @param y
* the y coordinate passed to the handler
* @param delayMillis
* how long to wait before the timer elapses, in milliseconds
*/
public void schedule(LongTouchHandler handler, int x, int y, int delayMillis) {
this.handler = handler;
this.x = x;
this.y = y;
longTouchHappened = false;
schedule(delayMillis);
}
/**
* Reschedules the timer if it is running and the new mouse location is
* within boundaries, with a default delay value.
*
* @param handler
* the handler to use when the timer fires
* @param x
* the x coordinate passed to the handler
* @param y
* the y coordinate passed to the handler
*/
public void rescheduleIfRunning(LongTouchHandler handler, int x, int y) {
rescheduleIfRunning(handler, x, y, SHOW_CONTEXT_MENU_DELAY, true);
}
/**
* Reschedules the timer if it is running, with a default delay value.
*
* @param handler
* the handler to use when the timer fires
* @param x
* the x coordinate passed to the handler
* @param y
* the y coordinate passed to the handler
* @param shouldCancel
* if true, the timer will be cancelled if the mouse moved too
* much
*/
public void rescheduleIfRunning(LongTouchHandler handler, int x, int y,
boolean shouldCancel) {
rescheduleIfRunning(handler, x, y, SHOW_CONTEXT_MENU_DELAY,
shouldCancel);
}
/**
* Reschedules the timer if it is running, with {@code delayMillis} ms.
*
* @param x
* the x coordinate passed to the handler
* @param y
* the y coordinate passed to the handler
* @param delayMillis
* how long to wait before the timer elapses, in milliseconds
* @param shouldCancel
* if true, the timer will be cancelled if the mouse moved too
* much
*/
public void rescheduleIfRunning(LongTouchHandler handler, int x, int y,
int delayMillis, boolean shouldCancel) {
if (isRunning()) {
longTouchHappened = false;
cancel();
if (!shouldCancel || pointWithinLimit(x, y)) {
schedule(handler, x, y, delayMillis);
}
}
}
public void cancelTimer() {
x = 0;
y = 0;
handler = null;
longTouchHappened = false;
cancel();
}
private boolean pointWithinLimit(int nx, int ny) {
if (Math.abs(nx - x) < MOVE_THRESHOLD
&& Math.abs(ny - y) < MOVE_THRESHOLD) {
return true;
}
return false;
}
public boolean isLongTouchHappened() {
return longTouchHappened;
}
}