summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorAleksi Hietanen <aleksi@vaadin.com>2017-02-23 09:34:59 +0200
committerPekka Hyvönen <pekka@vaadin.com>2017-02-23 09:34:59 +0200
commit6783bca88d4cf0c8944e84a0fef0a219c0b9a4d0 (patch)
tree4fe5a5752482f73c902beb4b5e05e647a2b6203b /server
parent813a99cfeff9d9cd70d77bd5d9ae75f5fa7b2ff5 (diff)
downloadvaadin-framework-6783bca88d4cf0c8944e84a0fef0a219c0b9a4d0.tar.gz
vaadin-framework-6783bca88d4cf0c8944e84a0fef0a219c0b9a4d0.zip
Add initial implementation of TreeGrid (#8572)
* Add initial implementation of TreeGrid * Refactor TreeGrid and related classes * Fix potential class cast exception in TreeGrid#getDataProvider * Add smoke tests for TreeGrid * Add communication constants for TreeGrid Use shared constant values for hierarchy data serialization and deserialization * Fix event ordering in TreeGrid, add javadocs, keyboard navigation test * TreeGrid improvements * Add TreeGrid.getDataProvider to StateGetDoesNotMarkDirtyTest exclude list * Merge remote-tracking branch 'github/master' into tree-grid * Remove getEscalator override from TreeGrid
Diffstat (limited to 'server')
-rw-r--r--server/src/main/java/com/vaadin/data/provider/HierarchicalDataProvider.java39
-rw-r--r--server/src/main/java/com/vaadin/ui/Grid.java2
-rw-r--r--server/src/main/java/com/vaadin/ui/TreeGrid.java164
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java1
4 files changed, 205 insertions, 1 deletions
diff --git a/server/src/main/java/com/vaadin/data/provider/HierarchicalDataProvider.java b/server/src/main/java/com/vaadin/data/provider/HierarchicalDataProvider.java
new file mode 100644
index 0000000000..ec54a3a138
--- /dev/null
+++ b/server/src/main/java/com/vaadin/data/provider/HierarchicalDataProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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.data.provider;
+
+/**
+ *
+ * @author Vaadin Ltd
+ * @since 8.1
+ *
+ * @param <T>
+ * @param <F>
+ */
+public interface HierarchicalDataProvider<T, F> extends DataProvider<T, F> {
+
+ public int getDepth(T item);
+
+ public boolean isRoot(T item);
+
+ public T getParent(T item);
+
+ public boolean isCollapsed(T item);
+
+ public boolean hasChildren(T item);
+
+ public void setCollapsed(T item, boolean b);
+}
diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java
index 186be328f4..c3456075c3 100644
--- a/server/src/main/java/com/vaadin/ui/Grid.java
+++ b/server/src/main/java/com/vaadin/ui/Grid.java
@@ -646,7 +646,7 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents,
Type type = null;
try {
type = getState(false).getClass()
- .getDeclaredField(diffStateKey).getGenericType();
+ .getField(diffStateKey).getGenericType();
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
diff --git a/server/src/main/java/com/vaadin/ui/TreeGrid.java b/server/src/main/java/com/vaadin/ui/TreeGrid.java
new file mode 100644
index 0000000000..f438df4e8f
--- /dev/null
+++ b/server/src/main/java/com/vaadin/ui/TreeGrid.java
@@ -0,0 +1,164 @@
+/*
+ * 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.ui;
+
+import java.util.Collection;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import com.vaadin.data.provider.DataProvider;
+import com.vaadin.data.provider.HierarchicalDataProvider;
+import com.vaadin.shared.ui.treegrid.NodeCollapseRpc;
+import com.vaadin.shared.ui.treegrid.TreeGridCommunicationConstants;
+import com.vaadin.shared.ui.treegrid.TreeGridState;
+
+import elemental.json.Json;
+import elemental.json.JsonObject;
+
+/**
+ * A grid component for displaying hierarchical tabular data.
+ *
+ * @author Vaadin Ltd
+ * @since 8.1
+ *
+ * @param <T>
+ * the grid bean type
+ */
+public class TreeGrid<T> extends Grid<T> {
+
+ public TreeGrid() {
+ super();
+
+ // Attaches hierarchy data to the row
+ addDataGenerator((item, rowData) -> {
+
+ JsonObject hierarchyData = Json.createObject();
+ hierarchyData.put(TreeGridCommunicationConstants.ROW_DEPTH,
+ getDataProvider().getDepth(item));
+
+ boolean isLeaf = !getDataProvider().hasChildren(item);
+ if (isLeaf) {
+ hierarchyData.put(TreeGridCommunicationConstants.ROW_LEAF,
+ true);
+ } else {
+ hierarchyData.put(TreeGridCommunicationConstants.ROW_COLLAPSED,
+ getDataProvider().isCollapsed(item));
+ hierarchyData.put(TreeGridCommunicationConstants.ROW_LEAF,
+ false);
+ }
+
+ // add hierarchy information to row as metadata
+ rowData.put(
+ TreeGridCommunicationConstants.ROW_HIERARCHY_DESCRIPTION,
+ hierarchyData);
+ });
+
+ registerRpc(new NodeCollapseRpc() {
+ @Override
+ public void toggleCollapse(String rowKey) {
+ T item = getDataCommunicator().getKeyMapper().get(rowKey);
+ TreeGrid.this.toggleCollapse(item);
+ }
+ });
+ }
+
+ // TODO: construct a "flat" in memory hierarchical data provider?
+ @Override
+ public void setItems(Collection<T> items) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void setItems(Stream<T> items) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void setItems(T... items) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void setDataProvider(DataProvider<T, ?> dataProvider) {
+ if (!(dataProvider instanceof HierarchicalDataProvider)) {
+ throw new IllegalArgumentException(
+ "TreeGrid only accepts hierarchical data providers");
+ }
+ super.setDataProvider(dataProvider);
+ }
+
+ /**
+ * Set the column that displays the hierarchy of this grid's data. By
+ * default the hierarchy will be displayed in the first column.
+ * <p>
+ * Setting a hierarchy column by calling this method also sets the column to
+ * be visible and not hidable.
+ *
+ * @see Column#setId(String)
+ *
+ * @param id
+ * id of the column to use for displaying hierarchy
+ */
+ public void setHierarchyColumn(String id) {
+ Objects.requireNonNull(id, "id may not be null");
+ if (getColumn(id) == null) {
+ throw new IllegalArgumentException("No column found for given id");
+ }
+ getColumn(id).setHidden(false);
+ getColumn(id).setHidable(false);
+ getState().hierarchyColumnId = getInternalIdForColumn(getColumn(id));
+ }
+
+ @Override
+ protected TreeGridState getState() {
+ return (TreeGridState) super.getState();
+ }
+
+ @Override
+ protected TreeGridState getState(boolean markAsDirty) {
+ return (TreeGridState) super.getState(markAsDirty);
+ }
+
+ /**
+ * Toggle the expansion of an item in this grid. If the item is already
+ * expanded, it will be collapsed.
+ * <p>
+ * Toggling expansion on a leaf item in the hierarchy will have no effect.
+ *
+ * @param item
+ * the item to toggle expansion for
+ */
+ public void toggleCollapse(T item) {
+ getDataProvider().setCollapsed(item,
+ !getDataProvider().isCollapsed(item));
+ getDataCommunicator().reset();
+ }
+
+ @Override
+ public HierarchicalDataProvider<T, ?> getDataProvider() {
+ DataProvider<T, ?> dataProvider = super.getDataProvider();
+ // FIXME DataCommunicator by default has a CallbackDataProvider if no
+ // DataProvider is set, resulting in a class cast exception if we don't
+ // check it here.
+
+ // Once fixed, remove this method from the exclude list in
+ // StateGetDoesNotMarkDirtyTest
+ if (!(dataProvider instanceof HierarchicalDataProvider)) {
+ throw new IllegalStateException("No data provider has been set.");
+ }
+ return (HierarchicalDataProvider<T, ?>) dataProvider;
+ }
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java b/server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java
index 7a11cf4df6..3b4c2413f9 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java
@@ -31,6 +31,7 @@ public class StateGetDoesNotMarkDirtyTest {
excludedMethods.add("getConnectorId");
excludedMethods.add("getContent");
excludedMethods.add("com.vaadin.ui.Grid:getSelectAllCheckBoxVisible");
+ excludedMethods.add("com.vaadin.ui.TreeGrid:getDataProvider");
}
@Test