diff options
9 files changed, 225 insertions, 22 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/AbstractSelectionModelConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/AbstractSelectionModelConnector.java index 114bc313d6..2210317c7c 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/AbstractSelectionModelConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/AbstractSelectionModelConnector.java @@ -19,6 +19,7 @@ import com.vaadin.client.ServerConnector; import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.extensions.AbstractExtensionConnector; import com.vaadin.client.widget.grid.selection.SelectionModel; +import com.vaadin.client.widget.grid.selection.SpaceSelectHandler; import com.vaadin.client.widgets.Grid; import com.vaadin.shared.ui.grid.AbstractSelectionModelState; @@ -34,9 +35,24 @@ import elemental.json.JsonObject; public abstract class AbstractSelectionModelConnector extends AbstractExtensionConnector { + private SpaceSelectHandler<JsonObject> spaceSelectHandler; + @Override protected void extend(ServerConnector target) { initSelectionModel(); + + // Default selection style is space key. + spaceSelectHandler = new SpaceSelectHandler<>(getGrid()); + } + + @Override + public void onUnregister() { + super.onUnregister(); + + if (spaceSelectHandler != null) { + spaceSelectHandler.removeHandler(); + spaceSelectHandler = null; + } } /** @@ -62,6 +78,15 @@ public abstract class AbstractSelectionModelConnector return getParent().getWidget(); } + /** + * Gets space selection handler registered for the Grid. + * + * @return space selection handler + */ + protected SpaceSelectHandler<JsonObject> getSpaceSelectionHandler() { + return spaceSelectHandler; + } + @OnStateChange("selectionAllowed") private void onSelectionAllowedChange() { getGrid().getSelectionModel() diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java index 828c795777..2e48e3a64a 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java @@ -47,8 +47,6 @@ import com.vaadin.client.widget.grid.events.BodyClickHandler; import com.vaadin.client.widget.grid.events.BodyDoubleClickHandler; import com.vaadin.client.widget.grid.events.GridClickEvent; import com.vaadin.client.widget.grid.events.GridDoubleClickEvent; -import com.vaadin.client.widget.grid.selection.ClickSelectHandler; -import com.vaadin.client.widget.grid.selection.SpaceSelectHandler; import com.vaadin.client.widget.grid.sort.SortEvent; import com.vaadin.client.widget.grid.sort.SortOrder; import com.vaadin.client.widgets.Grid; @@ -111,8 +109,6 @@ public class GridConnector extends AbstractListingConnector /* Child component list for HasComponentsConnector */ private List<ComponentConnector> childComponents; - private SpaceSelectHandler<JsonObject> spaceSelectHandler; - private ClickSelectHandler<JsonObject> clickSelectHandler; private ItemClickHandler itemClickHandler = new ItemClickHandler(); /** @@ -147,8 +143,6 @@ public class GridConnector extends AbstractListingConnector protected void init() { super.init(); - // Default selection style is space key. - spaceSelectHandler = new SpaceSelectHandler<>(getWidget()); getWidget().addSortHandler(this::handleSortEvent); getWidget().setRowStyleGenerator(rowRef -> { JsonObject json = rowRef.getRow(); @@ -344,12 +338,6 @@ public class GridConnector extends AbstractListingConnector super.onUnregister(); columnToIdMap.clear(); - removeClickHandler(); - - if (spaceSelectHandler != null) { - spaceSelectHandler.removeHandler(); - spaceSelectHandler = null; - } } @Override @@ -415,13 +403,6 @@ public class GridConnector extends AbstractListingConnector return (GridState) super.getState(); } - private void removeClickHandler() { - if (clickSelectHandler != null) { - clickSelectHandler.removeHandler(); - clickSelectHandler = null; - } - } - @Override public boolean hasTooltip() { // Always check for generated descriptions. diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/SingleSelectionModelConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/SingleSelectionModelConnector.java index 9b1d7cc27a..560ccb2d85 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/SingleSelectionModelConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/SingleSelectionModelConnector.java @@ -15,12 +15,14 @@ */ package com.vaadin.client.connectors.grid; +import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.widget.grid.events.GridSelectionAllowedEvent; import com.vaadin.client.widget.grid.selection.ClickSelectHandler; import com.vaadin.client.widget.grid.selection.SelectionModel; import com.vaadin.shared.data.DataCommunicatorConstants; import com.vaadin.shared.data.selection.SelectionServerRpc; import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.grid.SingleSelectionModelState; import elemental.json.JsonObject; @@ -44,6 +46,8 @@ public class SingleSelectionModelConnector private boolean isSelectionAllowed = true; + private boolean deselectAllowed = true; + @Override public void select(JsonObject item) { getRpcProxy(SelectionServerRpc.class) @@ -77,6 +81,39 @@ public class SingleSelectionModelConnector public boolean isSelectionAllowed() { return isSelectionAllowed; } + + /** + * Sets whether it's allowed to deselect the selected row through the + * UI. Deselection is allowed by default. + * + * @param deselectAllowed + * <code>true</code> if the selected row can be deselected + * without selecting another row instead; otherwise + * <code>false</code>. + */ + public void setDeselectAllowed(boolean deselectAllowed) { + this.deselectAllowed = deselectAllowed; + updateHandlerDeselectAllowed(); + } + + /** + * Gets whether it's allowed to deselect the selected row through the + * UI. + * + * @return <code>true</code> if deselection is allowed; otherwise + * <code>false</code> + */ + public boolean isDeselectAllowed() { + return deselectAllowed; + } + + private void updateHandlerDeselectAllowed() { + if (clickSelectHandler != null) { + clickSelectHandler.setDeselectAllowed(deselectAllowed); + } + getSpaceSelectionHandler().setDeselectAllowed(deselectAllowed); + } + } @Override @@ -94,4 +131,18 @@ public class SingleSelectionModelConnector } } + @Override + public SingleSelectionModelState getState() { + return (SingleSelectionModelState) super.getState(); + } + + @OnStateChange("deselectAllowed") + private void updateDeselectAllowed() { + getSelectionModel().setDeselectAllowed(getState().deselectAllowed); + } + + private SingleSelectionModel getSelectionModel() { + return (SingleSelectionModel) getGrid().getSelectionModel(); + } + } diff --git a/server/src/main/java/com/vaadin/data/SelectionModel.java b/server/src/main/java/com/vaadin/data/SelectionModel.java index 29c32c7698..397e2a1557 100644 --- a/server/src/main/java/com/vaadin/data/SelectionModel.java +++ b/server/src/main/java/com/vaadin/data/SelectionModel.java @@ -103,6 +103,26 @@ public interface SelectionModel<T> extends Serializable { default Optional<T> getFirstSelectedItem() { return getSelectedItem(); } + + /** + * Sets whether it's allowed to deselect the selected row through the + * UI. Deselection is allowed by default. + * + * @param deselectAllowed + * <code>true</code> if the selected row can be deselected + * without selecting another row instead; otherwise + * <code>false</code>. + */ + public void setDeselectAllowed(boolean deselectAllowed); + + /** + * Gets whether it's allowed to deselect the selected row through the + * UI. + * + * @return <code>true</code> if deselection is allowed; otherwise + * <code>false</code> + */ + public boolean isDeselectAllowed(); } /** diff --git a/server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java b/server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java index 4b3eb2d41c..42ca337e65 100644 --- a/server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java +++ b/server/src/main/java/com/vaadin/ui/components/grid/SingleSelectionModelImpl.java @@ -217,6 +217,16 @@ public class SingleSelectionModelImpl<T> extends AbstractSelectionModel<T> } } + @Override + public void setDeselectAllowed(boolean deselectAllowed) { + getState().deselectAllowed = deselectAllowed; + } + + @Override + public boolean isDeselectAllowed() { + return getState().deselectAllowed; + } + private boolean isUserSelectionAllowed() { return getState(false).selectionAllowed; } diff --git a/shared/src/main/java/com/vaadin/shared/ui/grid/SingleSelectionModelState.java b/shared/src/main/java/com/vaadin/shared/ui/grid/SingleSelectionModelState.java index 2ad1a30a3d..6fd1b09cd7 100644 --- a/shared/src/main/java/com/vaadin/shared/ui/grid/SingleSelectionModelState.java +++ b/shared/src/main/java/com/vaadin/shared/ui/grid/SingleSelectionModelState.java @@ -23,4 +23,7 @@ package com.vaadin.shared.ui.grid; * @since 8.0 */ public class SingleSelectionModelState extends AbstractSelectionModelState { + + /* Allow deselecting rows */ + public boolean deselectAllowed = true; } diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/DisallowedDeselection.java b/uitest/src/main/java/com/vaadin/tests/components/grid/DisallowedDeselection.java new file mode 100644 index 0000000000..fc2357c346 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/DisallowedDeselection.java @@ -0,0 +1,51 @@ +/* + * 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.tests.components.grid; + +import com.vaadin.data.ValueProvider; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.SelectionMode; +import com.vaadin.ui.components.grid.GridSelectionModel; +import com.vaadin.ui.components.grid.SingleSelectionModelImpl; + +/** + * @author Vaadin Ltd + * + */ +public class DisallowedDeselection extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Grid<String> grid = new Grid<>(); + grid.addColumn(ValueProvider.identity()); + grid.setItems("a", "b"); + + GridSelectionModel<String> model = grid + .setSelectionMode(SelectionMode.SINGLE); + SingleSelectionModelImpl<?> singleSelectionModel = (SingleSelectionModelImpl<?>) model; + singleSelectionModel.setDeselectAllowed(false); + addComponent(grid); + + Button allowDeselection = new Button("Allow deselection", + event -> singleSelectionModel.setDeselectAllowed(true)); + + addComponent(allowDeselection); + } + +} diff --git a/uitest/src/main/java/com/vaadin/tests/widgetset/client/grid/MySelectionModelConnector.java b/uitest/src/main/java/com/vaadin/tests/widgetset/client/grid/MySelectionModelConnector.java index 78851dd7ef..24f9aff2ad 100644 --- a/uitest/src/main/java/com/vaadin/tests/widgetset/client/grid/MySelectionModelConnector.java +++ b/uitest/src/main/java/com/vaadin/tests/widgetset/client/grid/MySelectionModelConnector.java @@ -15,7 +15,6 @@ */ package com.vaadin.tests.widgetset.client.grid; -import com.vaadin.client.ServerConnector; import com.vaadin.client.connectors.grid.MultiSelectionModelConnector; import com.vaadin.client.renderers.Renderer; import com.vaadin.client.widget.grid.selection.ClickSelectHandler; @@ -36,9 +35,10 @@ public class MySelectionModelConnector extends MultiSelectionModelConnector { private ClickSelectHandler<JsonObject> handler; @Override - protected void extend(ServerConnector target) { - handler = new ClickSelectHandler<>(getGrid()); + protected void initSelectionModel() { + super.initSelectionModel(); getGrid().setSelectionModel(new MyMultiSelectionModel()); + handler = new ClickSelectHandler<>(getGrid()); } @Override diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/DisallowedDeselectionTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/DisallowedDeselectionTest.java new file mode 100644 index 0000000000..85d202d50d --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/grid/DisallowedDeselectionTest.java @@ -0,0 +1,62 @@ +/* + * 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.tests.components.grid; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.GridElement; +import com.vaadin.testbench.elements.GridElement.GridRowElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * @author Vaadin Ltd + * + */ +public class DisallowedDeselectionTest extends MultiBrowserTest { + + @Test + public void checkDeselection() { + openTestURL(); + + GridRowElement row = $(GridElement.class).first().getRow(0); + Assert.assertFalse(row.isSelected()); + + select(row); + Assert.assertTrue(row.isSelected()); + + // deselection is disallowed + select(row); + Assert.assertTrue(row.isSelected()); + + // select another row + GridRowElement oldRow = row; + row = $(GridElement.class).first().getRow(1); + select(row); + Assert.assertTrue(row.isSelected()); + Assert.assertFalse(oldRow.isSelected()); + + $(ButtonElement.class).first().click(); + + select(row); + Assert.assertFalse(row.isSelected()); + } + + private void select(GridRowElement row) { + row.getCell(0).click(); + } +} |