summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2015-10-05 11:23:46 +0300
committerVaadin Code Review <review@vaadin.com>2015-10-05 11:10:13 +0000
commit5097095625403405d030575fcc1102f02aa3e327 (patch)
tree99d68d5d570a33f6fb2435b4f7d68dc5c563641c
parent743095d97bbd632e0493fca29ba2308b17b86716 (diff)
downloadvaadin-framework-5097095625403405d030575fcc1102f02aa3e327.tar.gz
vaadin-framework-5097095625403405d030575fcc1102f02aa3e327.zip
Add support for TreeContextClickEvents (#19062)
Tree connector now overrides the send context click event providing the row key to the server-side via RPC call. This is then passed on to a TreeContextClickEvent and fired to listeners. This patch modifies the test base for context click testing by making it tolerate 1 piksel differences. This was to fix any subpixel related issues in coordinate comparison. Change-Id: Iacced274a6b518b5f89378cbc32b8381362e1e4f
-rw-r--r--client/src/com/vaadin/client/ui/VTree.java5
-rw-r--r--client/src/com/vaadin/client/ui/tree/TreeConnector.java26
-rw-r--r--server/src/com/vaadin/ui/Tree.java36
-rw-r--r--shared/src/com/vaadin/shared/ui/tree/TreeServerRpc.java34
-rw-r--r--uitest/src/com/vaadin/tests/contextclick/AbstractContextClickTest.java66
-rw-r--r--uitest/src/com/vaadin/tests/contextclick/TreeContextClick.java39
-rw-r--r--uitest/src/com/vaadin/tests/contextclick/TreeContextClickTest.java78
7 files changed, 267 insertions, 17 deletions
diff --git a/client/src/com/vaadin/client/ui/VTree.java b/client/src/com/vaadin/client/ui/VTree.java
index 3e51374dc7..8fcb01e5d5 100644
--- a/client/src/com/vaadin/client/ui/VTree.java
+++ b/client/src/com/vaadin/client/ui/VTree.java
@@ -1088,9 +1088,10 @@ public class VTree extends FocusElementPanel implements VHasDropHandler,
top += Window.getScrollTop();
left += Window.getScrollLeft();
client.getContextMenu().showAt(this, left, top);
+
+ event.stopPropagation();
+ event.preventDefault();
}
- event.stopPropagation();
- event.preventDefault();
}
}
diff --git a/client/src/com/vaadin/client/ui/tree/TreeConnector.java b/client/src/com/vaadin/client/ui/tree/TreeConnector.java
index b2babe9d52..842be9c4d3 100644
--- a/client/src/com/vaadin/client/ui/tree/TreeConnector.java
+++ b/client/src/com/vaadin/client/ui/tree/TreeConnector.java
@@ -22,8 +22,11 @@ import java.util.Set;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.EventTarget;
+import com.google.gwt.event.dom.client.ContextMenuEvent;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.BrowserInfo;
+import com.vaadin.client.MouseEventDetailsBuilder;
import com.vaadin.client.Paintable;
import com.vaadin.client.TooltipInfo;
import com.vaadin.client.UIDL;
@@ -33,9 +36,11 @@ import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.client.ui.VTree;
import com.vaadin.client.ui.VTree.TreeNode;
+import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.MultiSelectMode;
import com.vaadin.shared.ui.tree.TreeConstants;
+import com.vaadin.shared.ui.tree.TreeServerRpc;
import com.vaadin.shared.ui.tree.TreeState;
import com.vaadin.ui.Tree;
@@ -373,4 +378,25 @@ public class TreeConnector extends AbstractComponentConnector implements
return true;
}
+ @Override
+ protected void sendContextClickEvent(ContextMenuEvent event) {
+ EventTarget eventTarget = event.getNativeEvent().getEventTarget();
+ if (!Element.is(eventTarget)) {
+ return;
+ }
+
+ Element e = Element.as(eventTarget);
+ String key = null;
+ MouseEventDetails details = MouseEventDetailsBuilder
+ .buildMouseEventDetails(event.getNativeEvent());
+
+ if (getWidget().body.getElement().isOrHasChild(e)) {
+ TreeNode t = WidgetUtil.findWidget(e, TreeNode.class);
+ if (t != null) {
+ key = t.key;
+ }
+ }
+
+ getRpcProxy(TreeServerRpc.class).contextClick(key, details);
+ }
}
diff --git a/server/src/com/vaadin/ui/Tree.java b/server/src/com/vaadin/ui/Tree.java
index b41139275b..2c537e3a98 100644
--- a/server/src/com/vaadin/ui/Tree.java
+++ b/server/src/com/vaadin/ui/Tree.java
@@ -38,6 +38,7 @@ import com.vaadin.data.util.ContainerHierarchicalWrapper;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
+import com.vaadin.event.ContextClickEvent;
import com.vaadin.event.DataBoundTransferable;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
@@ -59,6 +60,7 @@ import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.MultiSelectMode;
import com.vaadin.shared.ui.dd.VerticalDropLocation;
import com.vaadin.shared.ui.tree.TreeConstants;
+import com.vaadin.shared.ui.tree.TreeServerRpc;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignException;
@@ -75,6 +77,32 @@ import com.vaadin.util.ReflectTools;
public class Tree extends AbstractSelect implements Container.Hierarchical,
Action.Container, ItemClickNotifier, DragSource, DropTarget {
+ public static class TreeContextClickEvent extends ContextClickEvent {
+
+ private final Object itemId;
+
+ public TreeContextClickEvent(Tree source, Object itemId,
+ MouseEventDetails mouseEventDetails) {
+ super(source, mouseEventDetails);
+ this.itemId = itemId;
+ }
+
+ @Override
+ public Tree getComponent() {
+ return (Tree) super.getComponent();
+ }
+
+ /**
+ * Returns the item id of context clicked row.
+ *
+ * @return item id of clicked row; <code>null</code> if no row is
+ * present at the location
+ */
+ public Object getItemId() {
+ return itemId;
+ }
+ }
+
/* Private members */
private static final String NULL_ALT_EXCEPTION_MESSAGE = "Parameter 'altText' needs to be non null";
@@ -154,6 +182,14 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
*/
public Tree() {
this(null);
+
+ registerRpc(new TreeServerRpc() {
+ @Override
+ public void contextClick(String rowKey, MouseEventDetails details) {
+ fireEvent(new TreeContextClickEvent(Tree.this,
+ itemIdMapper.get(rowKey), details));
+ }
+ });
}
/**
diff --git a/shared/src/com/vaadin/shared/ui/tree/TreeServerRpc.java b/shared/src/com/vaadin/shared/ui/tree/TreeServerRpc.java
new file mode 100644
index 0000000000..e9ccdb57c6
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/tree/TreeServerRpc.java
@@ -0,0 +1,34 @@
+/*
+ * 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.shared.ui.tree;
+
+import com.vaadin.shared.MouseEventDetails;
+import com.vaadin.shared.communication.ServerRpc;
+
+/**
+ * Client-to-server RPC interface for the Tree component
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface TreeServerRpc extends ServerRpc {
+
+ /**
+ * Informs the server that a context click happened inside of Tree
+ */
+ public void contextClick(String rowKey, MouseEventDetails details);
+
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/contextclick/AbstractContextClickTest.java b/uitest/src/com/vaadin/tests/contextclick/AbstractContextClickTest.java
index 2323d0c9cb..ce97c87b75 100644
--- a/uitest/src/com/vaadin/tests/contextclick/AbstractContextClickTest.java
+++ b/uitest/src/com/vaadin/tests/contextclick/AbstractContextClickTest.java
@@ -18,7 +18,10 @@ package com.vaadin.tests.contextclick;
import static org.junit.Assert.assertEquals;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.junit.Assert;
import org.junit.Test;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebElement;
@@ -27,11 +30,15 @@ import org.openqa.selenium.remote.DesiredCapabilities;
import com.vaadin.testbench.elements.AbstractComponentElement;
import com.vaadin.testbench.elements.ButtonElement;
-import com.vaadin.testbench.parallel.BrowserUtil;
+import com.vaadin.testbench.parallel.TestCategory;
import com.vaadin.tests.tb3.MultiBrowserTest;
+@TestCategory("contextclick")
public abstract class AbstractContextClickTest extends MultiBrowserTest {
+ private Pattern defaultLog = Pattern
+ .compile("[0-9]+. ContextClickEvent: [(]([0-9]+), ([0-9]+)[)]");
+
@Override
public List<DesiredCapabilities> getBrowsersToTest() {
return getBrowsersSupportingContextMenu();
@@ -67,15 +74,25 @@ public abstract class AbstractContextClickTest extends MultiBrowserTest {
Point l = component.getLocation();
- int drift = 0;
- // IE 10 and 11 report different Y location.
- if (BrowserUtil.isIE(getDesiredCapabilities(), 10)
- || BrowserUtil.isIE(getDesiredCapabilities(), 11)) {
- drift = 1;
- }
-
- assertEquals(index + ". ContextClickEvent: (" + (l.getX() + 10) + ", "
- + (l.getY() + 10 + drift) + ")", getLogRow(0));
+ Matcher matcher = defaultLog.matcher(getLogRow(0));
+ Assert.assertTrue(
+ "Log row content did not match default listener output: "
+ + getLogRow(0), matcher.find());
+
+ int xCoord = Integer.parseInt(matcher.group(1));
+ int yCoord = Integer.parseInt(matcher.group(2));
+
+ int xExpected = l.getX() + 10;
+ int yExpected = l.getY() + 10;
+
+ Assert.assertTrue(
+ "X Coordinate differs too much from expected. Expected: "
+ + xExpected + ", actual: " + xCoord,
+ Math.abs(xExpected - xCoord) <= 1);
+ Assert.assertTrue(
+ "Y Coordinate differs too much from expected. Expected: "
+ + yExpected + ", actual: " + yCoord,
+ Math.abs(yExpected - yCoord) <= 1);
}
protected void addOrRemoveDefaultListener() {
@@ -89,15 +106,34 @@ public abstract class AbstractContextClickTest extends MultiBrowserTest {
}
/**
- * Performs a context click followed by a regular click. This prevents
- * browser context menu from blocking future operations.
+ * Performs a context click on given element at coordinates 10, 10 followed
+ * by a regular click. This prevents browser context menu from blocking
+ * future operations.
*
* @param e
* web element
*/
protected void contextClick(WebElement e) {
- new Actions(getDriver()).moveToElement(e, 10, 10).contextClick()
- .perform();
- new Actions(getDriver()).moveToElement(e, 5, 5).click().perform();
+ contextClick(e, 10, 10);
+ }
+
+ /**
+ * Performs a context click on given element at given coordinates followed
+ * by a regular click. This prevents browser context menu from blocking
+ * future operations.
+ *
+ * @param e
+ * web element
+ * @param xCoord
+ * x coordinate
+ * @param yCoord
+ * y coordinate
+ */
+ protected void contextClick(WebElement e, int xCoord, int yCoord) {
+ new Actions(getDriver()).moveToElement(e, xCoord, yCoord)
+ .contextClick().perform();
+ new Actions(getDriver()).moveToElement(e, xCoord - 5, yCoord - 5)
+ .click().perform();
}
+
}
diff --git a/uitest/src/com/vaadin/tests/contextclick/TreeContextClick.java b/uitest/src/com/vaadin/tests/contextclick/TreeContextClick.java
new file mode 100644
index 0000000000..6b58138ab2
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/contextclick/TreeContextClick.java
@@ -0,0 +1,39 @@
+/*
+ * 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.contextclick;
+
+import com.vaadin.ui.Tree;
+import com.vaadin.ui.Tree.TreeContextClickEvent;
+
+public class TreeContextClick extends
+ AbstractContextClickUI<Tree, TreeContextClickEvent> {
+
+ @Override
+ protected Tree createTestComponent() {
+ Tree tree = new Tree();
+ tree.addItem("Foo");
+ tree.addItem("Bar");
+ tree.addItem("Baz");
+ tree.setParent("Baz", "Bar");
+ tree.setHeight("200px");
+ return tree;
+ }
+
+ @Override
+ protected void handleContextClickEvent(TreeContextClickEvent event) {
+ log("ContextClickEvent: " + event.getItemId());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/contextclick/TreeContextClickTest.java b/uitest/src/com/vaadin/tests/contextclick/TreeContextClickTest.java
new file mode 100644
index 0000000000..180349af63
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/contextclick/TreeContextClickTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.contextclick;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.TreeElement;
+
+public class TreeContextClickTest extends AbstractContextClickTest {
+
+ @Test
+ public void testContextClickOnItem() {
+ openTestURL();
+
+ addOrRemoveTypedListener();
+
+ List<WebElement> nodes = $(TreeElement.class).first().findElements(
+ By.className("v-tree-node"));
+
+ contextClick(nodes.get(1));
+
+ assertEquals("1. ContextClickEvent: Bar", getLogRow(0));
+
+ contextClick(nodes.get(0));
+
+ assertEquals("2. ContextClickEvent: Foo", getLogRow(0));
+ }
+
+ @Test
+ public void testContextClickOnSubItem() {
+ openTestURL();
+
+ addOrRemoveTypedListener();
+
+ List<WebElement> nodes = $(TreeElement.class).first().findElements(
+ By.className("v-tree-node"));
+
+ new Actions(getDriver()).moveToElement(nodes.get(1), 10, 10).click()
+ .perform();
+
+ nodes = $(TreeElement.class).first().findElements(
+ By.className("v-tree-node"));
+ contextClick(nodes.get(2));
+
+ assertEquals("1. ContextClickEvent: Baz", getLogRow(0));
+ }
+
+ @Test
+ public void testContextClickOnEmptyArea() {
+ openTestURL();
+
+ addOrRemoveTypedListener();
+
+ contextClick($(TreeElement.class).first(), 20, 100);
+
+ assertEquals("1. ContextClickEvent: null", getLogRow(0));
+ }
+}