/*\r
* Copyright 2011, The gwtquery team.\r
* \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
+ * in compliance with the License. You may obtain a copy of the License at\r
* \r
* http://www.apache.org/licenses/LICENSE-2.0\r
* \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License\r
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
+ * or implied. See the License for the specific language governing permissions and limitations under\r
* the License.\r
*/\r
package com.google.gwt.query.client.plugins;\r
import com.google.gwt.query.client.GQuery;\r
import com.google.gwt.query.client.plugins.events.GqEvent;\r
import com.google.gwt.user.client.Event;\r
+import com.google.gwt.user.client.ui.Label;\r
+import com.google.gwt.user.client.ui.RootPanel;\r
\r
/**\r
* Base class for all plug-in that need to handle some mouse interactions.\r
*/\r
public abstract class MousePlugin extends UiPlugin {\r
\r
- private GqEvent mouseDownEvent;\r
- private boolean mouseStarted = false;\r
+ private GqEvent startEvent;\r
+ private boolean started = false;\r
private Duration mouseUpDuration;\r
private MouseOptions options;\r
private boolean preventClickEvent = false;\r
+ private boolean touchSupported = false;\r
\r
protected MousePlugin(GQuery gq) {\r
super(gq);\r
\r
protected void destroyMouseHandler() {\r
as(Events)\r
- .unbind(Event.ONMOUSEDOWN | Event.ONCLICK, getPluginName(), null);\r
+ .unbind(Event.ONMOUSEDOWN | Event.ONCLICK | Event.ONTOUCHSTART, getPluginName(), null);\r
}\r
\r
/**\r
- * Return a String identifying the plugin. This string is used as namespace\r
- * when we bind handlers.\r
+ * Return a String identifying the plugin. This string is used as namespace when we bind handlers.\r
* \r
*/\r
protected abstract String getPluginName();\r
\r
for (final Element e : elements()) {\r
\r
- $(e).as(Events).bind(Event.ONMOUSEDOWN, getPluginName(),\r
- (Object) null, new Function() {\r
- @Override\r
- public boolean f(com.google.gwt.user.client.Event event) {\r
- return mouseDown(e, GqEvent.create(event));\r
+ $(e).as(Events).bind(Event.ONMOUSEDOWN, getPluginName(), (Object) null, new Function() {\r
+ @Override\r
+ public boolean f(com.google.gwt.user.client.Event event) {\r
+ if (touchSupported) {\r
+ return true;\r
+ }\r
+ return mouseDown(e, GqEvent.create(event));\r
\r
- }\r
- }).bind(Event.ONCLICK, getPluginName(), (Object) null,\r
- new Function() {\r
- @Override\r
- public boolean f(com.google.gwt.user.client.Event event) {\r
- preventClickEvent |= !mouseClick(e, GqEvent.create(event));\r
+ }\r
+ }).bind(Event.ONTOUCHSTART, getPluginName(), (Object) null, new Function() {\r
+ public boolean f(com.google.gwt.user.client.Event event) {\r
+ if (event.getTouches().length() > 1) {\r
+ return true;\r
+ }\r
\r
- if (preventClickEvent) {\r
+ touchSupported = true;\r
+ return mouseDown(e, GqEvent.create(event));\r
\r
- preventClickEvent = false;\r
- event.stopPropagation();\r
- event.preventDefault();\r
- return false;\r
- }\r
+ }\r
+ }).bind(Event.ONCLICK, getPluginName(), (Object) null, new Function() {\r
+ @Override\r
+ public boolean f(com.google.gwt.user.client.Event event) {\r
+ if (touchSupported) {\r
+ return true;\r
+ }\r
\r
- return true;\r
- }\r
- });\r
+ preventClickEvent |= !mouseClick(e, GqEvent.create(event));\r
+\r
+ if (preventClickEvent) {\r
+\r
+ preventClickEvent = false;\r
+ event.stopPropagation();\r
+ event.preventDefault();\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+ });\r
}\r
\r
}\r
/**\r
* Method called when mouse down occur on the element.\r
* \r
- * You should not override this method. Instead, override\r
- * {@link #mouseStart(Element, GqEvent)} method\r
+ * You should not override this method. Instead, override {@link #mouseStart(Element, GqEvent)}\r
+ * method\r
* \r
*/\r
protected boolean mouseDown(Element element, GqEvent event) {\r
if (isEventAlreadyHandled(event)) {\r
return false;\r
}\r
- if (mouseStarted) { // case where we missed a mouseup\r
+\r
+ if (started) { // case where we missed a mouseup\r
mouseUp(element, event);\r
}\r
\r
}\r
\r
if (delayConditionMet() && distanceConditionMet(event)) {\r
- mouseStarted = mouseStart(element, event);\r
- if (!mouseStarted) {\r
+ started = mouseStart(element, event);\r
+ if (!started) {\r
event.getOriginalEvent().preventDefault();\r
return true;\r
}\r
}\r
\r
- bindOtherMouseEvent(element);\r
+ bindOtherEvents(element);\r
\r
event.getOriginalEvent().preventDefault();\r
\r
/**\r
* Method called on MouseMove event.\r
* \r
- * You should not override this method. Instead, override\r
- * {@link #mouseMove(Element, GqEvent)} method\r
+ * You should not override this method. Instead, override {@link #mouseMove(Element, GqEvent)}\r
+ * method\r
* \r
*/\r
protected boolean mouseMove(Element element, GqEvent event) {\r
- if (mouseStarted) {\r
+ if (started) {\r
event.getOriginalEvent().preventDefault();\r
return mouseDrag(element, event);\r
}\r
\r
if (delayConditionMet() && distanceConditionMet(event)) {\r
- mouseStarted = mouseStart(element, mouseDownEvent);\r
- if (mouseStarted) {\r
+ started = mouseStart(element, startEvent);\r
+ if (started) {\r
mouseDrag(element, event);\r
} else {\r
mouseUp(element, event);\r
}\r
}\r
\r
- return !mouseStarted;\r
+ return !started;\r
}\r
\r
/**\r
- * Method called when the mouse is clicked and all conditions for starting the\r
- * plugin are met.\r
+ * Method called when the mouse is clicked and all conditions for starting the plugin are met.\r
* \r
*/\r
protected abstract boolean mouseStart(Element element, GqEvent event);\r
/**\r
* Method called when mouse is released..\r
* \r
- * You should not override this method. Instead, override\r
- * {@link #mouseStop(Element, GqEvent)} method\r
+ * You should not override this method. Instead, override {@link #mouseStop(Element, GqEvent)}\r
+ * method\r
* \r
*/\r
protected boolean mouseUp(Element element, GqEvent event) {\r
- unbindOtherMouseEvent();\r
- if (mouseStarted) {\r
- mouseStarted = false;\r
- preventClickEvent = (event.getCurrentEventTarget() == mouseDownEvent\r
- .getCurrentEventTarget());\r
+ unbindOtherEvents();\r
+ if (started) {\r
+ started = false;\r
+ preventClickEvent = (event.getCurrentEventTarget() == startEvent.getCurrentEventTarget());\r
mouseStop(element, event);\r
}\r
return false;\r
\r
}\r
\r
- private void bindOtherMouseEvent(final Element element) {\r
+ private void bindOtherEvents(final Element element) {\r
+\r
+ int moveEvent = touchSupported ? Event.ONTOUCHMOVE : Event.ONMOUSEMOVE;\r
+\r
+ int endEvents = touchSupported ? Event.ONTOUCHEND : Event.ONMOUSEUP;\r
+\r
+ $(document).as(Events).bind(moveEvent, getPluginName(), (Object) null, new Function() {\r
+ @Override\r
+ public boolean f(com.google.gwt.user.client.Event e) {\r
+ mouseMove(element, (GqEvent) GqEvent.create(e));\r
+ return false;\r
+ }\r
+ }).bind(endEvents, getPluginName(), (Object) null, new Function() {\r
+ @Override\r
+ public boolean f(com.google.gwt.user.client.Event e) {\r
+ mouseUp(element, (GqEvent) GqEvent.create(e));\r
+ return false;\r
+ }\r
+ });\r
+\r
+ // TODO Event.ONTOUCHEND | Event.ONTOUCHCANCEL don't work -> investigate\r
+ if (touchSupported) {\r
+ $(document).as(Events).bind(Event.ONTOUCHCANCEL, getPluginName(), (Object) null,\r
+ new Function() {\r
+ @Override\r
+ public boolean f(com.google.gwt.user.client.Event e) {\r
+ mouseUp(element, (GqEvent) GqEvent.create(e));\r
+ return false;\r
+ }\r
+ });\r
+\r
+ }\r
\r
- $(document).as(Events).bind(Event.ONMOUSEMOVE, getPluginName(),\r
- (Object) null, new Function() {\r
- @Override\r
- public boolean f(com.google.gwt.user.client.Event e) {\r
- mouseMove(element, (GqEvent) GqEvent.create(e));\r
- return false;\r
- }\r
- }).bind(Event.ONMOUSEUP, getPluginName(), (Object) null,\r
- new Function() {\r
- @Override\r
- public boolean f(com.google.gwt.user.client.Event e) {\r
- mouseUp(element, (GqEvent) GqEvent.create(e));\r
- return false;\r
- }\r
- });\r
}\r
\r
private boolean delayConditionMet() {\r
\r
private boolean distanceConditionMet(GqEvent event) {\r
int neededDistance = options.getDistance();\r
- int mouseDownX = mouseDownEvent.getClientX();\r
- int mouseDownY = mouseDownEvent.getClientY();\r
- int xMouseDistance = Math.abs(mouseDownX - event.getClientX());\r
- int yMouseDistance = Math.abs(mouseDownY - event.getClientY());\r
+ int startX = getClientX(startEvent);\r
+ int startY = getClientY(startEvent);\r
+ int xDistance = Math.abs(startX - getClientX(event));\r
+ int yDistance = Math.abs(startY - getClientY(event));\r
// in jQuery-ui we take the greater distance between x and y... not really\r
// good !\r
// int mouseDistance = Math.max(xMouseDistance, yMouseDistance);\r
// use Pythagor theorem !!\r
- int mouseDistance = (int) Math.sqrt(xMouseDistance * xMouseDistance\r
- + yMouseDistance * yMouseDistance);\r
+ int mouseDistance = (int) Math.sqrt(xDistance * xDistance + yDistance * yDistance);\r
return mouseDistance >= neededDistance;\r
}\r
\r
private native boolean isEventAlreadyHandled(GqEvent event)/*-{\r
- var result = event.mouseHandled ? event.mouseHandled : false;\r
- return result;\r
+ var result = event.mouseHandled ? event.mouseHandled : false;\r
+ return result;\r
}-*/;\r
\r
private native void markEventAsHandled(GqEvent event)/*-{\r
- event.mouseHandled = true;\r
+ event.mouseHandled = true;\r
}-*/;\r
\r
private boolean notHandleMouseDown(Element element, GqEvent mouseDownEvent) {\r
\r
boolean isElementCancel = false;\r
if (options.getCancel() != null) {\r
- isElementCancel = $(eventTarget).parents().add($(eventTarget)).filter(\r
- options.getCancel()).length() > 0;\r
+ isElementCancel =\r
+ $(eventTarget).parents().add($(eventTarget)).filter(options.getCancel()).length() > 0;\r
}\r
\r
- return isNotBoutonLeft || isElementCancel\r
- || !mouseCapture(element, mouseDownEvent);\r
+ return isNotBoutonLeft || isElementCancel || !mouseCapture(element, mouseDownEvent);\r
\r
}\r
\r
- private void reset(GqEvent mouseDownEvent) {\r
- this.mouseDownEvent = mouseDownEvent;\r
+ private void reset(GqEvent nativeEvent) {\r
+ this.startEvent = nativeEvent;\r
this.mouseUpDuration = new Duration();\r
}\r
\r
- private void unbindOtherMouseEvent() {\r
- $(document).as(Events).unbind((Event.ONMOUSEUP | Event.ONMOUSEMOVE),\r
- getPluginName(), null);\r
+ private void unbindOtherEvents() {\r
+ int events =\r
+ touchSupported ? Event.ONTOUCHCANCEL | Event.ONTOUCHEND | Event.ONTOUCHMOVE\r
+ : Event.ONMOUSEUP | Event.ONMOUSEMOVE;\r
+\r
+ $(document).as(Events).unbind(events, getPluginName(), null);\r
+\r
+ RootPanel.get().add(new Label("events : " + events + " unbind"));\r
+ }\r
+\r
+ protected int getClientX(Event e) {\r
+ if (touchSupported) {\r
+ return e.getTouches().get(0).getClientX();\r
+ } else {\r
+ return e.getClientX();\r
+ }\r
+ }\r
+\r
+ protected int getClientY(Event e) {\r
+ if (touchSupported) {\r
+ return e.getTouches().get(0).getClientY();\r
+ } else {\r
+ return e.getClientY();\r
+ }\r
}\r
\r
}\r