diff options
4 files changed, 225 insertions, 1 deletions
diff --git a/documentation/components/components-treegrid.asciidoc b/documentation/components/components-treegrid.asciidoc index b0e28fee5f..d3a431c3e9 100644 --- a/documentation/components/components-treegrid.asciidoc +++ b/documentation/components/components-treegrid.asciidoc @@ -93,3 +93,16 @@ treeGrid.addColumn(Project::getHoursDone).setCaption("Hours Done"); treeGrid.setHierarchyColumn("name"); ---- +== Listening to Events + +In addition to supporting all the listeners of the standard [classname]#Grid#, [classname]#TreeGrid# supports listening to the expansion and collapsing of items in its hierarchy. +The expand and collapse listeners can be added as follows: + +[source, java] +---- +treeGrid.addExpandListener(event -> log("Item expanded: " + event.getExpandedItem())); +treeGrid.addCollapseListener(event -> log("Item collapsed: " + event.getCollapsedItem())); +---- + +The return types of the methods `getExpandedItem` and `getCollapsedItem` are the same as the type of the [classname]#TreeGrid# the events originated from. +Note that collapse listeners will not be triggered for any expanded subtrees of the collapsed item. diff --git a/server/src/main/java/com/vaadin/ui/TreeGrid.java b/server/src/main/java/com/vaadin/ui/TreeGrid.java index 82c857ac86..2378ff3f2b 100644 --- a/server/src/main/java/com/vaadin/ui/TreeGrid.java +++ b/server/src/main/java/com/vaadin/ui/TreeGrid.java @@ -15,6 +15,8 @@ */ package com.vaadin.ui; +import java.io.Serializable; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -33,6 +35,7 @@ import com.vaadin.data.provider.HierarchicalDataCommunicator; import com.vaadin.data.provider.HierarchicalDataProvider; import com.vaadin.data.provider.HierarchicalQuery; import com.vaadin.data.provider.InMemoryHierarchicalDataProvider; +import com.vaadin.shared.Registration; import com.vaadin.shared.ui.treegrid.NodeCollapseRpc; import com.vaadin.shared.ui.treegrid.TreeGridState; import com.vaadin.ui.declarative.DesignAttributeHandler; @@ -40,7 +43,7 @@ import com.vaadin.ui.declarative.DesignContext; import com.vaadin.ui.declarative.DesignFormatter; import com.vaadin.ui.renderers.AbstractRenderer; import com.vaadin.ui.renderers.Renderer; - +import com.vaadin.util.ReflectTools; /** * A grid component for displaying hierarchical tabular data. @@ -53,6 +56,123 @@ import com.vaadin.ui.renderers.Renderer; */ public class TreeGrid<T> extends Grid<T> { + /** + * Item expand event listener. + * + * @author Vaadin Ltd + * @since 8.1 + * @param <T> + * the expanded item's type + */ + @FunctionalInterface + public interface ExpandListener<T> extends Serializable { + + public static final Method EXPAND_METHOD = ReflectTools.findMethod( + ExpandListener.class, "itemExpand", ExpandEvent.class); + + /** + * Callback method for when an item has been expanded. + * + * @param event + * the expand event + */ + public void itemExpand(ExpandEvent<T> event); + } + + /** + * Item collapse event listener. + * + * @author Vaadin Ltd + * @since 8.1 + * @param <T> + * the collapsed item's type + */ + @FunctionalInterface + public interface CollapseListener<T> extends Serializable { + + public static final Method COLLAPSE_METHOD = ReflectTools.findMethod( + CollapseListener.class, "itemCollapse", CollapseEvent.class); + + /** + * Callback method for when an item has been collapsed. + * + * @param event + * the collapse event + */ + public void itemCollapse(CollapseEvent<T> event); + } + + /** + * An event that is fired when an item is expanded. + * + * @author Vaadin Ltd + * @since 8.1 + * @param <T> + * the expanded item's type + */ + public static class ExpandEvent<T> extends Component.Event { + + private final T expandedItem; + + /** + * Construct an expand event. + * + * @param source + * the tree grid this event originated from + * @param item + * the item that was expanded + */ + public ExpandEvent(TreeGrid<T> source, T expandedItem) { + super(source); + this.expandedItem = expandedItem; + } + + /** + * Get the expanded item that triggered this event. + * + * @return the expanded item + */ + public T getExpandedItem() { + return expandedItem; + } + } + + /** + * An event that is fired when an item is collapsed. Note that expanded + * subtrees of the collapsed item will not trigger collapse events. + * + * @author Vaadin Ltd + * @since 8.1 + * @param <T> + * collapsed item type + */ + public static class CollapseEvent<T> extends Component.Event { + + private final T collapsedItem; + + /** + * Construct a collapse event. + * + * @param source + * the tree grid this event originated from + * @param item + * the item that was collapsed + */ + public CollapseEvent(TreeGrid<T> source, T collapsedItem) { + super(source); + this.collapsedItem = collapsedItem; + } + + /** + * Get the collapsed item that triggered this event. + * + * @return the collapsed item + */ + public T getCollapsedItem() { + return collapsedItem; + } + } + public TreeGrid() { super(new HierarchicalDataCommunicator<>()); @@ -62,14 +182,46 @@ public class TreeGrid<T> extends Grid<T> { boolean collapse) { if (collapse) { getDataCommunicator().doCollapse(rowKey, rowIndex); + fireCollapseEvent( + getDataCommunicator().getKeyMapper().get(rowKey)); } else { getDataCommunicator().doExpand(rowKey, rowIndex); + fireExpandEvent( + getDataCommunicator().getKeyMapper().get(rowKey)); } } }); } /** + * Adds an ExpandListener to this TreeGrid. + * + * @see ExpandEvent + * + * @param listener + * the listener to add + * @return a registration for the listener + */ + public Registration addExpandListener(ExpandListener<T> listener) { + return addListener(ExpandEvent.class, listener, + ExpandListener.EXPAND_METHOD); + } + + /** + * Adds a CollapseListener to this TreeGrid. + * + * @see CollapseEvent + * + * @param listener + * the listener to add + * @return a registration for the listener + */ + public Registration addCollapseListener(CollapseListener<T> listener) { + return addListener(CollapseEvent.class, listener, + CollapseListener.COLLAPSE_METHOD); + } + + /** * Sets the data items of this component provided as a collection. * <p> * The provided items are wrapped into a @@ -336,4 +488,24 @@ public class TreeGrid<T> extends Grid<T> { } }; } + + /** + * Emit an expand event. + * + * @param item + * the item that was expanded + */ + private void fireExpandEvent(T item) { + fireEvent(new ExpandEvent<>(this, item)); + } + + /** + * Emit a collapse event. + * + * @param item + * the item that was collapsed + */ + private void fireCollapseEvent(T item) { + fireEvent(new CollapseEvent<>(this, item)); + } } diff --git a/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeatures.java b/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeatures.java index 7998537a6e..3b58e6c75e 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeatures.java +++ b/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeatures.java @@ -54,6 +54,7 @@ public class TreeGridBasicFeatures extends AbstractComponentTest<TreeGrid> { createDataProviderSelect(); createHierarchyColumnSelect(); + createListenerMenu(); } private void initializeDataProviders() { @@ -102,6 +103,16 @@ public class TreeGridBasicFeatures extends AbstractComponentTest<TreeGrid> { (treeGrid, value, data) -> treeGrid.setHierarchyColumn(value)); } + @SuppressWarnings("unchecked") + private void createListenerMenu() { + createListenerAction("Collapse listener", "State", + treeGrid -> treeGrid.addCollapseListener(event -> log( + "Item collapsed: " + event.getCollapsedItem()))); + createListenerAction("Expand listener", "State", + treeGrid -> treeGrid.addExpandListener(event -> log( + "Item expanded: " + event.getExpandedItem()))); + } + static class HierarchicalTestBean { private final String id; diff --git a/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeaturesTest.java b/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeaturesTest.java index b01a6273e2..215bef95d2 100644 --- a/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeaturesTest.java +++ b/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeaturesTest.java @@ -119,6 +119,34 @@ public class TreeGridBasicFeaturesTest extends MultiBrowserTest { .isElementPresent(By.className("v-tree-grid-expander"))); } + @Test + public void expand_and_collapse_listeners() { + selectMenuPath("Component", "State", "Expand listener"); + selectMenuPath("Component", "State", "Collapse listener"); + + Assert.assertFalse(logContainsText("Item expanded: 0 | 0")); + Assert.assertFalse(logContainsText("Item collapsed: 0 | 0")); + + grid.collapseWithClick(0); + + Assert.assertTrue(logContainsText("Item expanded: 0 | 0")); + Assert.assertFalse(logContainsText("Item collapsed: 0 | 0")); + + grid.collapseWithClick(0); + + Assert.assertTrue(logContainsText("Item expanded: 0 | 0")); + Assert.assertTrue(logContainsText("Item collapsed: 0 | 0")); + + selectMenuPath("Component", "State", "Expand listener"); + selectMenuPath("Component", "State", "Collapse listener"); + + grid.collapseWithClick(1); + grid.collapseWithClick(1); + + Assert.assertFalse(logContainsText("Item expanded: 0 | 1")); + Assert.assertFalse(logContainsText("Item collapsed: 0 | 1")); + } + private void assertCellTexts(int startRowIndex, int cellIndex, String[] cellTexts) { int index = startRowIndex; |