Search code examples
gwttouchtablet

Converting GWT Click Events to Touch Events


I am working on a Big Project and i have a lot of GWT code written. Now i am working on making the project fully compatible with Tablets like iPad and Android Tablets.

As a part of this, i have noticed that touch devices takes 300ms delay to handle click events. In this project, writing touch events again is a very tedious task. I have done a lot of researches in this and found the Google Fast Buttons API used in Google Voice Application. I tried that and its working good but requires a lot of coding and JSNI.

My question is, Is there anything else available in your knowledge to easily overcome this delay?


Solution

  • Here is a pure java implementation of the fast button.It doesn't include a single line of JNSI

    package com.apollo.tabletization.shared.util;
    
    import java.util.Date;
    
    import com.google.gwt.dom.client.Document;
    import com.google.gwt.dom.client.NativeEvent;
    import com.google.gwt.dom.client.Touch;
    import com.google.gwt.event.dom.client.HasAllTouchHandlers;
    import com.google.gwt.event.dom.client.HasClickHandlers;
    import com.google.gwt.user.client.DOM;
    import com.google.gwt.user.client.Event;
    import com.google.gwt.user.client.Window;
    import com.google.gwt.user.client.ui.Composite;
    import com.google.gwt.user.client.ui.Widget;
    
    /** Implementation of Google FastButton {@link http://code.google.com/mobile/articles/fast_buttons.html} */
    public class FastButton extends Composite {
    
      private boolean touchHandled = false;
      private boolean clickHandled = false;
      private boolean touchMoved = false;
      private int startY;
      private int startX;
      private int timeStart;
    
      public FastButton(Widget child) {
        // TODO - messages
        assert (child instanceof HasAllTouchHandlers) : "";
          assert (child instanceof HasClickHandlers) : "";
            initWidget(child);
            sinkEvents(Event.TOUCHEVENTS | Event.ONCLICK);
      }
    
      @Override
      public Widget getWidget() {
        return super.getWidget();
      }
    
      @Override
      public void onBrowserEvent(Event event) {
        timeStart = getUnixTimeStamp();
        switch (DOM.eventGetType(event)) {
          case Event.ONTOUCHSTART:
            {
              onTouchStart(event);
              break;
            }
          case Event.ONTOUCHEND:
            {
              onTouchEnd(event);
              break;
            }
          case Event.ONTOUCHMOVE:
            {
              onTouchMove(event);
              break;
            }
          case Event.ONCLICK:
            {
              onClick(event);
              return;
            }
        }
    
        super.onBrowserEvent(event);
      }
    
      private void onClick(Event event) {
        event.stopPropagation();
    
        int timeEnd = getUnixTimeStamp();
        if(touchHandled) {
          //Window.alert("click via touch: "+ this.toString() + "..." +timeStart+"---"+timeEnd);
          touchHandled = false;
          clickHandled = true;
          super.onBrowserEvent(event);
        }
        else {  
          if(clickHandled) {
    
            event.preventDefault();
          }
          else {
            clickHandled = false;
            //Window.alert("click nativo: "+ this.toString()+ "..." +(timeStart-timeEnd)+"==="+timeStart+"---"+timeEnd);
            super.onBrowserEvent(event);
          }
        }
      }
    
      private void onTouchEnd(Event event)  {
        if (!touchMoved) {
          touchHandled = true;
          fireClick();
        }
      }
    
      private void onTouchMove(Event event)  {
        if (!touchMoved) {
          Touch touch = event.getTouches().get(0);
          int deltaX = Math.abs(startX - touch.getClientX()); 
          int deltaY = Math.abs(startY - touch.getClientY());
    
          if (deltaX > 5 || deltaY > 5) {
            touchMoved = true;
          }
        }
      }
    
      private void onTouchStart(Event event) {
        Touch touch = event.getTouches().get(0);
        this.startX = touch.getClientX();
        this.startY = touch.getClientY();               
        touchMoved = false;
      }
    
      private void fireClick() {
        NativeEvent evt = Document.get().createClickEvent(1, 0, 0, 0, 0, false,
            false, false, false);
        getElement().dispatchEvent(evt);
      }
    
      private int getUnixTimeStamp() {
        Date date = new Date();
        int iTimeStamp = (int) (date.getTime() * .001);
        return iTimeStamp;
      }
    }