package org.vaadin.touchkit.gwt.client.ui; import java.util.Date; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.SpanElement; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.TouchCancelEvent; import com.google.gwt.event.dom.client.TouchCancelHandler; 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.user.client.Window.Navigator; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ui.Icon; public class VNavigationButton extends HTML implements TouchStartHandler, TouchCancelHandler, TouchEndHandler, TouchMoveHandler, ClickHandler { private static final String NAVBUTTON_CLASSNAME = "v-touchkit-navbutton"; private String caption; private Icon icon; private SpanElement descriptionElement; private boolean enabled; static final long IGNORE_SIMULATED_CLICKS_THRESHOLD = 1500; private boolean touchStarted = false; private Date fastClickAt; // TODO check if WP could support fast clicks as well. Now seem to get // duplicate events every now and then public static boolean useFastClicks = !Navigator.getUserAgent() .toLowerCase().contains("android 2"); public VNavigationButton() { setStyleName(NAVBUTTON_CLASSNAME); if (VNavigationButton.useFastClicks) { addTouchStartHandler(this); addTouchCancelHandler(this); addTouchEndHandler(this); addTouchMoveHandler(this); } addClickHandler(this); } public VNavigationManager findNavigationPanel() { Widget parent2 = getParent(); while (parent2 != null && !(parent2 instanceof VNavigationManager)) { parent2 = parent2.getParent(); } return (VNavigationManager) parent2; } @Override public void setText(String text) { caption = text; super.setText(text); } public String getCaption() { return caption; } public void setIcon(Icon newIcon) { if (newIcon == null) { if (icon != null) { getElement().removeChild(icon.getElement()); } } else if (icon != null // icon might have been removed by a call to #setText (#14536) && getElement().isOrHasChild(icon.getElement())) { getElement().replaceChild(icon.getElement(), newIcon.getElement()); } else { getElement().insertFirst(newIcon.getElement()); } icon = newIcon; } public void setDescription(String description) { if (description != null && !description.trim().isEmpty()) { if (descriptionElement == null) { descriptionElement = Document.get().createSpanElement(); descriptionElement.setClassName(NAVBUTTON_CLASSNAME + "-desc"); } /* * Add the descriptionElement if it's not already added as it might * have been overwritten by a call to #setText */ if (!getElement().isOrHasChild(descriptionElement)) { getElement().insertFirst(descriptionElement); } descriptionElement.setInnerHTML(description); } else if (descriptionElement != null) { descriptionElement.removeFromParent(); descriptionElement = null; } } @Override public void onTouchMove(TouchMoveEvent event) { touchStarted = false; } @Override public void onTouchEnd(TouchEndEvent event) { if (touchStarted) { event.preventDefault(); event.stopPropagation(); NativeEvent nativeEvent = event.getNativeEvent(); NativeEvent evt = Document.get().createClickEvent(1, nativeEvent.getScreenX(), nativeEvent.getScreenY(), nativeEvent.getClientX(), nativeEvent.getClientY(), false, false, false, false); getElement().dispatchEvent(evt); touchStarted = false; fastClickAt = new Date(); } } @Override public void onTouchCancel(TouchCancelEvent event) { touchStarted = false; } @Override public void onTouchStart(TouchStartEvent event) { touchStarted = true; fastClickAt = null; getElement().focus(); } @Override public void onClick(ClickEvent event) { if (enabled) { if (fastClickAt != null && (new Date().getTime() - fastClickAt.getTime()) < IGNORE_SIMULATED_CLICKS_THRESHOLD) { // VConsole.log("Ignored simulated event fired by old ios or android " // + (new Date().getTime() - fastClickAt.getTime())); fastClickAt = null; return; } getElement().focus(); } } public void setEnabled(boolean enabled) { this.enabled = enabled; } public boolean isEnabled() { return enabled; } }