diff options
3 files changed, 181 insertions, 22 deletions
diff --git a/client/src/com/vaadin/client/VTooltip.java b/client/src/com/vaadin/client/VTooltip.java index 8e653a0476..1385a52469 100644 --- a/client/src/com/vaadin/client/VTooltip.java +++ b/client/src/com/vaadin/client/VTooltip.java @@ -229,18 +229,23 @@ public class VTooltip extends VWindowOverlay { /** * For assistive tooltips to work correctly we must have the tooltip visible - * and attached to the DOM well in advance. + * and attached to the DOM well in advance. For this reason both isShowing + * and isVisible return false positives. We can't override either of them as + * external code may depend on this behavior. * - * @return + * @return boolean */ - public boolean isActuallyVisible() { - return super.isShowing() && getPopupLeft() > 0 && getPopupTop() > 0; + public boolean isTooltipOpen() { + return super.isShowing() && super.isVisible() && getPopupLeft() > 0 + && getPopupTop() > 0; } private void closeNow() { hide(); setWidth(""); closing = false; + justClosedTimer.schedule(getQuickOpenTimeout()); + justClosed = true; } private Timer showTimer = new Timer() { @@ -255,8 +260,6 @@ public class VTooltip extends VWindowOverlay { @Override public void run() { closeNow(); - justClosedTimer.schedule(getQuickOpenTimeout()); - justClosed = true; } }; @@ -279,7 +282,7 @@ public class VTooltip extends VWindowOverlay { // already about to close return; } - if (isActuallyVisible()) { + if (isTooltipOpen()) { closeTimer.schedule(getCloseTimeout()); closing = true; } @@ -331,6 +334,8 @@ public class VTooltip extends VWindowOverlay { if (closing) { closeTimer.cancel(); closeNow(); + justClosedTimer.cancel(); + justClosed = false; } showTooltip(); @@ -449,7 +454,7 @@ public class VTooltip extends VWindowOverlay { // hasn't changed, we ignore the event. // TooltipInfo contains a reference to the parent component that is // checked in it's equals-method. - if (currentElement != null && isActuallyVisible()) { + if (currentElement != null && isTooltipOpen()) { TooltipInfo currentTooltip = getTooltipFor(currentElement); TooltipInfo newTooltip = getTooltipFor(element); if (currentTooltip != null && currentTooltip.equals(newTooltip)) { @@ -465,24 +470,21 @@ public class VTooltip extends VWindowOverlay { closeTimer.cancel(); closing = false; } + + if (isTooltipOpen()) { + closeNow(); + } + setTooltipText(info); updatePosition(event, isFocused); - if (isActuallyVisible() && !isFocused) { + // Schedule timer for showing the tooltip according to if it + // was recently closed or not. + int timeout = justClosed ? getQuickOpenDelay() : getOpenDelay(); + if (timeout == 0) { showTooltip(); } else { - if (isActuallyVisible()) { - closeNow(); - } - // Schedule timer for showing the tooltip according to if it - // was recently closed or not. - int timeout = justClosed ? getQuickOpenDelay() - : getOpenDelay(); - if (timeout == 0) { - showTooltip(); - } else { - showTimer.schedule(timeout); - opening = true; - } + showTimer.schedule(timeout); + opening = true; } } diff --git a/uitest/src/com/vaadin/tests/tooltip/AdjacentElementsWithTooltips.java b/uitest/src/com/vaadin/tests/tooltip/AdjacentElementsWithTooltips.java new file mode 100644 index 0000000000..60167e43b4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tooltip/AdjacentElementsWithTooltips.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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 com.vaadin.tests.tooltip; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Component; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.TooltipConfiguration; + +/** + * When moving between adjacent elements, the tooltip replace should obey + * quickOpenDelay + * + * @author Vaadin Ltd + */ +public class AdjacentElementsWithTooltips extends AbstractTestUI { + + private int buttonCount = 0; + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. + * VaadinRequest) + */ + @Override + protected void setup(VaadinRequest request) { + TooltipConfiguration ttc = super.getTooltipConfiguration(); + ttc.setMaxWidth(350); + ttc.setOpenDelay(200); + ttc.setCloseTimeout(200); + ttc.setQuickOpenDelay(1000); + ttc.setQuickOpenTimeout(1000); + HorizontalLayout layout = new HorizontalLayout(); + layout.addComponent(makeButton("first")); + layout.addComponent(makeButton("second")); + addComponent(layout); + + } + + private Component makeButton(String tooltip) { + Button button = new Button("Button " + buttonCount++); + button.setDescription(tooltip); + return button; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Moving between adjacent elements with tooltips should open quickOpenDelay"; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 13998; + } + +} diff --git a/uitest/src/com/vaadin/tests/tooltip/AdjacentElementsWithTooltipsTest.java b/uitest/src/com/vaadin/tests/tooltip/AdjacentElementsWithTooltipsTest.java new file mode 100644 index 0000000000..b9fc788008 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tooltip/AdjacentElementsWithTooltipsTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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 com.vaadin.tests.tooltip; + +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.interactions.HasInputDevices; +import org.openqa.selenium.interactions.Mouse; +import org.openqa.selenium.interactions.internal.Coordinates; +import org.openqa.selenium.internal.Locatable; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test to see if tooltips obey quickOpenDelay when moving between directly + * adjacent elements. + * + * @author Vaadin Ltd + */ +public class AdjacentElementsWithTooltipsTest extends MultiBrowserTest { + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + return getBrowsersExcludingIE(); + } + + @Test + public void tooltipsHaveQuickOpenDelay() throws InterruptedException { + openTestURL(); + Coordinates button0Coordinates = getButtonCoordinates("Button 0"); + Coordinates button1Coordinates = getButtonCoordinates("Button 1"); + + Mouse mouse = getMouse(); + mouse.mouseMove(button0Coordinates, 10, 10); + sleep(1000); + assertThat(getTooltipElement().getLocation().x, is(greaterThan(0))); + + mouse.mouseMove(button1Coordinates, 10, 10); + assertThat(getTooltipElement().getLocation().x, is(lessThan(-1000))); + + sleep(1000); + assertThat(getTooltipElement().getLocation().x, + is(greaterThan(button1Coordinates.onPage().x))); + } + + private Coordinates getButtonCoordinates(String caption) { + return getCoordinates(getButton(caption)); + } + + private ButtonElement getButton(String caption) { + return $(ButtonElement.class) + .caption(caption).first(); + } +} |