]> source.dussan.org Git - vaadin-framework.git/commitdiff
Make select all work with TreeGrid (#9412)
authorAleksi Hietanen <aleksi@vaadin.com>
Tue, 23 May 2017 13:14:34 +0000 (16:14 +0300)
committerHenri Sara <henri.sara@gmail.com>
Tue, 23 May 2017 13:14:34 +0000 (16:14 +0300)
Fixes #9403

server/src/main/java/com/vaadin/ui/components/grid/MultiSelectionModelImpl.java
uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridBasicFeatures.java
uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridSelectTest.java [new file with mode: 0644]

index 01635302f0d26dcf01d0ade36793461dff2d5c33..289db2a04f5107a3a18cadba89d6d3186e9813d9 100644 (file)
@@ -29,6 +29,8 @@ import java.util.stream.Stream;
 
 import com.vaadin.data.provider.DataCommunicator;
 import com.vaadin.data.provider.DataProvider;
+import com.vaadin.data.provider.HierarchicalDataProvider;
+import com.vaadin.data.provider.HierarchicalQuery;
 import com.vaadin.data.provider.Query;
 import com.vaadin.event.selection.MultiSelectionEvent;
 import com.vaadin.event.selection.MultiSelectionListener;
@@ -312,14 +314,69 @@ public class MultiSelectionModelImpl<T> extends AbstractSelectionModel<T>
             getState().allSelected = true;
         }
 
-        DataProvider<T, ?> dataSource = getGrid().getDataProvider();
+        Stream<T> allItemsStream;
+        DataProvider<T, ?> dataProvider = getGrid().getDataProvider();
         // this will fetch everything from backend
-        Stream<T> stream = dataSource.fetch(new Query<>());
+        if (dataProvider instanceof HierarchicalDataProvider) {
+            allItemsStream = fetchAllHierarchical(
+                    (HierarchicalDataProvider<T, ?>) dataProvider);
+        } else {
+            allItemsStream = fetchAll(dataProvider);
+        }
         LinkedHashSet<T> allItems = new LinkedHashSet<>();
-        stream.forEach(allItems::add);
+        allItemsStream.forEach(allItems::add);
         updateSelection(allItems, Collections.emptySet(), userOriginated);
     }
 
+    /**
+     * Fetch all items from the given hierarchical data provider.
+     *
+     * @since 8.1
+     * @param dataProvider
+     *            the data provider to fetch from
+     * @return all items in the data provider
+     */
+    private Stream<T> fetchAllHierarchical(
+            HierarchicalDataProvider<T, ?> dataProvider) {
+        return fetchAllDescendants(null, dataProvider);
+    }
+
+    /**
+     * Fetch all the descendants of the given parent item from the given data
+     * provider.
+     *
+     * @since 8.1
+     * @param parent
+     *            the parent item to fetch descendants for
+     * @param dataProvider
+     *            the data provider to fetch from
+     * @return the stream of all descendant items
+     */
+    private Stream<T> fetchAllDescendants(T parent,
+            HierarchicalDataProvider<T, ?> dataProvider) {
+        List<T> children = dataProvider
+                .fetchChildren(new HierarchicalQuery<>(null, parent))
+                .collect(Collectors.toList());
+        if (children.isEmpty()) {
+            return Stream.empty();
+        }
+        return children.stream()
+                .flatMap(child -> Stream.concat(Stream.of(child),
+                        fetchAllDescendants(child, dataProvider)));
+    }
+
+    /**
+     * Fetch all items from the given data provider.
+     *
+     * @since 8.1
+     * @param dataProvider
+     *            the data provider to fetch from
+     * @return all items in this data provider
+     */
+    private Stream<T> fetchAll(DataProvider<T, ?> dataProvider) {
+        return dataProvider.fetch(new Query<>());
+    }
+
     /**
      * Triggered when the user unchecks the select all checkbox.
      *
index 911c13f449ae2c8555ae4ad646b5fa341e074bac..0c29f71294750974cee4604a2d4f8696fd75997c 100644 (file)
@@ -17,6 +17,7 @@ import com.vaadin.server.SerializablePredicate;
 import com.vaadin.shared.Range;
 import com.vaadin.tests.components.AbstractComponentTest;
 import com.vaadin.tests.data.bean.HierarchicalTestBean;
+import com.vaadin.ui.Grid.SelectionMode;
 import com.vaadin.ui.ItemCollapseAllowedProvider;
 import com.vaadin.ui.TreeGrid;
 
@@ -68,6 +69,7 @@ public class TreeGridBasicFeatures extends AbstractComponentTest<TreeGrid> {
         createExpandMenu();
         createCollapseMenu();
         createListenerMenu();
+        createSelectionModeMenu();
     }
 
     private void initializeDataProviders() {
@@ -137,6 +139,7 @@ public class TreeGridBasicFeatures extends AbstractComponentTest<TreeGrid> {
                 (treeGrid, value, data) -> treeGrid.setHierarchyColumn(value));
     }
 
+    @SuppressWarnings("unchecked")
     private void createCollapseAllowedSelect() {
         LinkedHashMap<String, ItemCollapseAllowedProvider<HierarchicalTestBean>> options = new LinkedHashMap<>();
         options.put("all allowed", t -> true);
@@ -190,4 +193,14 @@ public class TreeGridBasicFeatures extends AbstractComponentTest<TreeGrid> {
                                 + event.isUserOriginated() + "): "
                                 + event.getExpandedItem())));
     }
+
+    private void createSelectionModeMenu() {
+        LinkedHashMap<String, SelectionMode> options = new LinkedHashMap<>();
+        options.put("none", SelectionMode.NONE);
+        options.put("single", SelectionMode.SINGLE);
+        options.put("multi", SelectionMode.MULTI);
+
+        createSelectAction("Selection mode", "State", options, "single",
+                (treeGrid, value, data) -> treeGrid.setSelectionMode(value));
+    }
 }
diff --git a/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridSelectTest.java b/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridSelectTest.java
new file mode 100644 (file)
index 0000000..e167dc6
--- /dev/null
@@ -0,0 +1,60 @@
+package com.vaadin.tests.components.treegrid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.TreeGridElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class TreeGridSelectTest extends SingleBrowserTest {
+
+    @Override
+    public Class<?> getUIClass() {
+        return TreeGridBasicFeatures.class;
+    }
+
+    @Test
+    public void select_and_deselect_all() {
+        openTestURL();
+
+        selectMenuPath("Component", "Features", "Set data provider",
+                "TreeDataProvider");
+        selectMenuPath("Component", "State", "Selection mode", "multi");
+
+        TreeGridElement grid = $(TreeGridElement.class).first();
+
+        assertAllRowsDeselected(grid);
+        clickSelectAll(grid);
+        assertAllRowsSelected(grid);
+        grid.expandWithClick(1, 1);
+        grid.expandWithClick(2, 1);
+        assertAllRowsSelected(grid);
+        clickSelectAll(grid);
+        assertAllRowsDeselected(grid);
+        clickSelectAll(grid);
+        grid.collapseWithClick(2, 1);
+        grid.expandWithClick(2, 1);
+        assertAllRowsSelected(grid);
+        grid.collapseWithClick(2, 1);
+        clickSelectAll(grid);
+        grid.expandWithClick(2, 1);
+        assertAllRowsDeselected(grid);
+    }
+
+    private void assertAllRowsSelected(TreeGridElement grid) {
+        for (int i = 0; i < grid.getRowCount(); i++) {
+            Assert.assertTrue(grid.getRow(i).isSelected());
+        }
+    }
+
+    private void assertAllRowsDeselected(TreeGridElement grid) {
+        for (int i = 0; i < grid.getRowCount(); i++) {
+            Assert.assertFalse(grid.getRow(i).isSelected());
+        }
+    }
+
+    private void clickSelectAll(TreeGridElement grid) {
+        grid.getHeaderCell(0, 0).findElement(By.tagName("input")).click();
+    }
+}