diff options
-rw-r--r-- | server/src/main/java/com/vaadin/data/TreeData.java | 83 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java | 45 |
2 files changed, 128 insertions, 0 deletions
diff --git a/server/src/main/java/com/vaadin/data/TreeData.java b/server/src/main/java/com/vaadin/data/TreeData.java index b0bdcde835..bebf312614 100644 --- a/server/src/main/java/com/vaadin/data/TreeData.java +++ b/server/src/main/java/com/vaadin/data/TreeData.java @@ -368,6 +368,89 @@ public class TreeData<T> implements Serializable { } /** + * Moves an item to become a child of the given parent item. The new parent + * item must exist in the hierarchy. Setting the parent to {@code null} + * makes the item a root item. After making changes to the tree data, {@link + * TreeDataProvider#refreshAll()} should be called. + * + * @param item + * the item to be set as the child of {@code parent} + * @param parent + * the item to be set as parent or {@code null} to set the item as + * root + * @since 8.1 + */ + public void setParent(T item, T parent) { + if (!contains(item)) { + throw new IllegalArgumentException( + "Item '" + item + "' not in the hierarchy"); + } + + if (parent != null && !contains(parent)) { + throw new IllegalArgumentException( + "Parent needs to be added before children. " + + "To set as root item, call with parent as null"); + } + + if (item.equals(parent)) { + throw new IllegalArgumentException( + "Item cannot be the parent of itself"); + } + + T oldParent = itemToWrapperMap.get(item).getParent(); + + if (!Objects.equals(oldParent, parent)) { + // Remove item from old parent's children + itemToWrapperMap.get(oldParent).removeChild(item); + + // Add item to parent's children + itemToWrapperMap.get(parent).addChild(item); + + // Set item's new parent + itemToWrapperMap.get(item).setParent(parent); + } + } + + /** + * Moves an item to the position immediately after a sibling item. The two + * items must have the same parent. After making changes to the tree data, + * {@link TreeDataProvider#refreshAll()} should be called. + * + * @param item + * the item to be moved + * @param sibling + * the item after which the moved item will be located + * @since 8.1 + */ + public void moveAfterSibling(T item, T sibling) { + if (!contains(item)) { + throw new IllegalArgumentException( + "Item '" + item + "' not in the hierarchy"); + } + + if (!contains(sibling)) { + throw new IllegalArgumentException( + "Item '" + sibling + "' not in the hierarchy"); + } + + T parent = itemToWrapperMap.get(item).getParent(); + + if (!Objects + .equals(parent, itemToWrapperMap.get(sibling).getParent())) { + throw new IllegalArgumentException( + "Items '" + item + "' and '" + sibling + + "' don't have the same parent"); + } + + List<T> children = itemToWrapperMap.get(parent).getChildren(); + + // Move item to the position after the sibling + // If sibling is null, item is moved to the first position + children.remove(item); + children.add(children.indexOf(sibling) + 1, item); + } + + /** * Check whether the given item is in this hierarchy. * * @param item diff --git a/server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java b/server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java index 186ed14e8a..8232d2fc45 100644 --- a/server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java +++ b/server/src/test/java/com/vaadin/data/provider/TreeDataProviderTest.java @@ -81,6 +81,51 @@ public class TreeDataProviderTest } @Test + public void treeData_set_parent() { + StrBean item1 = rootData.get(0); + StrBean item2 = rootData.get(1); + Assert.assertEquals(0, data.getChildren(item2).size()); + Assert.assertEquals(10, data.getRootItems().size()); + + // Move item1 as item2's child + data.setParent(item1, item2); + Assert.assertEquals(1, data.getChildren(item2).size()); + Assert.assertEquals(9, data.getRootItems().size()); + Assert.assertEquals(item1, data.getChildren(item2).get(0)); + + // Move back to root + data.setParent(item1, null); + Assert.assertEquals(0, data.getChildren(item2).size()); + Assert.assertEquals(10, data.getRootItems().size()); + } + + @Test + public void treeData_move_after_sibling() { + StrBean root0 = rootData.get(0); + StrBean root9 = rootData.get(9); + Assert.assertEquals(root0, data.getRootItems().get(0)); + Assert.assertEquals(root9, data.getRootItems().get(9)); + + // Move to last position + data.moveAfterSibling(root0, root9); + Assert.assertEquals(root0, data.getRootItems().get(9)); + Assert.assertEquals(root9, data.getRootItems().get(8)); + + // Move back to first position + data.moveAfterSibling(root0, null); + Assert.assertEquals(root0, data.getRootItems().get(0)); + Assert.assertEquals(root9, data.getRootItems().get(9)); + } + + @Test(expected = IllegalArgumentException.class) + public void treeData_move_after_sibling_different_parents() { + StrBean root0 = rootData.get(0); + StrBean wrongSibling = data.getChildren(root0).get(0); + + data.moveAfterSibling(root0, wrongSibling); + } + + @Test public void treeData_root_items() { TreeData<String> data = new TreeData<>(); TreeData<String> dataVarargs = new TreeData<>(); |