/* * Copyright 2014 cruxframework.org. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.cruxframework.crux.core.client.select; import org.cruxframework.crux.core.client.event.SelectEndEvent; import org.cruxframework.crux.core.client.event.SelectStartEvent; import org.cruxframework.crux.core.client.event.TouchEventsHandler; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Touch; 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.logical.shared.AttachEvent; import com.google.gwt.event.logical.shared.AttachEvent.Handler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.Widget; /** * SelectEventsHanler Implementation for touch devices * @author Thiago da Rosa de Bustamante * @author Samuel Almeida Cardoso (samuel@cruxframework.org) * */ public class SelectEventsHandlerTouchImpl extends SelectEventsHandler implements TouchStartHandler, TouchMoveHandler, TouchEndHandler { private int tapEventThreshold = 5; private int startX; private int startY; private HandlerRegistration touchMoveHandler; private HandlerRegistration touchEndHandler; private boolean childOfSelectableWidget = false; public void handleWidget() { selectableWidget.addTouchStartHandler(this); selectableWidget.addAttachHandler(new Handler() { @Override public void onAttachOrDetach(AttachEvent event) { childOfSelectableWidget = false; if (event.isAttached()) { Widget parent = selectableWidget.getParent(); while (parent != null) { if (parent instanceof TouchEventsHandler) { childOfSelectableWidget = true; break; } parent = parent.getParent(); } } } }); } @Override public void onTouchEnd(TouchEndEvent event) { if(!allowPropagationToNonSelectableWidgets && !childOfSelectableWidget) { event.stopPropagation(); } else if (stopPropagationTouchEvents) { event.stopPropagation(); } if (preventDefaultTouchEvents) { event.preventDefault(); } if (isEnabled()) { //TODO: check this! Giving some time to onTouchEnd finalize. //If we don't do it, focus events that runs inside any selectHandler //will be overridden by (some crazy?) focus events onTouchEnd. Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { SelectEndEvent.fire(selectableWidget); selectableWidget.select(); } }); } resetHandlers(); } @Override public void onTouchMove(TouchMoveEvent event) { Touch touch = event.getTouches().get(0); if (Math.abs(touch.getClientX() - this.startX) > this.tapEventThreshold || Math.abs (touch.getClientY() - this.startY) > this.tapEventThreshold) { this.resetHandlers(); } } @Override public void onTouchStart(TouchStartEvent event) { if (stopPropagationTouchEvents) { event.stopPropagation(); } if (preventDefaultTouchEvents) { event.preventDefault(); } Touch touch = event.getTouches().get(0); startX = touch.getClientX(); startY = touch.getClientY(); touchMoveHandler = selectableWidget.addTouchMoveHandler(this); touchEndHandler = selectableWidget.addTouchEndHandler(this); SelectStartEvent.fire(selectableWidget); } private void resetHandlers() { if(touchMoveHandler != null) { touchMoveHandler.removeHandler(); touchMoveHandler = null; } if(touchEndHandler != null) { touchEndHandler.removeHandler(); touchEndHandler = null; } } @Override public void setTapEventThreshold(int tapEventThreshold) { this.tapEventThreshold = tapEventThreshold; } }