Browse Source

Displaying tooltip in slot for touch devices (#15353)

Change-Id: Ia2fce4dbfc205b44622557017afff19c4a2ef7df
tags/7.5.0.alpha1
Alexey Fansky 9 years ago
parent
commit
05fc5806e7

+ 23
- 13
client/src/com/vaadin/client/VTooltip.java View File

import com.google.gwt.aria.client.Roles; import com.google.gwt.aria.client.Roles;
import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Timer;
} }


private class TooltipEventHandler implements MouseMoveHandler, private class TooltipEventHandler implements MouseMoveHandler,
KeyDownHandler, FocusHandler, BlurHandler, MouseDownHandler {
KeyDownHandler, FocusHandler, BlurHandler, MouseDownHandler,
MouseUpHandler, TouchStartHandler {


/** /**
* Current element hovered * Current element hovered
*/ */
private boolean handledByFocus; private boolean handledByFocus;


/**
* Indicates whether the tooltip is being called after a touch event.
*/
private boolean touchInitiated = false;

/** /**
* Locate the tooltip for given element * Locate the tooltip for given element
* *


@Override @Override
public void onMouseMove(MouseMoveEvent mme) { public void onMouseMove(MouseMoveEvent mme) {
handleShowHide(mme, false);
if (!touchInitiated) {
handleShowHide(mme, false);
}
}

@Override
public void onMouseUp(MouseUpEvent event) {
touchInitiated = false;
}

@Override
public void onTouchStart(TouchStartEvent te) {
touchInitiated = true;
} }


@Override @Override
Profiler.enter("VTooltip.connectHandlersToWidget"); Profiler.enter("VTooltip.connectHandlersToWidget");
widget.addDomHandler(tooltipEventHandler, MouseMoveEvent.getType()); widget.addDomHandler(tooltipEventHandler, MouseMoveEvent.getType());
widget.addDomHandler(tooltipEventHandler, MouseDownEvent.getType()); widget.addDomHandler(tooltipEventHandler, MouseDownEvent.getType());
widget.addDomHandler(tooltipEventHandler, MouseUpEvent.getType());
widget.addDomHandler(tooltipEventHandler, KeyDownEvent.getType()); widget.addDomHandler(tooltipEventHandler, KeyDownEvent.getType());
widget.addDomHandler(tooltipEventHandler, FocusEvent.getType()); widget.addDomHandler(tooltipEventHandler, FocusEvent.getType());
widget.addDomHandler(tooltipEventHandler, BlurEvent.getType()); widget.addDomHandler(tooltipEventHandler, BlurEvent.getType());
widget.addDomHandler(tooltipEventHandler, TouchStartEvent.getType());
Profiler.leave("VTooltip.connectHandlersToWidget"); Profiler.leave("VTooltip.connectHandlersToWidget");
} }



+ 102
- 6
client/src/com/vaadin/client/ui/orderedlayout/Slot.java View File

import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.BrowserInfo; import com.vaadin.client.BrowserInfo;
public final class Slot extends SimplePanel { public final class Slot extends SimplePanel {


private static final String ALIGN_CLASS_PREFIX = "v-align-"; private static final String ALIGN_CLASS_PREFIX = "v-align-";
private static final int TOUCH_ERROR_MESSAGE_HIDE_DELAY = 200;


private final VAbstractOrderedLayout layout; private final VAbstractOrderedLayout layout;


private Element captionText; private Element captionText;
private Icon icon; private Icon icon;
private Element errorIcon; private Element errorIcon;
private Element errorMessage;
private Element requiredIcon; private Element requiredIcon;


private HandlerRegistration focusRegistration;
private HandlerRegistration blurRegistration;
private boolean labelClicked = false;

private ElementResizeListener captionResizeListener; private ElementResizeListener captionResizeListener;


private ElementResizeListener widgetResizeListener; private ElementResizeListener widgetResizeListener;
errorIcon.setClassName("v-errorindicator"); errorIcon.setClassName("v-errorindicator");
} }
caption.appendChild(errorIcon); caption.appendChild(errorIcon);
} else if (errorIcon != null) {
errorIcon.removeFromParent();
errorIcon = null;

if(BrowserInfo.get().isTouchDevice()) {
addFocusHandlerToWidget(error, widget);
addBlurHandlerToWidget(widget);
}

} else {
if (errorIcon != null) {
errorIcon.removeFromParent();
errorIcon = null;
}

if (errorMessage != null) {
removeErrorMessageAndHandlers();
}
} }


if (caption != null) { if (caption != null) {
} }
} }


private void removeErrorMessageAndHandlers() {
errorMessage.removeFromParent();
errorMessage = null;

if (focusRegistration != null) {
focusRegistration.removeHandler();
focusRegistration = null;
}

if(blurRegistration != null) {
blurRegistration.removeHandler();
blurRegistration = null;
}
}

private void addFocusHandlerToWidget(final String error, Widget widget) {
focusRegistration = widget.addHandler(new FocusHandler() {
@Override
public void onFocus(FocusEvent event) {
if(labelClicked) {
labelClicked = false;
return;
}
if (errorMessage == null) {
errorMessage = DOM.createDiv();
errorMessage.setClassName("v-touch-error-message");
}
errorMessage.setInnerHTML(error);
captionWrap.appendChild(errorMessage);
}
}, FocusEvent.getType());
}

private void addBlurHandlerToWidget(final Widget widget) {
blurRegistration = widget.addHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
if(errorMessage != null) {
addClickHandlerToErrorMessage(widget);
}
scheduleErrorMessageHide(TOUCH_ERROR_MESSAGE_HIDE_DELAY);
}
}, BlurEvent.getType());
}

private void scheduleErrorMessageHide(int delay) {
//Delaying hiding to allow error message click handler
//do his job and return the focus back if error message was tapped
Timer hideTimer = new Timer() {
@Override
public void run() {
if(errorMessage != null) {
errorMessage.removeFromParent();
errorMessage = null;
}
}
};
hideTimer.schedule(delay);
}

private void addClickHandlerToErrorMessage(final Widget widget) {
Event.sinkEvents(errorMessage, Event.ONCLICK);
Event.setEventListener(errorMessage, new EventListener() {
@Override
public void onBrowserEvent(Event event) {
if(Event.ONCLICK == event.getTypeInt()) {
errorMessage.removeFromParent();
errorMessage = null;
labelClicked = true;
widget.getElement().focus();
}
}
});
}

/** /**
* Does the slot have a caption * Does the slot have a caption
*/ */

+ 57
- 0
uitest/src/com/vaadin/tests/components/TouchDevicesTooltip.java View File

package com.vaadin.tests.components;

import com.vaadin.data.util.converter.StringToIntegerConverter;
import com.vaadin.data.validator.IntegerRangeValidator;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

public class TouchDevicesTooltip extends AbstractTestUI {

@Override
protected void setup(VaadinRequest request) {
final Label errorLabel = new Label("No error");
addComponent(errorLabel);

TextField textField = new TextField("Value");
textField.setConverter(new StringToIntegerConverter());
textField.addValidator(new IntegerRangeValidator("incorrect value", 0, 100));
textField.setImmediate(true);
textField.setValue("-5");
addComponent(textField);

TextField textField2 = new TextField("Value2");
textField2.setConverter(new StringToIntegerConverter());
textField2.addValidator(new IntegerRangeValidator("incorrect value2", 0, 100));
textField2.setImmediate(true);
textField2.setValue("-5");
addComponent(textField2);
}

public static class Bean {
@NotNull
@Min(0)
private Integer value;

public Integer getValue() {
return value;
}

public void setValue(Integer value) {
this.value = value;
}
}

@Override
protected Integer getTicketNumber() {
return 15353;
}

@Override
public String getDescription() {
return "Displaying error message in slot for touch devices";
}
}

Loading…
Cancel
Save