package org.cruxframework.crux.smartfaces.client.slider; import java.util.Date; import org.cruxframework.crux.core.client.css.transition.Transition; import org.cruxframework.crux.core.client.event.SelectEvent; import org.cruxframework.crux.smartfaces.client.slider.Slider.SliderEventHandlers; import com.google.gwt.event.dom.client.TouchEndEvent; import com.google.gwt.event.dom.client.TouchEndHandler; import com.google.gwt.event.dom.client.TouchMoveEvent; import com.google.gwt.event.dom.client.TouchMoveHandler; import com.google.gwt.event.dom.client.TouchStartEvent; import com.google.gwt.event.dom.client.TouchStartHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.Widget; /** * * @author Thiago da Rosa de Bustamante * */ class TouchSliderEventHandlers extends SliderEventHandlers implements TouchStartHandler, TouchMoveHandler, TouchEndHandler { private static final int SWIPE_THRESHOLD = 50; private static final long SWIPE_TIME_THRESHOLD = 250; private static final int TAP_EVENT_THRESHOLD = 5; private int currentTouchPosition; private boolean didMove; private int startTouchPosition; private long startTouchTime; private HandlerRegistration touchEndHandler; private HandlerRegistration touchMoveHandler; @Override public void onTouchEnd(TouchEndEvent event) { if (slider.sliding) { return; } if (currentTouchPosition != startTouchPosition) { final int slideBy = getSlideBy(); slider.slide(slideBy, false); } else { SlideEndEvent.fire(slider); } if (!didMove) { SelectEvent.fire(slider); } if(touchMoveHandler != null) { touchMoveHandler.removeHandler(); } if(touchEndHandler != null) { touchEndHandler.removeHandler(); } } @Override public void onTouchMove(TouchMoveEvent event) { if (slider.sliding) { return; } int clientX = event.getTouches().get(0).getClientX(); int diff = clientX - startTouchPosition; boolean hasNextPanel = slider.hasNextWidget(); boolean hasPreviousPanel = slider.hasPreviousWidget(); if ((diff < 0 && hasNextPanel) || (diff > 0 && hasPreviousPanel)) { currentTouchPosition = clientX; Transition.translateX(slider.getCurrentPanel(), diff, null); if (hasPreviousPanel) { Widget previousPanel = slider.getPreviousPanel(); Transition.translateX(previousPanel, diff-previousPanel.getOffsetWidth(), null); } if (hasNextPanel) { Widget nextPanel = slider.getNextPanel(); Transition.translateX(nextPanel, diff+nextPanel.getOffsetWidth(), null); } } if (!didMove && (Math.abs(diff) > TAP_EVENT_THRESHOLD)) { didMove = true; } } @Override public void onTouchStart(TouchStartEvent event) { didMove = false; SlideStartEvent.fire(slider); startTouchPosition = event.getTouches().get(0).getClientX(); currentTouchPosition = startTouchPosition; startTouchTime = new Date().getTime(); touchMoveHandler = slider.touchPanel.addTouchMoveHandler(this); touchEndHandler = slider.touchPanel.addTouchEndHandler(this); } @Override protected void handleSliderEvents() { slider.touchPanel.addTouchStartHandler(this); super.handleSliderEvents(); } /** * return the final width used to slide the panels. * @param hasPreviousPanel * @param hasNextPanel * @return negative width means "go to next", positive "go to previous" and zero "keep on current" */ private int getSlideBy() { int slideBy; int distX = currentTouchPosition - startTouchPosition; int width = slider.contentPanel.getElement().getOffsetWidth(); if (isSwapEvent(distX)) { slideBy = distX > 0?width:-width; } else { if (Math.abs(distX) > width / 2) { slideBy = (distX > 0) ? width : width * -1; } else { slideBy = 0; } } if ((slideBy > 0 && !slider.hasPreviousWidget()) || (slideBy < 0 && !slider.hasNextWidget())) { slideBy = 0; } return slideBy; } private boolean isSwapEvent(int distX) { long endTime = new Date().getTime(); long diffTime = endTime - this.startTouchTime; if (diffTime <= SWIPE_TIME_THRESHOLD) { if (Math.abs(distX) >= SWIPE_THRESHOLD) { return true; } } return false; } }