]> source.dussan.org Git - gwtquery.git/commitdiff
support of touch events in Mouse plugin
authorJulien Dramaix <julien.dramaix@gmail.com>
Sun, 22 Apr 2012 12:19:37 +0000 (12:19 +0000)
committerJulien Dramaix <julien.dramaix@gmail.com>
Sun, 22 Apr 2012 12:19:37 +0000 (12:19 +0000)
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/MousePlugin.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java

index f5573fbabc4c1a5e7f79468de4dd6e9267751451..1e58a691221efdd00a7175ad0d9904c77434c556 100755 (executable)
@@ -1,16 +1,14 @@
 /*\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
@@ -22,6 +20,8 @@ import com.google.gwt.query.client.Function;
 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
@@ -29,11 +29,12 @@ import com.google.gwt.user.client.Event;
  */\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
@@ -41,12 +42,11 @@ public abstract class MousePlugin extends UiPlugin {
 \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
@@ -60,30 +60,45 @@ public abstract class MousePlugin extends UiPlugin {
 \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
@@ -107,8 +122,8 @@ public abstract class MousePlugin extends UiPlugin {
   /**\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
@@ -117,7 +132,8 @@ public abstract class MousePlugin extends UiPlugin {
     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
@@ -129,14 +145,14 @@ public abstract class MousePlugin extends UiPlugin {
     }\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
@@ -154,31 +170,30 @@ public abstract class MousePlugin extends UiPlugin {
   /**\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
@@ -192,39 +207,54 @@ public abstract class MousePlugin extends UiPlugin {
   /**\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
@@ -238,26 +268,25 @@ public abstract class MousePlugin extends UiPlugin {
 \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
@@ -266,23 +295,43 @@ public abstract class MousePlugin extends UiPlugin {
 \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
index 596578f5046028933a97671ce3d5755886aa7755..cb1a69d75cce8a645963e0d9cc81c3303c242ee2 100644 (file)
@@ -43,6 +43,7 @@ public class GqEvent extends Event {
                }
                gQueryEvent.originalEvent = originalEvent;
   }-*/;
 
   protected GqEvent() {
   }
@@ -76,7 +77,11 @@ public class GqEvent extends Event {
    * 
    */
   public final int pageX() {
-    return getClientX() + GQuery.document.getScrollLeft();
+    if (getTouches() != null && getTouches().length() > 0){
+      return getTouches().get(0).getPageX();
+    }else{
+      return getClientX() + GQuery.document.getScrollLeft();
+    }
   }
 
   /**
@@ -84,7 +89,11 @@ public class GqEvent extends Event {
    * 
    */
   public final int pageY() {
-    return getClientY() + GQuery.document.getScrollTop();
+    if (getTouches() != null &&  getTouches().length() > 0){
+      return getTouches().get(0).getPageY();
+    }else{
+      return getClientY() + GQuery.document.getScrollTop();
+    }
   }
 
 }