aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/main/java/com/vaadin/client/ui/AbstractComponentConnector.java3
-rw-r--r--client/src/main/java/com/vaadin/client/ui/composite/CompositeConnector.java8
-rw-r--r--documentation/components/components-tree.asciidoc11
-rw-r--r--server/src/main/java/com/vaadin/event/MouseEvents.java11
-rw-r--r--server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java6
-rw-r--r--server/src/main/java/com/vaadin/ui/Tree.java118
-rw-r--r--uitest/src/main/java/com/vaadin/tests/contextclick/TreeV8ContextClick.java72
-rw-r--r--uitest/src/test/java/com/vaadin/tests/contextclick/TreeV8ContextClickTest.java63
8 files changed, 281 insertions, 11 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/main/java/com/vaadin/client/ui/AbstractComponentConnector.java
index 8ba94f9ba7..1eb9908335 100644
--- a/client/src/main/java/com/vaadin/client/ui/AbstractComponentConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/AbstractComponentConnector.java
@@ -330,7 +330,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector
* interface.
*
* @since 7.6
- * @param event
+ * @param details
+ * @param eventTarget
*/
protected void sendContextClickEvent(MouseEventDetails details,
EventTarget eventTarget) {
diff --git a/client/src/main/java/com/vaadin/client/ui/composite/CompositeConnector.java b/client/src/main/java/com/vaadin/client/ui/composite/CompositeConnector.java
index 93e42fab1f..916363cf23 100644
--- a/client/src/main/java/com/vaadin/client/ui/composite/CompositeConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/composite/CompositeConnector.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.client.ui.composite;
+import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
@@ -22,6 +23,7 @@ import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.HasComponentsConnector;
import com.vaadin.client.ui.AbstractHasComponentsConnector;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.Connect.LoadStyle;
import com.vaadin.ui.Composite;
@@ -93,4 +95,10 @@ public class CompositeConnector extends AbstractHasComponentsConnector {
ConnectorHierarchyChangeEvent event) {
// Handled in getChildConnector
}
+
+ @Override
+ protected void sendContextClickEvent(MouseEventDetails details, EventTarget eventTarget) {
+ //Do nothing, because Composite is not an actual component, and the event
+ //must be handled in inner components.
+ }
}
diff --git a/documentation/components/components-tree.asciidoc b/documentation/components/components-tree.asciidoc
index 03ea963170..cc44bec6ea 100644
--- a/documentation/components/components-tree.asciidoc
+++ b/documentation/components/components-tree.asciidoc
@@ -98,6 +98,17 @@ tree.addItemClickListener(event ->
);
----
+[[components.tree.right.clicks]]
+=== Right-clicks
+Right-clicks are supported similar way via `addContextClickListener()` method
+
+[source, java]
+----
+ tree.addContextClickListener(event -> Notification.show(
+ ((TreeContextClickEvent<Person>)event).getItem() + " Clicked")
+ );
+----
+
[[components.tree.expandcollapse]]
== Expanding and Collapsing Nodes
diff --git a/server/src/main/java/com/vaadin/event/MouseEvents.java b/server/src/main/java/com/vaadin/event/MouseEvents.java
index 76f14d0840..34456f2498 100644
--- a/server/src/main/java/com/vaadin/event/MouseEvents.java
+++ b/server/src/main/java/com/vaadin/event/MouseEvents.java
@@ -182,6 +182,17 @@ public interface MouseEvents {
public String getButtonName() {
return details.getButtonName();
}
+
+ /**
+ * Returns an information about mouse event like position, buttons
+ * pressed etc.
+ *
+ * @since 8.1
+ * @return An information about mouse event
+ */
+ public MouseEventDetails getMouseEventDetails() {
+ return details;
+ }
}
/**
diff --git a/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java
index e4783cbf6e..f2caf5631c 100644
--- a/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java
+++ b/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java
@@ -591,10 +591,12 @@ public class ServerRpcHandler implements Serializable {
* corresponding to the received method invocation has been
* registered.
*/
- getLogger().warning("Ignoring RPC call to " + interfaceName + "."
+ String message = "Ignoring RPC call to " + interfaceName + "."
+ methodName + " in connector "
+ connector.getClass().getName() + "(" + connectorId
- + ") as no RPC implementation is registered");
+ + ") as no RPC implementation is registered";
+ assert rpcManager != null : message;
+ getLogger().warning(message);
return null;
}
diff --git a/server/src/main/java/com/vaadin/ui/Tree.java b/server/src/main/java/com/vaadin/ui/Tree.java
index 6ae86efe37..be00417374 100644
--- a/server/src/main/java/com/vaadin/ui/Tree.java
+++ b/server/src/main/java/com/vaadin/ui/Tree.java
@@ -34,12 +34,14 @@ import com.vaadin.data.provider.TreeDataProvider;
import com.vaadin.event.CollapseEvent;
import com.vaadin.event.CollapseEvent.CollapseListener;
import com.vaadin.event.ConnectorEvent;
+import com.vaadin.event.ContextClickEvent;
import com.vaadin.event.ExpandEvent;
import com.vaadin.event.ExpandEvent.ExpandListener;
import com.vaadin.event.SerializableEventListener;
import com.vaadin.event.selection.SelectionListener;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.Resource;
+import com.vaadin.shared.EventId;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.ContentMode;
@@ -69,6 +71,7 @@ public class Tree<T> extends Composite
@Deprecated
private static final Method ITEM_CLICK_METHOD = ReflectTools
.findMethod(ItemClickListener.class, "itemClick", ItemClick.class);
+ private Registration contextClickRegistration = null;
/**
* A listener for item click events.
@@ -483,7 +486,7 @@ public class Tree<T> extends Composite
* Adds a selection listener to the current selection model.
* <p>
* <strong>NOTE:</strong> If selection mode is switched with
- * {@link setSelectionMode(SelectionMode)}, then this listener is not
+ * {@link #setSelectionMode(SelectionMode)}, then this listener is not
* triggered anymore when selection changes!
*
* @param listener
@@ -492,7 +495,7 @@ public class Tree<T> extends Composite
*
* @throws UnsupportedOperationException
* if selection has been disabled with
- * {@link SelectionMode.NONE}
+ * {@link SelectionMode#NONE}
*/
public Registration addSelectionListener(SelectionListener<T> listener) {
return treeGrid.addSelectionListener(listener);
@@ -630,6 +633,7 @@ public class Tree<T> extends Composite
* @param listener
* the item click listener, not null
* @return a registration for the listener
+ * @see #addContextClickListener
*/
public Registration addItemClickListener(ItemClickListener<T> listener) {
return addListener(ItemClick.class, listener, ITEM_CLICK_METHOD);
@@ -655,12 +659,12 @@ public class Tree<T> extends Composite
Objects.requireNonNull(selectionMode,
"Can not set selection mode to null");
switch (selectionMode) {
- case MULTI:
- TreeMultiSelectionModel<T> model = new TreeMultiSelectionModel<>();
- treeGrid.setSelectionModel(model);
- return model;
- default:
- return treeGrid.setSelectionMode(selectionMode);
+ case MULTI:
+ TreeMultiSelectionModel<T> model = new TreeMultiSelectionModel<>();
+ treeGrid.setSelectionModel(model);
+ return model;
+ default:
+ return treeGrid.setSelectionMode(selectionMode);
}
}
@@ -811,4 +815,102 @@ public class Tree<T> extends Composite
public void setContentMode(ContentMode contentMode) {
renderer.getState().mode = contentMode;
}
+
+ /**
+ * Adds a context click listener that gets notified when a context click
+ * happens.
+ *
+ * @param listener
+ * the context click listener to add, not null
+ * actual event provided to the listener is {@link TreeContextClickEvent}
+ * @return a registration object for removing the listener
+ *
+ * @since 8.1
+ * @see #addItemClickListener
+ * @see Registration
+ */
+ @Override
+ public Registration addContextClickListener(ContextClickEvent.ContextClickListener listener) {
+ Registration registration =
+ addListener(EventId.CONTEXT_CLICK, ContextClickEvent.class,
+ listener, ContextClickEvent.CONTEXT_CLICK_METHOD);
+ setupContextClickListener();
+ return () -> {
+ registration.remove();
+ setupContextClickListener();
+ };
+ }
+
+ @Override
+ @Deprecated
+ public void removeContextClickListener(ContextClickEvent.ContextClickListener listener) {
+ super.removeContextClickListener(listener);
+ setupContextClickListener();
+ }
+
+ private void setupContextClickListener() {
+ if (hasListeners(ContextClickEvent.class)) {
+ if (contextClickRegistration == null) {
+ contextClickRegistration = treeGrid.addContextClickListener(
+ event -> {
+ T item = null;
+ if (event instanceof Grid.GridContextClickEvent) {
+ item = ((Grid.GridContextClickEvent<T>) event).getItem();
+ }
+ fireEvent(new TreeContextClickEvent<>(this, event.getMouseEventDetails(), item));
+ }
+ );
+ }
+ } else if (contextClickRegistration != null) {
+ contextClickRegistration.remove();
+ contextClickRegistration = null;
+ }
+ }
+
+ /**
+ * ContextClickEvent for the Tree Component.
+ * <p>
+ * Usage:
+ * <pre>
+ * tree.addContextClickListener(event -&gt; Notification.show(
+ * ((TreeContextClickEvent&lt;Person&gt;)event).getItem() + " Clicked")
+ * );
+ * </pre>
+ *
+ * @param <T> the tree bean type
+ */
+ public static class TreeContextClickEvent<T> extends ContextClickEvent {
+
+ private final T item;
+
+ /**
+ * Creates a new context click event.
+ *
+ * @param source the tree where the context click occurred
+ * @param mouseEventDetails details about mouse position
+ * @param item the item which was clicked or {@code null}
+ * if the click happened outside any item
+ */
+ public TreeContextClickEvent(Tree<T> source,
+ MouseEventDetails mouseEventDetails,
+ T item) {
+ super(source, mouseEventDetails);
+ this.item = item;
+ }
+
+ /**
+ * Returns the item of context clicked row.
+ *
+ * @return clicked item; {@code null}
+ * the click happened outside any item
+ */
+ public T getItem() {
+ return item;
+ }
+
+ @Override
+ public Tree<T> getComponent() {
+ return (Tree<T>) super.getComponent();
+ }
+ }
}
diff --git a/uitest/src/main/java/com/vaadin/tests/contextclick/TreeV8ContextClick.java b/uitest/src/main/java/com/vaadin/tests/contextclick/TreeV8ContextClick.java
new file mode 100644
index 0000000000..ed30eb47d6
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/contextclick/TreeV8ContextClick.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2016 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.data.TreeData;
+import com.vaadin.shared.Registration;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Tree;
+import com.vaadin.ui.Tree.TreeContextClickEvent;
+
+import java.util.Collections;
+
+public class TreeV8ContextClick extends
+ AbstractContextClickUI<Tree<String>, TreeContextClickEvent<String>> {
+
+ @Override
+ protected Tree<String> createTestComponent() {
+ TreeData<String> treeData = new TreeData<>();
+ for (int i = 0; i < 3; i++) {
+ String grandDad = "Granddad " + i;
+ treeData.addItems(null, grandDad);
+ for (int j = 0; j < 4; j++) {
+ String dad = "Dad " + i + "/" + j;
+ treeData.addItems(grandDad, dad);
+ for (int k = 0; k < 5; k++) {
+ treeData.addItems(dad, "Son " + i + "/" + j + "/" + k);
+ }
+ }
+ }
+ Tree<String> tree = new Tree<>("Clane", treeData);
+ tree.setWidth("100%");
+ return tree;
+ }
+
+ @Override
+ protected void handleContextClickEvent(
+ TreeContextClickEvent<String> event) {
+ String value = event.getItem();
+ log("ContextClickEvent value: " + value);
+ }
+
+ @Override
+ protected HorizontalLayout createContextClickControls() {
+ HorizontalLayout controls = super.createContextClickControls();
+ controls.addComponent(
+ new Button("Remove all content", new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ testComponent.setItems(Collections.emptyList());
+ testComponent.setHeight("200px");
+ }
+ }));
+ return controls;
+ }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/contextclick/TreeV8ContextClickTest.java b/uitest/src/test/java/com/vaadin/tests/contextclick/TreeV8ContextClickTest.java
new file mode 100644
index 0000000000..3272cce334
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/contextclick/TreeV8ContextClickTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2016 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.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TreeElement;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import static org.junit.Assert.assertEquals;
+
+public class TreeV8ContextClickTest extends AbstractContextClickTest {
+
+ @Test
+ public void testBodyContextClickWithTypedListener() {
+ addOrRemoveTypedListener();
+
+ TreeElement tree = $(TreeElement.class).first();
+ contextClick(tree.getItem(0));
+
+ assertEquals(
+ "1. ContextClickEvent value: Granddad 0",
+ getLogRow(0));
+
+ tree.expand(0);
+ tree.expand(2);
+ contextClick(tree.getItem(6));
+
+ assertEquals(
+ "2. ContextClickEvent value: Son 0/1/3",
+ getLogRow(0));
+ }
+
+ /**
+ * Performs a context click on given element at coordinates 20, 10 followed
+ * by a regular click. This prevents browser context menu from blocking
+ * future operations.
+ *
+ * A smaller X offset might hit the resize handle of the previous cell that
+ * overlaps with the next header cell.
+ *
+ * @param e
+ * web element
+ */
+ @Override
+ protected void contextClick(WebElement e) {
+ contextClick(e, 20, 10);
+ }
+
+}