]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix tooltip positioning near screen edges (#12870)
authorJuuso Valli <juuso@vaadin.com>
Mon, 2 Jun 2014 15:46:07 +0000 (18:46 +0300)
committerJuuso Valli <juuso@vaadin.com>
Mon, 9 Jun 2014 11:47:21 +0000 (14:47 +0300)
Change-Id: I3f5244565dd393e9fcb7386d352f835b5afd9faa

client/src/com/vaadin/client/VTooltip.java
uitest/src/com/vaadin/tests/components/menubar/MenuBarTooltipsNearEdge.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/menubar/MenuBarTooltipsNearEdgeTest.java [new file with mode: 0644]

index bbf5e5c32c6be7fc8e37e4c09d159cd9d5ede731..77720089b114317b31f556430c655ab57580239e 100644 (file)
@@ -153,15 +153,61 @@ public class VTooltip extends VWindowOverlay {
                         offsetWidth = getOffsetWidth();
                         offsetHeight = getOffsetHeight();
                     }
+                    int x = getFinalX(offsetWidth);
+                    int y = getFinalY(offsetHeight);
 
-                    int x = tooltipEventMouseX + 10 + Window.getScrollLeft();
-                    int y = tooltipEventMouseY + 10 + Window.getScrollTop();
+                    setPopupPosition(x, y);
+                    sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT);
+                }
 
+                /**
+                 * Return the final X-coordinate of the tooltip based on cursor
+                 * position, size of the tooltip, size of the page and necessary
+                 * margins.
+                 * 
+                 * @param offsetWidth
+                 * @return The final X-coordinate
+                 */
+                private int getFinalX(int offsetWidth) {
+                    int x = 0;
+                    int widthNeeded = 10 + MARGIN + offsetWidth;
+                    int roomLeft = tooltipEventMouseX;
+                    int roomRight = Window.getClientWidth() - roomLeft;
+                    if (roomRight > widthNeeded) {
+                        x = tooltipEventMouseX + 10 + Window.getScrollLeft();
+                    } else {
+                        x = tooltipEventMouseX + Window.getScrollLeft() - 10
+                                - offsetWidth;
+                    }
                     if (x + offsetWidth + MARGIN - Window.getScrollLeft() > Window
                             .getClientWidth()) {
                         x = Window.getClientWidth() - offsetWidth - MARGIN
                                 + Window.getScrollLeft();
                     }
+                    return x;
+                }
+
+                /**
+                 * Return the final Y-coordinate of the tooltip based on cursor
+                 * position, size of the tooltip, size of the page and necessary
+                 * margins.
+                 * 
+                 * @param offsetHeight
+                 * @return The final y-coordinate
+                 * 
+                 */
+                private int getFinalY(int offsetHeight) {
+                    int y = 0;
+                    int heightNeeded = 10 + MARGIN + offsetHeight;
+                    int roomAbove = tooltipEventMouseY;
+                    int roomBelow = Window.getClientHeight() - roomAbove;
+
+                    if (roomBelow > heightNeeded) {
+                        y = tooltipEventMouseY + 10 + Window.getScrollTop();
+                    } else {
+                        y = tooltipEventMouseY + Window.getScrollTop() - 10
+                                - offsetHeight;
+                    }
 
                     if (y + offsetHeight + MARGIN - Window.getScrollTop() > Window
                             .getClientHeight()) {
@@ -173,8 +219,7 @@ public class VTooltip extends VWindowOverlay {
                             y = Window.getScrollTop();
                         }
                     }
-                    setPopupPosition(x, y);
-                    sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT);
+                    return y;
                 }
             });
         } else {
diff --git a/uitest/src/com/vaadin/tests/components/menubar/MenuBarTooltipsNearEdge.java b/uitest/src/com/vaadin/tests/components/menubar/MenuBarTooltipsNearEdge.java
new file mode 100644 (file)
index 0000000..4e42d97
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.components.menubar;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.MenuBar;
+import com.vaadin.ui.MenuBar.Command;
+import com.vaadin.ui.MenuBar.MenuItem;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * Test to see if tooltips will render in the correct locations near the edges.
+ * 
+ * @author Vaadin Ltd
+ */
+public class MenuBarTooltipsNearEdge extends AbstractTestUI {
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server.
+     * VaadinRequest)
+     */
+    @Override
+    protected void setup(VaadinRequest request) {
+        VerticalLayout vlayout = new VerticalLayout();
+        vlayout.setSizeFull();
+        vlayout.addComponent(buildMenu("Menu"));
+        vlayout.setComponentAlignment(vlayout.getComponent(0),
+                Alignment.BOTTOM_RIGHT);
+        setContent(vlayout);
+
+        getTooltipConfiguration().setOpenDelay(0);
+        getTooltipConfiguration().setQuickOpenDelay(0);
+        getTooltipConfiguration().setCloseTimeout(1000);
+
+    }
+
+    private Component buildMenu(String label) {
+        MenuBar menu = new MenuBar();
+        MenuItem item = menu.addItem(label, null);
+
+        item.addItem("Item 1", null).setDescription("TOOLTIP 1");
+        item.addItem("Item 2", null).setDescription("TOOLTIP 2");
+        item.addItem("Item 3", null).setDescription("TOOLTIP 3");
+        item.addItem("Item 4", null).setDescription("TOOLTIP 4");
+
+        return menu;
+    }
+
+    private Command buildCommand() {
+        Command command = new Command() {
+
+            @Override
+            public void menuSelected(MenuItem selectedItem) {
+
+            }
+        };
+        return command;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription()
+     */
+    @Override
+    protected String getTestDescription() {
+        return "Menu item tooltips should not abscure other menu items";
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber()
+     */
+    @Override
+    protected Integer getTicketNumber() {
+        return 12870;
+    }
+}
diff --git a/uitest/src/com/vaadin/tests/components/menubar/MenuBarTooltipsNearEdgeTest.java b/uitest/src/com/vaadin/tests/components/menubar/MenuBarTooltipsNearEdgeTest.java
new file mode 100644 (file)
index 0000000..197963a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.components.menubar;
+
+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.WebElement;
+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.By;
+import com.vaadin.testbench.elements.MenuBarElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Test to see if tooltips will render in the correct locations near the edges.
+ * 
+ * @author Vaadin Ltd
+ */
+public class MenuBarTooltipsNearEdgeTest extends MultiBrowserTest {
+
+    @Override
+    public List<DesiredCapabilities> getBrowsersToTest() {
+        // Tooltip tests work unreliably on IE due to an issue with the
+        // WebDriver (see #13854)
+        List<DesiredCapabilities> browsers = super.getBrowsersToTest();
+        browsers.remove(Browser.IE8.getDesiredCapabilities());
+        return browsers;
+    };
+
+    @Test
+    public void testTooltipLocation() {
+        openTestURL();
+        Mouse mouse = ((HasInputDevices) getDriver()).getMouse();
+        WebElement menu = $(MenuBarElement.class).first().getWrappedElement();
+        Coordinates menuLocation = ((Locatable) menu).getCoordinates();
+        mouse.click(menuLocation);
+        mouse.mouseMove(menuLocation, 5, -40);
+        WebElement tooltip = getTooltipElement();
+        assertThat(tooltip.getLocation().x, is(lessThan(menuLocation.onPage().x
+                - tooltip.getSize().getWidth())));
+
+    }
+
+    private WebElement getTooltipElement() {
+        return getDriver().findElement(By.className("v-tooltip-text"));
+    }
+}