summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/com/vaadin/client/connectors/GridConnector.java14
-rw-r--r--client/src/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java14
-rw-r--r--client/src/com/vaadin/client/widget/grid/selection/SelectionModel.java20
-rw-r--r--client/src/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java24
-rw-r--r--client/src/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java19
-rw-r--r--server/src/com/vaadin/ui/Grid.java30
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridState.java3
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java20
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java130
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java35
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java10
11 files changed, 311 insertions, 8 deletions
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java
index f8aa044a8d..f263b47642 100644
--- a/client/src/com/vaadin/client/connectors/GridConnector.java
+++ b/client/src/com/vaadin/client/connectors/GridConnector.java
@@ -57,6 +57,7 @@ import com.vaadin.client.widget.grid.events.SelectAllHandler;
import com.vaadin.client.widget.grid.selection.AbstractRowHandleSelectionModel;
import com.vaadin.client.widget.grid.selection.SelectionEvent;
import com.vaadin.client.widget.grid.selection.SelectionHandler;
+import com.vaadin.client.widget.grid.selection.SelectionModel;
import com.vaadin.client.widget.grid.selection.SelectionModelMulti;
import com.vaadin.client.widget.grid.selection.SelectionModelNone;
import com.vaadin.client.widget.grid.selection.SelectionModelSingle;
@@ -536,7 +537,12 @@ public class GridConnector extends AbstractHasComponentsConnector implements
// Selection
if (stateChangeEvent.hasPropertyChanged("selectionMode")) {
onSelectionModeChange();
+ updateSelectDeselectAllowed();
+ } else if (stateChangeEvent
+ .hasPropertyChanged("singleSelectDeselectAllowed")) {
+ updateSelectDeselectAllowed();
}
+
if (stateChangeEvent.hasPropertyChanged("selectedKeys")) {
updateSelectionFromState();
}
@@ -567,6 +573,14 @@ public class GridConnector extends AbstractHasComponentsConnector implements
}
}
+ private void updateSelectDeselectAllowed() {
+ SelectionModel<JsonObject> model = getWidget().getSelectionModel();
+ if (model instanceof SelectionModel.Single<?>) {
+ ((SelectionModel.Single<?>) model)
+ .setDeselectAllowed(getState().singleSelectDeselectAllowed);
+ }
+ }
+
private void updateColumnOrderFromState(List<String> stateColumnOrder) {
CustomGridColumn[] columns = new CustomGridColumn[stateColumnOrder
.size()];
diff --git a/client/src/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java b/client/src/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java
index 0a1154e787..c6bc52dd1c 100644
--- a/client/src/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java
+++ b/client/src/com/vaadin/client/widget/grid/selection/ClickSelectHandler.java
@@ -30,6 +30,7 @@ public class ClickSelectHandler<T> {
private Grid<T> grid;
private HandlerRegistration clickHandler;
+ private boolean deselectAllowed = true;
private class RowClickHandler implements BodyClickHandler {
@@ -38,6 +39,8 @@ public class ClickSelectHandler<T> {
T row = (T) event.getTargetCell().getRow();
if (!grid.isSelected(row)) {
grid.select(row);
+ } else if (deselectAllowed) {
+ grid.deselect(row);
}
}
}
@@ -60,4 +63,15 @@ public class ClickSelectHandler<T> {
public void removeHandler() {
clickHandler.removeHandler();
}
+
+ /**
+ * Sets whether clicking the currently selected row should deselect the row.
+ *
+ * @param deselectAllowed
+ * <code>true</code> to allow deselecting the selected row;
+ * otherwise <code>false</code>
+ */
+ public void setDeselectAllowed(boolean deselectAllowed) {
+ this.deselectAllowed = deselectAllowed;
+ }
}
diff --git a/client/src/com/vaadin/client/widget/grid/selection/SelectionModel.java b/client/src/com/vaadin/client/widget/grid/selection/SelectionModel.java
index 37f6fb48c3..ec36ab52e8 100644
--- a/client/src/com/vaadin/client/widget/grid/selection/SelectionModel.java
+++ b/client/src/com/vaadin/client/widget/grid/selection/SelectionModel.java
@@ -116,6 +116,26 @@ public interface SelectionModel<T> {
*/
public T getSelectedRow();
+ /**
+ * 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);
+
+ /**
+ * Sets 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/client/src/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java b/client/src/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java
index 20eb3c1e63..38605db12c 100644
--- a/client/src/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java
+++ b/client/src/com/vaadin/client/widget/grid/selection/SelectionModelSingle.java
@@ -40,6 +40,8 @@ public class SelectionModelSingle<T> extends AbstractRowHandleSelectionModel<T>
/** Event handling for selection by clicking cells */
private ClickSelectHandler<T> clickSelectHandler;
+ private boolean deselectAllowed = true;
+
@Override
public boolean isSelected(T row) {
return selectedRow != null
@@ -66,6 +68,7 @@ public class SelectionModelSingle<T> extends AbstractRowHandleSelectionModel<T>
if (this.grid != null) {
spaceSelectHandler = new SpaceSelectHandler<T>(grid);
clickSelectHandler = new ClickSelectHandler<T>(grid);
+ updateHandlerDeselectAllowed();
} else {
spaceSelectHandler.removeHandler();
clickSelectHandler.removeHandler();
@@ -148,4 +151,25 @@ public class SelectionModelSingle<T> extends AbstractRowHandleSelectionModel<T>
return false;
}
}
+
+ @Override
+ public void setDeselectAllowed(boolean deselectAllowed) {
+ this.deselectAllowed = deselectAllowed;
+ updateHandlerDeselectAllowed();
+ }
+
+ @Override
+ public boolean isDeselectAllowed() {
+ return deselectAllowed;
+ }
+
+ private void updateHandlerDeselectAllowed() {
+ if (spaceSelectHandler != null) {
+ spaceSelectHandler.setDeselectAllowed(deselectAllowed);
+ }
+ if (clickSelectHandler != null) {
+ clickSelectHandler.setDeselectAllowed(deselectAllowed);
+ }
+ }
+
}
diff --git a/client/src/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java b/client/src/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java
index 7a1bf2dc06..3e04a6dfac 100644
--- a/client/src/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java
+++ b/client/src/com/vaadin/client/widget/grid/selection/SpaceSelectHandler.java
@@ -79,10 +79,10 @@ public class SpaceSelectHandler<T> {
protected void setSelected(Grid<T> grid, int rowIndex) {
T row = grid.getDataSource().getRow(rowIndex);
- if (grid.isSelected(row)) {
- grid.deselect(row);
- } else {
+ if (!grid.isSelected(row)) {
grid.select(row);
+ } else if (deselectAllowed) {
+ grid.deselect(row);
}
}
}
@@ -91,6 +91,7 @@ public class SpaceSelectHandler<T> {
private Grid<T> grid;
private HandlerRegistration spaceUpHandler;
private HandlerRegistration spaceDownHandler;
+ private boolean deselectAllowed = true;
/**
* Constructor for SpaceSelectHandler. This constructor will add all
@@ -121,4 +122,16 @@ public class SpaceSelectHandler<T> {
spaceDownHandler.removeHandler();
spaceUpHandler.removeHandler();
}
+
+ /**
+ * Sets whether pressing space for the currently selected row should
+ * deselect the row.
+ *
+ * @param deselectAllowed
+ * <code>true</code> to allow deselecting the selected row;
+ * otherwise <code>false</code>
+ */
+ public void setDeselectAllowed(boolean deselectAllowed) {
+ this.deselectAllowed = deselectAllowed;
+ }
} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index 150f672835..bbae501782 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -641,6 +641,26 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
* <code>null</code> if nothing is selected
*/
Object getSelectedRow();
+
+ /**
+ * 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);
+
+ /**
+ * Sets 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();
}
/**
@@ -814,6 +834,16 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
public void reset() {
deselect(getSelectedRow());
}
+
+ @Override
+ public void setDeselectAllowed(boolean deselectAllowed) {
+ grid.getState().singleSelectDeselectAllowed = deselectAllowed;
+ }
+
+ @Override
+ public boolean isDeselectAllowed() {
+ return grid.getState(false).singleSelectDeselectAllowed;
+ }
}
/**
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridState.java b/shared/src/com/vaadin/shared/ui/grid/GridState.java
index 9d94a2cb8e..7018df1413 100644
--- a/shared/src/com/vaadin/shared/ui/grid/GridState.java
+++ b/shared/src/com/vaadin/shared/ui/grid/GridState.java
@@ -132,6 +132,9 @@ public class GridState extends AbstractComponentState {
public SharedSelectionMode selectionMode;
+ /** Whether single select mode can be cleared through the UI */
+ public boolean singleSelectDeselectAllowed = true;
+
/** Keys of the currently sorted columns */
public String[] sortColumns = new String[0];
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
index fe4a31d9e7..0c335f58b2 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
@@ -57,6 +57,7 @@ import com.vaadin.ui.Grid.MultiSelectionModel;
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.renderer.DateRenderer;
import com.vaadin.ui.renderer.HtmlRenderer;
import com.vaadin.ui.renderer.NumberRenderer;
@@ -82,6 +83,8 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
private int containerDelay = 0;
+ private boolean singleSelectAllowDeselect = true;
+
private IndexedContainer ds;
private Grid grid;
private SelectionListener selectionListener = new SelectionListener() {
@@ -320,6 +323,9 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
grid.setSelectionMode(selectionMode);
if (selectionMode == SelectionMode.SINGLE) {
grid.addSelectionListener(selectionListener);
+
+ ((SelectionModel.Single) grid.getSelectionModel())
+ .setDeselectAllowed(singleSelectAllowDeselect);
} else {
grid.removeSelectionListener(selectionListener);
}
@@ -488,6 +494,20 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
});
+
+ createBooleanAction("Single select allow deselect", "State",
+ singleSelectAllowDeselect, new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ singleSelectAllowDeselect = value.booleanValue();
+
+ SelectionModel model = c.getSelectionModel();
+ if (model instanceof SelectionModel.Single) {
+ ((SelectionModel.Single) model)
+ .setDeselectAllowed(singleSelectAllowDeselect);
+ }
+ }
+ });
}
protected void createHeaderActions() {
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java
index d4c10da626..dccf2c0974 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java
@@ -19,6 +19,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
import com.vaadin.testbench.By;
import com.vaadin.testbench.elements.GridElement.GridCellElement;
@@ -74,7 +76,7 @@ public class GridClientSelectionTest extends GridBasicClientFeaturesTest {
assertTrue("Multi Selection Model should have select all checkbox",
header.isElementPresent(By.tagName("input")));
- setSelectionModelSingle();
+ setSelectionModelSingle(true);
header = getGridElement().getHeaderCell(0, 0);
assertFalse(
"Check box shouldn't have been in header for Single Selection Model",
@@ -88,15 +90,133 @@ public class GridClientSelectionTest extends GridBasicClientFeaturesTest {
}
+ @Test
+ public void testDeselectAllowedMouseInput() {
+ openTestURL();
+
+ setSelectionModelSingle(true);
+
+ getGridElement().getCell(5, 1).click();
+
+ assertTrue("Row 5 should be selected after clicking", isRowSelected(5));
+
+ getGridElement().getCell(7, 1).click();
+
+ assertFalse("Row 5 should be deselected after clicking another row",
+ isRowSelected(5));
+ assertTrue("Row 7 should be selected after clicking", isRowSelected(7));
+
+ getGridElement().getCell(7, 1).click();
+
+ assertFalse("Row should be deselected after clicking again",
+ isRowSelected(7));
+ }
+
+ @Test
+ public void testDeselectAllowedKeyboardInput() {
+ openTestURL();
+
+ setSelectionModelSingle(true);
+
+ getGridElement().getHeaderCell(0, 1).click();
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform();
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Row 0 should be selected after pressing space",
+ isRowSelected(0));
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform();
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertFalse(
+ "Row 0 should be deselected after pressing space another row",
+ isRowSelected(0));
+ assertTrue("Row 1 should be selected after pressing space",
+ isRowSelected(1));
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertFalse("Row should be deselected after pressing space again",
+ isRowSelected(1));
+ }
+
+ @Test
+ public void testDeselectNotAllowedMouseInput() {
+ openTestURL();
+
+ setSelectionModelSingle(false);
+
+ getGridElement().getCell(5, 1).click();
+
+ assertTrue("Row 5 should be selected after clicking", isRowSelected(5));
+
+ getGridElement().getCell(7, 1).click();
+
+ assertFalse("Row 5 should be deselected after clicking another row",
+ isRowSelected(5));
+ assertTrue("Row 7 should be selected after clicking", isRowSelected(7));
+
+ getGridElement().getCell(7, 1).click();
+
+ assertTrue("Row should remain selected after clicking again",
+ isRowSelected(7));
+ }
+
+ @Test
+ public void testDeselectNotAllowedKeyboardInput() {
+ openTestURL();
+
+ setSelectionModelSingle(false);
+
+ getGridElement().getHeaderCell(0, 1).click();
+ new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform();
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Row 0 should be selected after pressing space",
+ isRowSelected(0));
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform();
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertFalse(
+ "Row 0 should be deselected after pressing space another row",
+ isRowSelected(0));
+ assertTrue("Row 1 should be selected after pressing space",
+ isRowSelected(1));
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Row should remain selected after pressing space again",
+ isRowSelected(1));
+ }
+
+ private boolean isRowSelected(int index) {
+ boolean selected = getGridElement().getRow(index).isSelected();
+ return selected;
+ }
+
private void setSelectionModelMulti() {
- selectMenuPath("Component", "State", "Selection mode", "multi");
+ setSelectionModel("multi");
}
- private void setSelectionModelSingle() {
- selectMenuPath("Component", "State", "Selection mode", "single");
+ private void setSelectionModelSingle(boolean deselectAllowed) {
+ String mode = "single";
+ if (!deselectAllowed) {
+ mode += " (no deselect)";
+ }
+ setSelectionModel(mode);
}
private void setSelectionModelNone() {
- selectMenuPath("Component", "State", "Selection mode", "none");
+ setSelectionModel("none");
+ }
+
+ private void setSelectionModel(String model) {
+ selectMenuPath("Component", "State", "Selection mode", model);
}
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
index 3dbf613ba0..b4eb473d4b 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
@@ -270,6 +270,41 @@ public class GridSelectionTest extends GridBasicFeaturesTest {
}
+ @Test
+ public void testToggleDeselectAllowed() {
+ openTestURL();
+
+ setSelectionModelSingle();
+ // Deselect allowed already enabled
+
+ getGridElement().getCell(5, 1).click();
+ getGridElement().getCell(5, 1).click();
+ assertFalse("Row should be not selected after two clicks", getRow(5)
+ .isSelected());
+
+ selectMenuPath("Component", "State", "Single select allow deselect");
+ getGridElement().getCell(5, 1).click();
+ getGridElement().getCell(5, 1).click();
+ assertTrue("Row should be selected after two clicks", getRow(5)
+ .isSelected());
+
+ selectMenuPath("Component", "State", "Single select allow deselect");
+ getGridElement().getCell(5, 1).click();
+ assertFalse("Row should be not selected after another click", getRow(5)
+ .isSelected());
+
+ // Also verify that state is updated together with the model
+ setSelectionModelNone();
+ selectMenuPath("Component", "State", "Single select allow deselect");
+ setSelectionModelSingle();
+
+ getGridElement().getCell(5, 1).click();
+ getGridElement().getCell(5, 1).click();
+
+ assertTrue("Row should stay selected after two clicks", getRow(5)
+ .isSelected());
+ }
+
private void setSelectionModelMulti() {
selectMenuPath("Component", "State", "Selection mode", "multi");
}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java
index 232a3a780e..0452aa65d1 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java
@@ -66,6 +66,7 @@ import com.vaadin.client.widget.grid.events.HeaderKeyPressHandler;
import com.vaadin.client.widget.grid.events.HeaderKeyUpHandler;
import com.vaadin.client.widget.grid.events.ScrollEvent;
import com.vaadin.client.widget.grid.events.ScrollHandler;
+import com.vaadin.client.widget.grid.selection.SelectionModel;
import com.vaadin.client.widget.grid.selection.SelectionModel.None;
import com.vaadin.client.widgets.Grid;
import com.vaadin.client.widgets.Grid.Column;
@@ -468,6 +469,15 @@ public class GridBasicClientFeaturesWidget extends
}
}, selectionModePath);
+ addMenuCommand("single (no deselect)", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ ((SelectionModel.Single<?>) grid.getSelectionModel())
+ .setDeselectAllowed(false);
+ }
+ }, selectionModePath);
+
addMenuCommand("none", new ScheduledCommand() {
@Override
public void execute() {