diff options
author | Teemu Suo-Anttila <tsuoanttila@users.noreply.github.com> | 2017-05-23 12:54:26 +0300 |
---|---|---|
committer | Aleksi Hietanen <aleksi@vaadin.com> | 2017-05-23 12:54:26 +0300 |
commit | 6b6dc9306a749e24f498507d0eddce10b5c6cbf5 (patch) | |
tree | a4be32a24c55a67d7c6c6682f15397273807ca7a | |
parent | e746334d6444bb16c099f31480919b9020a69bc7 (diff) | |
download | vaadin-framework-6b6dc9306a749e24f498507d0eddce10b5c6cbf5.tar.gz vaadin-framework-6b6dc9306a749e24f498507d0eddce10b5c6cbf5.zip |
Add MultiSelection support for Tree Component (#9354)
6 files changed, 214 insertions, 3 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/MultiSelectionModelConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/MultiSelectionModelConnector.java index 83008b5a88..92b858cb97 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/MultiSelectionModelConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/MultiSelectionModelConnector.java @@ -125,12 +125,24 @@ public class MultiSelectionModelConnector @Override protected void initSelectionModel() { - getGrid().setSelectionModel(new MultiSelectionModel()); + getGrid().setSelectionModel(createSelectionModel()); // capture current rows so that can show selection update immediately dataAvailable = getGrid().addDataAvailableHandler( event -> availableRows = event.getAvailableRows()); } + /** + * Creates an instance of MultiSelectionModel. Method provided overriding + * features of the selection model without copying all logic. + * + * @since 8.1 + * + * @return selection model instance, not {@code null} + */ + protected MultiSelectionModel createSelectionModel() { + return new MultiSelectionModel(); + } + @Override public void onUnregister() { super.onUnregister(); diff --git a/client/src/main/java/com/vaadin/client/connectors/tree/TreeMultiSelectionModelConnector.java b/client/src/main/java/com/vaadin/client/connectors/tree/TreeMultiSelectionModelConnector.java new file mode 100644 index 0000000000..bcb3a66faa --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/tree/TreeMultiSelectionModelConnector.java @@ -0,0 +1,71 @@ +/* + * 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.client.connectors.tree; + +import com.vaadin.client.connectors.grid.MultiSelectionModelConnector; +import com.vaadin.client.renderers.Renderer; +import com.vaadin.client.widget.grid.selection.ClickSelectHandler; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.tree.TreeMultiSelectionModelState; +import com.vaadin.ui.Tree.TreeMultiSelectionModel; + +import elemental.json.JsonObject; + +/** + * Connector for the server side multiselection model of the tree component. + * <p> + * Implementation detail: The selection is updated immediately on client side, + * without waiting for the server response. + * + * @author Vaadin Ltd + * @since 8.1 + */ +@Connect(TreeMultiSelectionModel.class) +public class TreeMultiSelectionModelConnector + extends MultiSelectionModelConnector { + + private ClickSelectHandler<JsonObject> clickSelectHandler; + + @Override + protected MultiSelectionModel createSelectionModel() { + return new MultiSelectionModel() { + @Override + public Renderer<Boolean> getRenderer() { + // Prevent selection column. + return null; + } + }; + } + + @Override + public TreeMultiSelectionModelState getState() { + return (TreeMultiSelectionModelState) super.getState(); + } + + @Override + protected void initSelectionModel() { + super.initSelectionModel(); + clickSelectHandler = new ClickSelectHandler<>(getParent().getWidget()); + } + + @Override + public void onUnregister() { + super.onUnregister(); + if (clickSelectHandler != null) { + clickSelectHandler.removeHandler(); + } + } +} diff --git a/server/src/main/java/com/vaadin/ui/Tree.java b/server/src/main/java/com/vaadin/ui/Tree.java index c89d0796bc..998c61cf18 100644 --- a/server/src/main/java/com/vaadin/ui/Tree.java +++ b/server/src/main/java/com/vaadin/ui/Tree.java @@ -43,8 +43,10 @@ import com.vaadin.server.Resource; import com.vaadin.shared.Registration; import com.vaadin.shared.ui.ContentMode; import com.vaadin.shared.ui.grid.HeightMode; +import com.vaadin.shared.ui.tree.TreeMultiSelectionModelState; import com.vaadin.shared.ui.tree.TreeRendererState; import com.vaadin.ui.Grid.SelectionMode; +import com.vaadin.ui.components.grid.MultiSelectionModelImpl; import com.vaadin.ui.renderers.AbstractRenderer; import com.vaadin.util.ReflectTools; @@ -190,6 +192,29 @@ public class Tree<T> extends Composite } } + /** + * Custom MultiSelectionModel for Tree. TreeMultiSelectionModel does not + * show selection column. + * + * @param <T> + * the tree item type + * + * @since 8.1 + */ + public final static class TreeMultiSelectionModel<T> + extends MultiSelectionModelImpl<T> { + + @Override + protected TreeMultiSelectionModelState getState() { + return (TreeMultiSelectionModelState) super.getState(); + } + + @Override + protected TreeMultiSelectionModelState getState(boolean markAsDirty) { + return (TreeMultiSelectionModelState) super.getState(markAsDirty); + } + } + private TreeGrid<T> treeGrid = new TreeGrid<>(); private ItemCaptionGenerator<T> captionGenerator = String::valueOf; private IconGenerator<T> iconProvider = t -> null; @@ -551,7 +576,7 @@ public class Tree<T> extends Composite /** * Gets the item collapse allowed provider. - * + * * @return the item collapse allowed provider */ public ItemCollapseAllowedProvider<T> getItemCollapseAllowedProvider() { @@ -560,7 +585,7 @@ public class Tree<T> extends Composite /** * Gets the style generator. - * + * * @see StyleGenerator * * @return the item style generator @@ -582,6 +607,35 @@ public class Tree<T> extends Composite } /** + * Sets the tree's selection mode. + * <p> + * The built-in selection modes are: + * <ul> + * <li>{@link SelectionMode#SINGLE} <b>the default model</b></li> + * <li>{@link SelectionMode#MULTI}</li> + * <li>{@link SelectionMode#NONE} preventing selection</li> + * </ul> + * + * @param selectionMode + * the selection mode to switch to, not {@code null} + * @return the used selection model + * + * @see SelectionMode + */ + public SelectionModel<T> setSelectionMode(SelectionMode selectionMode) { + 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); + } + } + + /** * @deprecated This component's height is always set to be undefined. * Calling this method will have no effect. */ diff --git a/shared/src/main/java/com/vaadin/shared/ui/tree/TreeMultiSelectionModelState.java b/shared/src/main/java/com/vaadin/shared/ui/tree/TreeMultiSelectionModelState.java new file mode 100644 index 0000000000..dca676b5b2 --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/tree/TreeMultiSelectionModelState.java @@ -0,0 +1,27 @@ +/* + * 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.shared.ui.tree; + +import com.vaadin.shared.ui.grid.MultiSelectionModelState; + +/** + * State for TreeMultiSelectionModel. + * + * @author Vaadin Ltd + * @since 8.1 + */ +public class TreeMultiSelectionModelState extends MultiSelectionModelState { +} diff --git a/uitest/src/main/java/com/vaadin/tests/components/tree/TreeBasicFeatures.java b/uitest/src/main/java/com/vaadin/tests/components/tree/TreeBasicFeatures.java index a579c98a12..9f69f3d760 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/tree/TreeBasicFeatures.java +++ b/uitest/src/main/java/com/vaadin/tests/components/tree/TreeBasicFeatures.java @@ -21,6 +21,7 @@ import com.vaadin.ui.MenuBar.Command; import com.vaadin.ui.MenuBar.MenuItem; import com.vaadin.ui.Tree; import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Grid.SelectionMode; @Theme("tests-valo-disabled-animations") @Widgetset("com.vaadin.DefaultWidgetSet") @@ -68,6 +69,7 @@ public class TreeBasicFeatures extends AbstractTestUIWithLog { MenuItem componentMenu = menu.addItem("Component", null); createIconMenu(componentMenu.addItem("Icons", null)); createCaptionMenu(componentMenu.addItem("Captions", null)); + createSelectionModeMenu(componentMenu.addItem("Selection Mode", null)); componentMenu.addItem("Item Click Listener", new Command() { private Registration registration; @@ -108,6 +110,12 @@ public class TreeBasicFeatures extends AbstractTestUIWithLog { return menu; } + private void createSelectionModeMenu(MenuItem modeMenu) { + for (SelectionMode mode : SelectionMode.values()) { + modeMenu.addItem(mode.name(), item -> tree.setSelectionMode(mode)); + } + } + private void createCaptionMenu(MenuItem captionMenu) { captionMenu.addItem("String.valueOf", menu -> tree.setItemCaptionGenerator(String::valueOf)); diff --git a/uitest/src/test/java/com/vaadin/tests/components/tree/TreeBasicFeaturesTest.java b/uitest/src/test/java/com/vaadin/tests/components/tree/TreeBasicFeaturesTest.java index 8d95bf5ef6..bde38a963a 100644 --- a/uitest/src/test/java/com/vaadin/tests/components/tree/TreeBasicFeaturesTest.java +++ b/uitest/src/test/java/com/vaadin/tests/components/tree/TreeBasicFeaturesTest.java @@ -7,6 +7,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; import com.vaadin.testbench.TestBenchElement; import com.vaadin.testbench.elements.TreeElement; @@ -164,4 +166,41 @@ public class TreeBasicFeaturesTest extends MultiBrowserTest { Assert.assertEquals("Tree should prevent collapsing all nodes.", "2 | 0", tree.getItem(2).getText()); } + + @Test + public void tree_multiselect() { + selectMenuPath("Component", "Selection Mode", "MULTI"); + TreeElement tree = $(TreeElement.class).first(); + tree.getItem(0).click(); + TreeGridElement wrap = tree.wrap(TreeGridElement.class); + Assert.assertFalse( + "Tree MultiSelection shouldn't have selection column", + wrap.getCell(0, 0).isElementPresent(By.tagName("input"))); + Assert.assertTrue("First row was not selected", + wrap.getRow(0).isSelected()); + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN, Keys.SPACE) + .perform(); + Assert.assertTrue("First row was deselected", + wrap.getRow(0).isSelected()); + Assert.assertTrue("Second row was not selected", + wrap.getRow(1).isSelected()); + } + + @Test + public void tree_multiselect_click() { + selectMenuPath("Component", "Selection Mode", "MULTI"); + TreeElement tree = $(TreeElement.class).first(); + TreeGridElement wrap = tree.wrap(TreeGridElement.class); + tree.getItem(0).click(); + Assert.assertTrue("First row was not selected", + wrap.getRow(0).isSelected()); + tree.getItem(1).click(); + Assert.assertTrue("First row was deselected", + wrap.getRow(0).isSelected()); + Assert.assertTrue("Second row was not selected", + wrap.getRow(1).isSelected()); + tree.getItem(0).click(); + Assert.assertFalse("First row was not deselected", + wrap.getRow(0).isSelected()); + } } |