summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/main/java/com/vaadin/client/connectors/MultiSelectionModelConnector.java45
-rw-r--r--client/src/main/java/com/vaadin/client/connectors/SingleSelectionModelConnector.java36
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java4
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/selection/HasUserSelectionAllowed.java44
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java6
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelMulti.java13
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java13
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java4
-rwxr-xr-xclient/src/main/java/com/vaadin/client/widgets/Grid.java57
-rw-r--r--documentation/components/components-grid.asciidoc13
-rw-r--r--server/src/main/java/com/vaadin/ui/Grid.java127
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java41
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java13
-rw-r--r--server/src/test/java/com/vaadin/ui/ComponentTest.java119
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/grid/selection/MultiSelectionModelState.java1
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/grid/selection/SingleSelectionModelState.java1
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java30
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java157
18 files changed, 694 insertions, 30 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/MultiSelectionModelConnector.java b/client/src/main/java/com/vaadin/client/connectors/MultiSelectionModelConnector.java
index 748e9b1acf..5c0a84bd5f 100644
--- a/client/src/main/java/com/vaadin/client/connectors/MultiSelectionModelConnector.java
+++ b/client/src/main/java/com/vaadin/client/connectors/MultiSelectionModelConnector.java
@@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.logging.Logger;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.CheckBox;
@@ -35,12 +36,15 @@ import com.vaadin.client.widget.grid.DataAvailableEvent;
import com.vaadin.client.widget.grid.DataAvailableHandler;
import com.vaadin.client.widget.grid.events.SelectAllEvent;
import com.vaadin.client.widget.grid.events.SelectAllHandler;
+import com.vaadin.client.widget.grid.selection.HasUserSelectionAllowed;
import com.vaadin.client.widget.grid.selection.MultiSelectionRenderer;
import com.vaadin.client.widget.grid.selection.SelectionModel;
import com.vaadin.client.widget.grid.selection.SelectionModel.Multi;
import com.vaadin.client.widget.grid.selection.SpaceSelectHandler;
import com.vaadin.client.widgets.Grid;
+import com.vaadin.client.widgets.Grid.Column;
import com.vaadin.client.widgets.Grid.HeaderCell;
+import com.vaadin.client.widgets.Grid.SelectionColumn;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.grid.GridState;
import com.vaadin.shared.ui.grid.Range;
@@ -94,8 +98,30 @@ public class MultiSelectionModelConnector extends
}
}
+ @OnStateChange("userSelectionAllowed")
+ void updateUserSelectionAllowed() {
+ if (selectionModel instanceof HasUserSelectionAllowed) {
+ ((HasUserSelectionAllowed) selectionModel)
+ .setUserSelectionAllowed(getState().userSelectionAllowed);
+ } else {
+ getLogger().warning("userSelectionAllowed set to "
+ + getState().userSelectionAllowed
+ + " but the selection model does not implement "
+ + HasUserSelectionAllowed.class.getSimpleName());
+ }
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(MultiSelectionModelConnector.class.getName());
+ }
+
+ /**
+ * The default multi selection model used for this connector.
+ *
+ */
protected class MultiSelectionModel extends AbstractSelectionModel
- implements SelectionModel.Multi.Batched<JsonObject> {
+ implements SelectionModel.Multi.Batched<JsonObject>,
+ HasUserSelectionAllowed<JsonObject> {
private ComplexRenderer<Boolean> renderer = null;
private Set<RowHandle<JsonObject>> selected = new HashSet<RowHandle<JsonObject>>();
@@ -104,6 +130,7 @@ public class MultiSelectionModelConnector extends
private HandlerRegistration dataAvailable;
private Range availableRows;
private boolean batchSelect = false;
+ private boolean userSelectionAllowed = true;
@Override
public void setGrid(Grid<JsonObject> grid) {
@@ -382,5 +409,21 @@ public class MultiSelectionModelConnector extends
public Collection<JsonObject> getDeselectedRowsBatch() {
return Collections.unmodifiableSet(getRows(deselected));
}
+
+ @Override
+ public boolean isUserSelectionAllowed() {
+ return userSelectionAllowed;
+ }
+
+ @Override
+ public void setUserSelectionAllowed(boolean userSelectionAllowed) {
+ this.userSelectionAllowed = userSelectionAllowed;
+ for (Column<?, ?> c : getGrid().getColumns()) {
+ if (c instanceof SelectionColumn) {
+ ((SelectionColumn) c)
+ .setUserSelectionAllowed(userSelectionAllowed);
+ }
+ }
+ }
}
}
diff --git a/client/src/main/java/com/vaadin/client/connectors/SingleSelectionModelConnector.java b/client/src/main/java/com/vaadin/client/connectors/SingleSelectionModelConnector.java
index 55c1eddf61..7cd30e40ef 100644
--- a/client/src/main/java/com/vaadin/client/connectors/SingleSelectionModelConnector.java
+++ b/client/src/main/java/com/vaadin/client/connectors/SingleSelectionModelConnector.java
@@ -15,11 +15,14 @@
*/
package com.vaadin.client.connectors;
+import java.util.logging.Logger;
+
import com.vaadin.client.ServerConnector;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.data.DataSource.RowHandle;
import com.vaadin.client.renderers.Renderer;
import com.vaadin.client.widget.grid.selection.ClickSelectHandler;
+import com.vaadin.client.widget.grid.selection.HasUserSelectionAllowed;
import com.vaadin.client.widget.grid.selection.SelectionModel;
import com.vaadin.client.widget.grid.selection.SelectionModel.Single;
import com.vaadin.client.widget.grid.selection.SpaceSelectHandler;
@@ -75,14 +78,34 @@ public class SingleSelectionModelConnector extends
selectionModel.setDeselectAllowed(getState().deselectAllowed);
}
+ @OnStateChange("userSelectionAllowed")
+ void updateUserSelectionAllowed() {
+
+ if (selectionModel instanceof HasUserSelectionAllowed) {
+ ((HasUserSelectionAllowed) selectionModel)
+ .setUserSelectionAllowed(getState().userSelectionAllowed);
+ } else {
+ getLogger().warning("userSelectionAllowed set to "
+ + getState().userSelectionAllowed
+ + " but the selection model does not implement "
+ + HasUserSelectionAllowed.class.getSimpleName());
+ }
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(SingleSelectionModelConnector.class.getName());
+ }
+
/**
* SingleSelectionModel without a selection column renderer.
*/
public class SingleSelectionModel extends AbstractSelectionModel
- implements SelectionModel.Single<JsonObject> {
+ implements SelectionModel.Single<JsonObject>,
+ HasUserSelectionAllowed<JsonObject> {
private RowHandle<JsonObject> selectedRow;
private boolean deselectAllowed;
+ private boolean userSelectionAllowed = true;
@Override
public Renderer<Boolean> getSelectionColumnRenderer() {
@@ -182,5 +205,16 @@ public class SingleSelectionModelConnector extends
public boolean isDeselectAllowed() {
return deselectAllowed;
}
+
+ @Override
+ public boolean isUserSelectionAllowed() {
+ return userSelectionAllowed;
+ }
+
+ @Override
+ public void setUserSelectionAllowed(boolean userSelectionAllowed) {
+ this.userSelectionAllowed = userSelectionAllowed;
+ }
+
}
} \ No newline at end of file
diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java
index e7be08f141..7ace1eb4a4 100644
--- a/client/src/main/java/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java
+++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java
@@ -36,6 +36,10 @@ public class ClickSelectHandler<T> {
@Override
public void onClick(GridClickEvent event) {
+ if (!grid.isUserSelectionAllowed()) {
+ return;
+ }
+
T row = (T) event.getTargetCell().getRow();
if (!grid.isSelected(row)) {
grid.select(row);
diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/HasUserSelectionAllowed.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/HasUserSelectionAllowed.java
new file mode 100644
index 0000000000..de4eda36ca
--- /dev/null
+++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/HasUserSelectionAllowed.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2014 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.widget.grid.selection;
+
+/**
+ * Interface implemented by selection models which support disabling client side
+ * selection while still allowing programmatic selection on the server.
+ *
+ * @param <T>
+ * Grid's row type
+ */
+public interface HasUserSelectionAllowed<T> extends SelectionModel<T> {
+
+ /**
+ * Checks if the user is allowed to change the selection.
+ *
+ * @return <code>true</code> if the user is allowed to change the selection,
+ * <code>false</code> otherwise
+ */
+ public boolean isUserSelectionAllowed();
+
+ /**
+ * Sets whether the user is allowed to change the selection.
+ *
+ * @param userSelectionAllowed
+ * <code>true</code> if the user is allowed to change the
+ * selection, <code>false</code> otherwise
+ */
+ public void setUserSelectionAllowed(boolean userSelectionAllowed);
+
+}
diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
index b27a4a2eed..9c8f60c0cd 100644
--- a/client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
+++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
@@ -632,7 +632,8 @@ public class MultiSelectionRenderer<T>
public void render(final RendererCellReference cell, final Boolean data,
CheckBox checkBox) {
checkBox.setValue(data, false);
- checkBox.setEnabled(grid.isEnabled() && !grid.isEditorActive());
+ checkBox.setEnabled(grid.isEnabled() && !grid.isEditorActive()
+ && grid.isUserSelectionAllowed());
}
@Override
@@ -770,6 +771,9 @@ public class MultiSelectionRenderer<T>
}
protected void setSelected(final int logicalRow, final boolean select) {
+ if (!grid.isUserSelectionAllowed()) {
+ return;
+ }
T row = grid.getDataSource().getRow(logicalRow);
if (select) {
grid.select(row);
diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelMulti.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelMulti.java
index 00c115c5c2..7874e03006 100644
--- a/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelMulti.java
+++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelMulti.java
@@ -33,7 +33,7 @@ import com.vaadin.client.widgets.Grid;
* @since 7.4
*/
public class SelectionModelMulti<T> extends AbstractRowHandleSelectionModel<T>
- implements SelectionModel.Multi.Batched<T> {
+ implements SelectionModel.Multi.Batched<T>, HasUserSelectionAllowed<T> {
private final LinkedHashSet<RowHandle<T>> selectedRows;
private Renderer<Boolean> renderer;
@@ -45,6 +45,7 @@ public class SelectionModelMulti<T> extends AbstractRowHandleSelectionModel<T>
/* Event handling for selection with space key */
private SpaceSelectHandler<T> spaceSelectHandler;
+ private boolean userSelectionAllowed = true;
public SelectionModelMulti() {
grid = null;
@@ -270,4 +271,14 @@ public class SelectionModelMulti<T> extends AbstractRowHandleSelectionModel<T>
}
return rows;
}
+
+ @Override
+ public boolean isUserSelectionAllowed() {
+ return userSelectionAllowed;
+ }
+
+ @Override
+ public void setUserSelectionAllowed(boolean userSelectionAllowed) {
+ this.userSelectionAllowed = userSelectionAllowed;
+ }
}
diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java
index f3df892623..217682bcd1 100644
--- a/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java
+++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java
@@ -29,7 +29,7 @@ import com.vaadin.client.widgets.Grid;
* @since 7.4
*/
public class SelectionModelSingle<T> extends AbstractRowHandleSelectionModel<T>
- implements SelectionModel.Single<T> {
+ implements SelectionModel.Single<T>, HasUserSelectionAllowed<T> {
private Grid<T> grid;
private RowHandle<T> selectedRow;
@@ -41,6 +41,7 @@ public class SelectionModelSingle<T> extends AbstractRowHandleSelectionModel<T>
private ClickSelectHandler<T> clickSelectHandler;
private boolean deselectAllowed = true;
+ private boolean userSelectionAllowed = true;
@Override
public boolean isSelected(T row) {
@@ -172,4 +173,14 @@ public class SelectionModelSingle<T> extends AbstractRowHandleSelectionModel<T>
}
}
+ @Override
+ public boolean isUserSelectionAllowed() {
+ return userSelectionAllowed;
+ }
+
+ @Override
+ public void setUserSelectionAllowed(boolean userSelectionAllowed) {
+ this.userSelectionAllowed = userSelectionAllowed;
+ }
+
}
diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java
index 456f08c5b3..476f342838 100644
--- a/client/src/main/java/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java
+++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java
@@ -44,6 +44,10 @@ public class SpaceSelectHandler<T> {
@Override
public void onKeyDown(GridKeyDownEvent event) {
+ if (!grid.isUserSelectionAllowed()) {
+ return;
+ }
+
if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE || spaceDown) {
return;
}
diff --git a/client/src/main/java/com/vaadin/client/widgets/Grid.java b/client/src/main/java/com/vaadin/client/widgets/Grid.java
index f796529aa7..d215b3c565 100755
--- a/client/src/main/java/com/vaadin/client/widgets/Grid.java
+++ b/client/src/main/java/com/vaadin/client/widgets/Grid.java
@@ -158,6 +158,7 @@ import com.vaadin.client.widget.grid.events.ScrollHandler;
import com.vaadin.client.widget.grid.events.SelectAllEvent;
import com.vaadin.client.widget.grid.events.SelectAllHandler;
import com.vaadin.client.widget.grid.selection.HasSelectionHandlers;
+import com.vaadin.client.widget.grid.selection.HasUserSelectionAllowed;
import com.vaadin.client.widget.grid.selection.MultiSelectionRenderer;
import com.vaadin.client.widget.grid.selection.SelectionEvent;
import com.vaadin.client.widget.grid.selection.SelectionHandler;
@@ -1922,6 +1923,9 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
checkBox.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
+ if (!grid.isUserSelectionAllowed()) {
+ return;
+ }
T row = pinnedRowHandle.getRow();
if (grid.isSelected(row)) {
grid.deselect(row);
@@ -2885,6 +2889,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
private boolean initDone = false;
private boolean selected = false;
private CheckBox selectAllCheckBox;
+ private boolean userSelectionAllowed = true;
+ private boolean enabled = true;
SelectionColumn(final Renderer<Boolean> selectColumnRenderer) {
super(selectColumnRenderer);
@@ -2915,6 +2921,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
if (selectAllCheckBox == null) {
selectAllCheckBox = GWT.create(CheckBox.class);
+ selectAllCheckBox.setEnabled(enabled && userSelectionAllowed);
selectAllCheckBox.setStylePrimaryName(
getStylePrimaryName() + SELECT_ALL_CHECKBOX_CLASSNAME);
selectAllCheckBox.addValueChangeHandler(
@@ -2923,6 +2930,9 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
@Override
public void onValueChange(
ValueChangeEvent<Boolean> event) {
+ if (!isUserSelectionAllowed()) {
+ return;
+ }
if (event.getValue()) {
fireEvent(new SelectAllEvent<T>(model));
selected = true;
@@ -2937,6 +2947,10 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
addHeaderClickHandler(new HeaderClickHandler() {
@Override
public void onClick(GridClickEvent event) {
+ if (!userSelectionAllowed) {
+ return;
+ }
+
CellReference<?> targetCell = event.getTargetCell();
int defaultRowIndex = getHeader().getRows()
.indexOf(getDefaultHeaderRow());
@@ -2956,6 +2970,10 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE) {
return;
}
+ if (!isUserSelectionAllowed()) {
+ return;
+ }
+
HeaderRow targetHeaderRow = getHeader()
.getRow(event.getFocusedCell().getRowIndex());
if (!targetHeaderRow.isDefault()) {
@@ -3051,8 +3069,9 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
* to disable it.
*/
public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
if (selectAllCheckBox != null) {
- selectAllCheckBox.setEnabled(enabled);
+ selectAllCheckBox.setEnabled(enabled && userSelectionAllowed);
}
}
@@ -3060,6 +3079,26 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
public void onEnabled(boolean enabled) {
setEnabled(enabled);
}
+
+ /**
+ * Sets whether the user is allowed to change the selection.
+ *
+ * @param userSelectionAllowed
+ * <code>true</code> if the user is allowed to change the
+ * selection, <code>false</code> otherwise
+ */
+ public void setUserSelectionAllowed(boolean userSelectionAllowed) {
+ if (userSelectionAllowed == this.userSelectionAllowed) {
+ return;
+ }
+
+ this.userSelectionAllowed = userSelectionAllowed;
+ // Update checkbox state
+ setEnabled(enabled);
+ // Re-render select checkboxes
+ getEscalator().getBody().refreshRows(0,
+ getEscalator().getBody().getRowCount());
+ }
}
/**
@@ -9205,4 +9244,20 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
}
return null;
}
+
+ /**
+ * Checks if selection by the user is allowed in the grid.
+ *
+ * @return <code>true</code> if selection by the user is allowed by the
+ * selection model (the default), <code>false</code> otherwise
+ */
+ public boolean isUserSelectionAllowed() {
+ if (!(getSelectionModel() instanceof HasUserSelectionAllowed)) {
+ // Selection model does not support toggling user selection allowed
+ // - old default is to always allow selection
+ return true;
+ }
+ return ((HasUserSelectionAllowed) getSelectionModel())
+ .isUserSelectionAllowed();
+ }
}
diff --git a/documentation/components/components-grid.asciidoc b/documentation/components/components-grid.asciidoc
index 9b465a71b0..931c50ee2a 100644
--- a/documentation/components/components-grid.asciidoc
+++ b/documentation/components/components-grid.asciidoc
@@ -327,6 +327,19 @@ grid.addSelectionListener(selection -> { // Java 8
});
----
+[[components.grid.selection.disallowuser]]
+=== Disallowing User Selection
+It is possible to prevent the user from changing the selection in grid for both single- and multi-selection models:
+
+[source, java]
+----
+HasUserSelectionAllowed model = (HasUserSelectionAllowed) grid.getSelectionModel();
+model.setUserSelectionAllowed(false);
+----
+
+[NOTE]
+Both `SingleSelectionModel` and `MultiSelectModel` implement `HasUserSelectionAllowed` so the cast is generally safe.
+
[[components.grid.selection.clicks]]
=== Focus and Clicks
diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java
index 1efc091104..f96b485cc0 100644
--- a/server/src/main/java/com/vaadin/ui/Grid.java
+++ b/server/src/main/java/com/vaadin/ui/Grid.java
@@ -105,6 +105,7 @@ import com.vaadin.shared.ui.grid.selection.MultiSelectionModelState;
import com.vaadin.shared.ui.grid.selection.SingleSelectionModelServerRpc;
import com.vaadin.shared.ui.grid.selection.SingleSelectionModelState;
import com.vaadin.shared.util.SharedUtil;
+import com.vaadin.ui.Grid.SelectionModel.HasUserSelectionAllowed;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignException;
@@ -569,11 +570,10 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
}
- private void bindFields(List<Field<?>> fields,
- Item itemDataSource) {
+ private void bindFields(List<Field<?>> fields, Item itemDataSource) {
for (Field<?> field : fields) {
- if (itemDataSource.getItemProperty(getPropertyId(field))
- != null) {
+ if (itemDataSource
+ .getItemProperty(getPropertyId(field)) != null) {
bind(field, getPropertyId(field));
}
}
@@ -1105,6 +1105,34 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
* SelectionModel should extend {@link AbstractGridExtension}.
*/
public interface SelectionModel extends Serializable, Extension {
+
+ /**
+ * Interface implemented by selection models which support disabling
+ * client side selection while still allowing programmatic selection on
+ * the server.
+ *
+ */
+ public interface HasUserSelectionAllowed extends SelectionModel {
+
+ /**
+ * Checks if the user is allowed to change the selection.
+ *
+ * @return <code>true</code> if the user is allowed to change the
+ * selection, <code>false</code> otherwise
+ */
+ public boolean isUserSelectionAllowed();
+
+ /**
+ * Sets whether the user is allowed to change the selection.
+ *
+ * @param userSelectionAllowed
+ * <code>true</code> if the user is allowed to change the
+ * selection, <code>false</code> otherwise
+ */
+ public void setUserSelectionAllowed(boolean userSelectionAllowed);
+
+ }
+
/**
* Checks whether an item is selected or not.
*
@@ -1464,7 +1492,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
* A default implementation of a {@link SelectionModel.Single}
*/
public static class SingleSelectionModel extends AbstractSelectionModel
- implements SelectionModel.Single {
+ implements SelectionModel.Single, HasUserSelectionAllowed {
@Override
protected void extend(AbstractClientConnector target) {
@@ -1473,6 +1501,11 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public void select(String rowKey) {
+ if (!isUserSelectionAllowed()) {
+ throw new IllegalStateException(
+ "Client tried to select '" + rowKey
+ + "' although user selection is disallowed");
+ }
SingleSelectionModel.this.select(getItemId(rowKey), false);
}
});
@@ -1563,6 +1596,21 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
protected SingleSelectionModelState getState() {
return (SingleSelectionModelState) super.getState();
}
+
+ @Override
+ protected SingleSelectionModelState getState(boolean markAsDirty) {
+ return (SingleSelectionModelState) super.getState(markAsDirty);
+ }
+
+ @Override
+ public boolean isUserSelectionAllowed() {
+ return getState(false).userSelectionAllowed;
+ }
+
+ @Override
+ public void setUserSelectionAllowed(boolean userSelectionAllowed) {
+ getState().userSelectionAllowed = userSelectionAllowed;
+ }
}
/**
@@ -1590,13 +1638,15 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
public void reset() {
// NOOP
}
+
}
/**
* A default implementation of a {@link SelectionModel.Multi}
*/
public static class MultiSelectionModel extends AbstractSelectionModel
- implements SelectionModel.Multi {
+ implements SelectionModel.Multi,
+ SelectionModel.HasUserSelectionAllowed {
/**
* The default selection size limit.
@@ -1614,6 +1664,12 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public void select(List<String> rowKeys) {
+ if (!isUserSelectionAllowed()) {
+ throw new IllegalStateException(
+ "Client tried to select '" + rowKeys
+ + "' although user selection is disallowed");
+ }
+
List<Object> items = new ArrayList<Object>();
for (String rowKey : rowKeys) {
items.add(getItemId(rowKey));
@@ -1623,6 +1679,12 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public void deselect(List<String> rowKeys) {
+ if (!isUserSelectionAllowed()) {
+ throw new IllegalStateException(
+ "Client tried to deselect '" + rowKeys
+ + "' although user selection is disallowed");
+ }
+
List<Object> items = new ArrayList<Object>();
for (String rowKey : rowKeys) {
items.add(getItemId(rowKey));
@@ -1632,11 +1694,21 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public void selectAll() {
+ if (!isUserSelectionAllowed()) {
+ throw new IllegalStateException(
+ "Client tried to select all although user selection is disallowed");
+ }
+
MultiSelectionModel.this.selectAll(false);
}
@Override
public void deselectAll() {
+ if (!isUserSelectionAllowed()) {
+ throw new IllegalStateException(
+ "Client tried to deselect all although user selection is disallowed");
+ }
+
MultiSelectionModel.this.deselectAll(false);
}
});
@@ -1920,6 +1992,21 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
protected MultiSelectionModelState getState() {
return (MultiSelectionModelState) super.getState();
}
+
+ @Override
+ protected MultiSelectionModelState getState(boolean markAsDirty) {
+ return (MultiSelectionModelState) super.getState(markAsDirty);
+ }
+
+ @Override
+ public boolean isUserSelectionAllowed() {
+ return getState(false).userSelectionAllowed;
+ }
+
+ @Override
+ public void setUserSelectionAllowed(boolean userSelectionAllowed) {
+ getState().userSelectionAllowed = userSelectionAllowed;
+ }
}
/**
@@ -2228,8 +2315,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
Item item = cell.getItem();
Property itemProperty = item.getItemProperty(cell.getPropertyId());
- Object modelValue =
- itemProperty == null ? null : itemProperty.getValue();
+ Object modelValue = itemProperty == null ? null
+ : itemProperty.getValue();
data.put(columnKeys.key(cell.getPropertyId()), AbstractRenderer
.encodeValue(modelValue, renderer, converter, getLocale()));
@@ -4563,8 +4650,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
private FieldGroup editorFieldGroup = new CustomFieldGroup();
/**
- * Poperty ID to Field mapping that stores editor fields set by {@link
- * #setEditorField(Object, Field)}.
+ * Poperty ID to Field mapping that stores editor fields set by
+ * {@link #setEditorField(Object, Field)}.
*/
private Map<Object, Field<?>> editorFields = new HashMap<Object, Field<?>>();
@@ -5271,10 +5358,12 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
/**
- * Sets the column resize mode to use. The default mode is {@link ColumnResizeMode#ANIMATED}.
+ * Sets the column resize mode to use. The default mode is
+ * {@link ColumnResizeMode#ANIMATED}.
*
- * @param mode a ColumnResizeMode value
-
+ * @param mode
+ * a ColumnResizeMode value
+ *
* @since 7.7.5
*/
public void setColumnResizeMode(ColumnResizeMode mode) {
@@ -5282,7 +5371,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
/**
- * Returns the current column resize mode. The default mode is {@link ColumnResizeMode#ANIMATED}.
+ * Returns the current column resize mode. The default mode is
+ * {@link ColumnResizeMode#ANIMATED}.
*
* @return a ColumnResizeMode value
*
@@ -6873,7 +6963,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
Field<?> editor = editorFieldGroup.getField(propertyId);
- // If field group has no field for this property, see if we have it stored
+ // If field group has no field for this property, see if we have it
+ // stored
if (editor == null) {
editor = editorFields.get(propertyId);
if (editor != null) {
@@ -6937,9 +7028,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
editorFieldGroup.setItemDataSource(item);
for (Column column : getColumns()) {
- column.getState().editorConnector =
- item.getItemProperty(column.getPropertyId()) == null
- ? null : getEditorField(column.getPropertyId());
+ column.getState().editorConnector = item
+ .getItemProperty(column.getPropertyId()) == null ? null
+ : getEditorField(column.getPropertyId());
}
editorActive = true;
diff --git a/server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java b/server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java
index f07c740b6c..49856dffa9 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java
@@ -17,6 +17,7 @@ package com.vaadin.tests.server.component.grid;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import org.junit.After;
@@ -28,8 +29,11 @@ import com.vaadin.data.Container;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.SelectionEvent;
import com.vaadin.event.SelectionEvent.SelectionListener;
+import com.vaadin.shared.ui.grid.selection.MultiSelectionModelServerRpc;
import com.vaadin.shared.ui.grid.selection.MultiSelectionModelState;
+import com.vaadin.ui.ComponentTest;
import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionModel.HasUserSelectionAllowed;
public class MultiSelectionModelTest {
@@ -187,4 +191,41 @@ public class MultiSelectionModelTest {
}
Assert.fail("Not all items were correctly selected");
}
+
+ @Test(expected = IllegalStateException.class)
+ public void refuseSelectWhenUserSelectionDisallowed() {
+ ((HasUserSelectionAllowed) grid.getSelectionModel())
+ .setUserSelectionAllowed(false);
+ MultiSelectionModelServerRpc serverRpc = ComponentTest.getRpcProxy(
+ grid.getSelectionModel(), MultiSelectionModelServerRpc.class);
+ serverRpc.select(Collections.singletonList("a"));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void refuseDeselectWhenUserSelectionDisallowed() {
+ ((HasUserSelectionAllowed) grid.getSelectionModel())
+ .setUserSelectionAllowed(false);
+ MultiSelectionModelServerRpc serverRpc = ComponentTest.getRpcProxy(
+ grid.getSelectionModel(), MultiSelectionModelServerRpc.class);
+ serverRpc.deselect(Collections.singletonList("a"));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void refuseSelectAllWhenUserSelectionDisallowed() {
+ ((HasUserSelectionAllowed) grid.getSelectionModel())
+ .setUserSelectionAllowed(false);
+ MultiSelectionModelServerRpc serverRpc = ComponentTest.getRpcProxy(
+ grid.getSelectionModel(), MultiSelectionModelServerRpc.class);
+ serverRpc.selectAll();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void refuseDeselectAllWhenUserSelectionDisallowed() {
+ ((HasUserSelectionAllowed) grid.getSelectionModel())
+ .setUserSelectionAllowed(false);
+ MultiSelectionModelServerRpc serverRpc = ComponentTest.getRpcProxy(
+ grid.getSelectionModel(), MultiSelectionModelServerRpc.class);
+ serverRpc.deselectAll();
+ }
+
}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java b/server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java
index 8b66ab625d..e3331cd0be 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java
@@ -24,8 +24,11 @@ import com.vaadin.data.Container;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.SelectionEvent;
import com.vaadin.event.SelectionEvent.SelectionListener;
+import com.vaadin.shared.ui.grid.selection.SingleSelectionModelServerRpc;
+import com.vaadin.ui.ComponentTest;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.Grid.SelectionModel.HasUserSelectionAllowed;
import com.vaadin.ui.Grid.SingleSelectionModel;
public class SingleSelectionModelTest {
@@ -150,4 +153,14 @@ public class SingleSelectionModelTest {
}
});
}
+
+ @Test(expected = IllegalStateException.class)
+ public void refuseSelectionWhenUserSelectionDisallowed() {
+ ((HasUserSelectionAllowed) grid.getSelectionModel())
+ .setUserSelectionAllowed(false);
+ SingleSelectionModelServerRpc serverRpc = ComponentTest.getRpcProxy(
+ grid.getSelectionModel(), SingleSelectionModelServerRpc.class);
+ serverRpc.select("a");
+ }
+
}
diff --git a/server/src/test/java/com/vaadin/ui/ComponentTest.java b/server/src/test/java/com/vaadin/ui/ComponentTest.java
new file mode 100644
index 0000000000..7077f8b22e
--- /dev/null
+++ b/server/src/test/java/com/vaadin/ui/ComponentTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.junit.Assert;
+
+import com.vaadin.server.ClientConnector;
+import com.vaadin.server.ServerRpcManager;
+import com.vaadin.shared.communication.ServerRpc;
+
+import elemental.json.JsonObject;
+
+/**
+ * Base class for component unit tests, providing helper methods for e.g.
+ * invoking RPC and updating diff state.
+ */
+public class ComponentTest {
+
+ /**
+ * Perform operations on the component similar to what would be done when
+ * the component state is communicated to the client, e.g. update diff state
+ * and mark as clean.
+ *
+ * @param component
+ * the component to update
+ */
+ public static void syncToClient(AbstractComponent component) {
+ updateDiffState(component);
+ component.getUI().getConnectorTracker().markClean(component);
+ }
+
+ /**
+ * Checks if the connector has been marked dirty.
+ *
+ * @param connector
+ * the connector to check
+ * @return <code>true</code> if the connector has been marked dirty,
+ * <code>false</code> otherwise
+ */
+ public static boolean isDirty(ClientConnector connector) {
+ return connector.getUI().getConnectorTracker().isDirty(connector);
+ }
+
+ /**
+ * Updates the stored diff state from the current component state.
+ *
+ * @param rta
+ * the component to update
+ */
+ public static void updateDiffState(AbstractComponent component) {
+ component.getUI().getSession().getCommunicationManager()
+ .encodeState(component, component.getState());
+
+ }
+
+ /**
+ * Gets the server rpc handler registered for a component.
+ *
+ * @param connector
+ * the connector which listens to the RPC
+ * @param serverRpcClass
+ * the server RPC class
+ * @return the server RPC handler
+ */
+ public static <T extends ServerRpc> T getRpcProxy(ClientConnector connector,
+ Class<T> serverRpcClass) {
+ try {
+ ServerRpcManager<?> rpcManager = connector
+ .getRpcManager(serverRpcClass.getName());
+ Method method = ServerRpcManager.class
+ .getDeclaredMethod("getImplementation");
+ method.setAccessible(true);
+ return serverRpcClass.cast(method.invoke(rpcManager));
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Asserts the set of properties that would be sent as state changes for the
+ * given connector.
+ *
+ * @param connector
+ * the connector that has state changes
+ * @param message
+ * the message to show if the properties are not as expected
+ * @param expectedProperties
+ * names of the expected properties
+ */
+ public static void assertEncodedStateProperties(ClientConnector connector,
+ String message, String... expectedProperties) {
+ assert connector.isAttached();
+
+ JsonObject encodeState = connector.encodeState();
+
+ // Collect to HashSet so that order doesn't matter
+ Assert.assertEquals(message,
+ new HashSet<String>(Arrays.asList(expectedProperties)),
+ new HashSet<String>(Arrays.asList(encodeState.keys())));
+ }
+
+} \ No newline at end of file
diff --git a/shared/src/main/java/com/vaadin/shared/ui/grid/selection/MultiSelectionModelState.java b/shared/src/main/java/com/vaadin/shared/ui/grid/selection/MultiSelectionModelState.java
index 35da1d1e0b..3fd685c98e 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/grid/selection/MultiSelectionModelState.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/grid/selection/MultiSelectionModelState.java
@@ -27,5 +27,6 @@ public class MultiSelectionModelState extends SharedState {
/* Select All -checkbox status */
public boolean allSelected;
+ public boolean userSelectionAllowed = true;
}
diff --git a/shared/src/main/java/com/vaadin/shared/ui/grid/selection/SingleSelectionModelState.java b/shared/src/main/java/com/vaadin/shared/ui/grid/selection/SingleSelectionModelState.java
index de06dfc61a..6355ddec7e 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/grid/selection/SingleSelectionModelState.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/grid/selection/SingleSelectionModelState.java
@@ -27,4 +27,5 @@ public class SingleSelectionModelState extends SharedState {
/* Allow deselecting rows */
public boolean deselectAllowed = true;
+ public boolean userSelectionAllowed = true;
}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
index e3fdd68ed6..6f1986720b 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
@@ -75,6 +75,7 @@ import com.vaadin.ui.Grid.RowReference;
import com.vaadin.ui.Grid.RowStyleGenerator;
import com.vaadin.ui.Grid.SelectionMode;
import com.vaadin.ui.Grid.SelectionModel;
+import com.vaadin.ui.Grid.SelectionModel.HasUserSelectionAllowed;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
@@ -108,6 +109,7 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
private int containerDelay = 0;
private boolean singleSelectAllowDeselect = true;
+ private boolean allowUserSelection = true;
private IndexedContainer ds;
private Grid grid;
@@ -509,6 +511,9 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
} else {
grid.removeSelectionListener(selectionListener);
}
+
+ ((HasUserSelectionAllowed) grid.getSelectionModel())
+ .setUserSelectionAllowed(allowUserSelection);
}
});
@@ -804,6 +809,17 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
}
});
+ createBooleanAction("Allow user selection", "State", allowUserSelection,
+ new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ allowUserSelection = value.booleanValue();
+
+ SelectionModel model = c.getSelectionModel();
+ ((HasUserSelectionAllowed) model)
+ .setUserSelectionAllowed(allowUserSelection);
+ }
+ });
createBooleanAction("Column Reordering Allowed", "State", false,
new Command<Grid, Boolean>() {
@@ -1268,12 +1284,14 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
}, null);
- createBooleanAction("Simple resize mode", "Columns", false, new Command<Grid, Boolean>() {
- @Override
- public void execute(Grid g, Boolean value, Object data) {
- g.setColumnResizeMode(value ? ColumnResizeMode.SIMPLE : ColumnResizeMode.ANIMATED);
- }
- });
+ createBooleanAction("Simple resize mode", "Columns", false,
+ new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid g, Boolean value, Object data) {
+ g.setColumnResizeMode(value ? ColumnResizeMode.SIMPLE
+ : ColumnResizeMode.ANIMATED);
+ }
+ });
}
private static String getColumnProperty(int c) {
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
index 642514393e..b185d52c5b 100644
--- a/uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
@@ -483,6 +483,10 @@ public class GridSelectionTest extends GridBasicFeaturesTest {
selectMenuPath("Component", "Body rows", "Select first row");
}
+ private void toggleUserSelectionAllowed() {
+ selectMenuPath("Component", "State", "Allow user selection");
+ }
+
private GridRowElement getRow(int i) {
return getGridElement().getRow(i);
}
@@ -526,4 +530,157 @@ public class GridSelectionTest extends GridBasicFeaturesTest {
getGridElement().getCell(0, 0).click();
assertTrue("row should become selected", getRow(0).isSelected());
}
+
+ @Test
+ public void singleSelectUserSelectionDisallowedSpaceSelectionNoOp() {
+ openTestURL();
+ setSelectionModelSingle();
+ getGridElement().focus();
+ getGridElement().sendKeys(Keys.DOWN, Keys.SPACE);
+ assertTrue("row was selected when selection was allowed",
+ getRow(1).isSelected());
+ toggleUserSelectionAllowed();
+ getGridElement().sendKeys(Keys.SPACE);
+ assertTrue("deselect disallowed", getRow(1).isSelected());
+ getGridElement().sendKeys(Keys.DOWN, Keys.SPACE);
+ assertFalse("select disallowed", getRow(2).isSelected());
+ assertTrue("old selection remains", getRow(1).isSelected());
+ toggleUserSelectionAllowed();
+ getGridElement().sendKeys(Keys.SPACE);
+ assertTrue("select allowed again", getRow(2).isSelected());
+ assertFalse("old selection removed", getRow(1).isSelected());
+
+ }
+
+ @Test
+ public void singleSelectUserSelectionDisallowedClickSelectionNoOp() {
+ openTestURL();
+ setSelectionModelSingle();
+ getGridElement().getCell(1, 0).click();
+ assertTrue("selection allowed, should have been selected",
+ getRow(1).isSelected());
+ toggleUserSelectionAllowed();
+ getGridElement().getCell(1, 0).click();
+ assertTrue("deselect disallowed, should remain selected",
+ getRow(1).isSelected());
+ getGridElement().getCell(2, 0).click();
+ assertFalse("select disallowed, should not have been selected",
+ getRow(2).isSelected());
+ assertTrue("select disallowed, old selection should have remained",
+ getRow(1).isSelected());
+ toggleUserSelectionAllowed();
+ getGridElement().getCell(2, 0).click();
+ assertTrue("select allowed again, row should have been selected",
+ getRow(2).isSelected());
+ assertFalse("old selection removed", getRow(1).isSelected());
+
+ }
+
+ @Test
+ public void multiSelectUserSelectionDisallowedSpaceSelectionNoOp() {
+ openTestURL();
+ setSelectionModelMulti();
+ getGridElement().focus();
+ getGridElement().sendKeys(Keys.DOWN, Keys.SPACE);
+ assertTrue("selection allowed, should have been selected",
+ getRow(1).isSelected());
+ toggleUserSelectionAllowed();
+ getGridElement().sendKeys(Keys.SPACE);
+ assertTrue("deselect disallowed, should remain selected",
+ getRow(1).isSelected());
+ getGridElement().sendKeys(Keys.DOWN, Keys.SPACE);
+ assertFalse("select disallowed, should not have been selected",
+ getRow(2).isSelected());
+ assertTrue("select disallowed, old selection should have remained",
+ getRow(1).isSelected());
+
+ toggleUserSelectionAllowed();
+ getGridElement().sendKeys(Keys.SPACE);
+ assertTrue("select allowed again, row should have been selected",
+ getRow(2).isSelected());
+ assertTrue(
+ "select allowed again but old selection should have remained",
+ getRow(1).isSelected());
+ }
+
+ @Test
+ public void multiSelectUserSelectionDisallowedCheckboxSelectionNoOp() {
+ openTestURL();
+ setSelectionModelMulti();
+ assertTrue(getSelectionCheckbox(0).isEnabled());
+ toggleUserSelectionAllowed();
+ assertFalse(getSelectionCheckbox(0).isEnabled());
+
+ // Select by clicking on checkbox (should always fail as it is disabled)
+ getSelectionCheckbox(0).click();
+ assertFalse(getGridElement().getRow(0).isSelected());
+ // Select by clicking on cell (should fail)
+ getGridElement().getCell(0, 0).click();
+ assertFalse(getGridElement().getRow(0).isSelected());
+
+ toggleUserSelectionAllowed();
+ assertTrue(getSelectionCheckbox(0).isEnabled());
+ getSelectionCheckbox(0).click();
+ assertTrue(getGridElement().getRow(0).isSelected());
+ }
+
+ @Test
+ public void multiSelectUserSelectionDisallowedCheckboxSelectAllNoOp() {
+ openTestURL();
+ setSelectionModelMulti();
+
+ assertTrue(getSelectAllCheckbox().isEnabled());
+ toggleUserSelectionAllowed();
+ assertFalse(getSelectAllCheckbox().isEnabled());
+
+ // Select all by clicking on checkbox (should not select)
+ getSelectAllCheckbox().click();
+ assertFalse(getSelectAllCheckbox().isSelected());
+ assertFalse(getGridElement().getRow(0).isSelected());
+ assertFalse(getGridElement().getRow(10).isSelected());
+
+ // Select all by clicking on header cell (should not select)
+ getGridElement().getHeaderCell(0, 0).click();
+ assertFalse(getSelectAllCheckbox().isSelected());
+ assertFalse(getGridElement().getRow(0).isSelected());
+ assertFalse(getGridElement().getRow(10).isSelected());
+
+ toggleUserSelectionAllowed();
+
+ assertTrue(getSelectAllCheckbox().isEnabled());
+ getSelectAllCheckbox().click();
+ assertTrue(getGridElement().getRow(0).isSelected());
+ assertTrue(getGridElement().getRow(10).isSelected());
+ }
+
+ @Test
+ public void singleSelectUserSelectionDisallowedServerSelect() {
+ openTestURL();
+ setSelectionModelSingle();
+ toggleUserSelectionAllowed();
+
+ toggleFirstRowSelection();
+ assertTrue(getGridElement().getRow(0).isSelected());
+ }
+
+ @Test
+ public void multiSelectUserSelectionDisallowedServerSelect() {
+ openTestURL();
+ setSelectionModelMulti();
+ toggleUserSelectionAllowed();
+
+ toggleFirstRowSelection();
+ assertTrue(getGridElement().getRow(0).isSelected());
+ }
+
+ private WebElement getSelectAllCheckbox() {
+ return getGridElement().getHeaderCell(0, 0)
+ .findElement(By.tagName("input"));
+ }
+
+ private WebElement getSelectionCheckbox(int row) {
+ return getGridElement().getCell(row, 0)
+ .findElement(By.tagName("input"));
+ }
+
}