package org.geogebra.web.html5.event; import java.util.LinkedList; import org.geogebra.common.awt.GPoint; import org.geogebra.common.euclidian.event.AbstractEvent; import org.geogebra.common.euclidian.event.PointerEventType; import com.google.gwt.core.client.JsArray; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Touch; import com.google.gwt.event.dom.client.HumanInputEvent; import com.google.gwt.event.dom.client.MouseEvent; import com.google.gwt.event.dom.client.TouchEvent; import com.google.gwt.event.dom.client.TouchMoveEvent; import com.google.gwt.event.dom.client.TouchStartEvent; /** * Base implementation of AbstractEvent. * * @author Thomas Krismayer * */ public class PointerEvent extends AbstractEvent { private Element relativeElement; private GPoint point = new GPoint(0, 0); private PointerEventType type; private HasOffsets off; private boolean shift, control, alt, meta, right, middle; private int clickCount = 1; private int evID; private HumanInputEvent<?> nativeEvent; private final boolean relative; public PointerEvent(double x, double y, PointerEventType type, HasOffsets off, boolean isRelative) { this.off = off; this.point = new GPoint((int) Math.round(x), (int) Math.round(y)); this.type = type; this.evID = off.getEvID(); this.relative = isRelative; } public PointerEvent(double x, double y, PointerEventType type, HasOffsets off) { this(x, y, type, off, type == PointerEventType.MOUSE); } @Override public int getClickCount() { return this.clickCount; } @Override public GPoint getPoint() { return new GPoint(getX(), getY()); } @Override public int getX() { if (relative) { return off.mouseEventX(this.point.x); } return off.touchEventX(this.point.x); } @Override public int getY() { if (relative) { return off.mouseEventY(this.point.y); } return off.touchEventY(this.point.y); } @Override public boolean isAltDown() { return this.alt; } @Override public boolean isControlDown() { return this.control; } @Override public boolean isMetaDown() { return this.meta; } @Override public boolean isMiddleClick() { return this.middle; } @Override public boolean isPopupTrigger() { return false; } @Override public boolean isRightClick() { return this.right; } /** * set is (or isn't) right click * * @param flag * value */ public void setIsRightClick(boolean flag) { this.right = flag; } @Override public boolean isShiftDown() { return this.shift; } @Override public void release() { if (this.type == PointerEventType.TOUCH) { this.off.getTouchEventPool().add(this); } } @Override public PointerEventType getType() { return this.type; } private static PointerEvent wrapEvent(int x, int y, PointerEventType type, HasOffsets h, LinkedList<PointerEvent> pool) { if (!pool.isEmpty()) { PointerEvent wrap = pool.getLast(); wrap.point = new GPoint(x, y); wrap.type = type; wrap.evID = h.getEvID(); pool.removeLast(); return wrap; } return new PointerEvent(x, y, type, h); } private static void setProperties(PointerEvent destination, MouseEvent<?> source) { destination.nativeEvent = source; destination.alt = source.isAltKeyDown(); destination.control = source.isControlKeyDown(); destination.clickCount = "dblclick".equals(source.getNativeEvent() .getType()) ? 2 : 1; destination.meta = source.isMetaKeyDown(); destination.middle = source.getNativeButton() == NativeEvent.BUTTON_MIDDLE; destination.right = source.getNativeButton() == NativeEvent.BUTTON_RIGHT; destination.shift = source.isShiftKeyDown(); destination.relativeElement = source.getRelativeElement(); } /** * Wraps the event taking the relative coordinates of the event. * * @param event * event to wrap * @param off * offsets * @return wrapped event */ public static PointerEvent wrapEvent(MouseEvent<?> event, HasOffsets off) { PointerEvent evt = wrapEvent(event.getX(), event.getY(), off.getDefaultEventType(), off, off.getMouseEventPool()); setProperties(evt, event); return evt; } /** * Wraps the event taking the absolute coordinates of the event. * * @param event * event to wrap * @param off * offsets * @return wrapped event */ public static PointerEvent wrapEventAbsolute(MouseEvent<?> event, HasOffsets off) { int clientX = event.getClientX(); int clientY = event.getClientY(); PointerEvent evt = wrapEvent(clientX, clientY, off.getDefaultEventType(), off, off.getMouseEventPool()); setProperties(evt, event); return evt; } /** * Creates a wrapped event, based on the touch coordinates, with a relative * element. * * @param touch * touch * @param off * offsets * @param relativeElement * event relative to element * @return wrapped event */ public static PointerEvent wrapEvent(Touch touch, HasOffsets off, Element relativeElement) { PointerEvent event = wrapEvent(touch, off); event.relativeElement = relativeElement; return event; } /** * Creates a wrapped event, based on the touch coordinates. * * @param touch * touch * @param off * offsets * @return wrapped event */ public static PointerEvent wrapEvent(Touch touch, HasOffsets off) { return wrapEvent(touch.getClientX(), touch.getClientY(), PointerEventType.TOUCH, off, off.getTouchEventPool()); } /** * Wraps a single touch event. * * @param event * @param off * @return */ public static PointerEvent wrapEvent(TouchEvent<?> event, HasOffsets off) { JsArray<Touch> touches = null; int index = 0; if (event instanceof TouchStartEvent) { touches = event.getTargetTouches(); } else if (event instanceof TouchMoveEvent) { touches = event.getTargetTouches(); index = touches.length() - 1; } else { // assume if (event instanceof TouchEndEvent) { touches = event.getChangedTouches(); } PointerEvent e = wrapEvent(touches.get(index), off); e.nativeEvent = event; return e; } /** * @return The euclidian view id if the event was fired on it, else 0. */ public int getEvID() { return this.evID; } /** * This field is only set when the event was created with * {@link PointerEvent#wrapEvent(Touch, HasOffsets, Element)}. * * @return the event relative to the element */ public Element getRelativeElement() { return relativeElement; } /** * Returns the event that was wrapped. * * @return native event */ public HumanInputEvent<?> getWrappedEvent() { return nativeEvent; } public void setControl(boolean b) { this.control = b; } public void setShift(boolean b) { this.shift = b; } public void setAlt(boolean b) { this.alt = b; } }