* interface.
*
* @since 7.6
- * @param event
+ * @param details
+ * @param eventTarget
*/
protected void sendContextClickEvent(MouseEventDetails details,
EventTarget eventTarget) {
*/
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;
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;
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.
+ }
}
);
----
+[[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
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;
+ }
}
/**
* 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;
}
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;
@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.
* 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
*
* @throws UnsupportedOperationException
* if selection has been disabled with
- * {@link SelectionMode.NONE}
+ * {@link SelectionMode#NONE}
*/
public Registration addSelectionListener(SelectionListener<T> listener) {
return treeGrid.addSelectionListener(listener);
* @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);
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);
}
}
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 -> Notification.show(
+ * ((TreeContextClickEvent<Person>)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();
+ }
+ }
}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}