aboutsummaryrefslogtreecommitdiffstats
path: root/server/src
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <tsuoanttila@users.noreply.github.com>2018-09-04 15:45:08 +0300
committerIlia Motornyi <elmot@vaadin.com>2018-09-04 15:45:08 +0300
commit5a24c4865519be892b33a412e26326bc58f9cf0a (patch)
treeffc54b48b2c78a63ec3f26cde7bb338157942a28 /server/src
parent8f61b4c52906f4fe0417ca35d3995179b4f1b9df (diff)
downloadvaadin-framework-5a24c4865519be892b33a412e26326bc58f9cf0a.tar.gz
vaadin-framework-5a24c4865519be892b33a412e26326bc58f9cf0a.zip
Add API to access features of SelectionModels (#10939)
Diffstat (limited to 'server/src')
-rw-r--r--server/src/main/java/com/vaadin/ui/Grid.java21
-rw-r--r--server/src/main/java/com/vaadin/ui/components/grid/GridMultiSelect.java282
-rw-r--r--server/src/main/java/com/vaadin/ui/components/grid/GridSingleSelect.java260
-rw-r--r--server/src/test/java/com/vaadin/tests/components/grid/GridSelectionModeTest.java62
4 files changed, 610 insertions, 15 deletions
diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java
index 40618074d8..6e7d7b1cd4 100644
--- a/server/src/main/java/com/vaadin/ui/Grid.java
+++ b/server/src/main/java/com/vaadin/ui/Grid.java
@@ -103,7 +103,9 @@ import com.vaadin.ui.components.grid.Editor;
import com.vaadin.ui.components.grid.EditorImpl;
import com.vaadin.ui.components.grid.Footer;
import com.vaadin.ui.components.grid.FooterRow;
+import com.vaadin.ui.components.grid.GridMultiSelect;
import com.vaadin.ui.components.grid.GridSelectionModel;
+import com.vaadin.ui.components.grid.GridSingleSelect;
import com.vaadin.ui.components.grid.Header;
import com.vaadin.ui.components.grid.Header.Row;
import com.vaadin.ui.components.grid.HeaderCell;
@@ -3904,14 +3906,8 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents,
* @throws IllegalStateException
* if not using a single selection model
*/
- public SingleSelect<T> asSingleSelect() {
- GridSelectionModel<T> model = getSelectionModel();
- if (!(model instanceof SingleSelectionModel)) {
- throw new IllegalStateException(
- "Grid is not in single select mode, it needs to be explicitly set to such with setSelectionModel(SingleSelectionModel) before being able to use single selection features.");
- }
-
- return ((SingleSelectionModel<T>) model).asSingleSelect();
+ public GridSingleSelect<T> asSingleSelect() {
+ return new GridSingleSelect<>(this);
}
public Editor<T> getEditor() {
@@ -3928,13 +3924,8 @@ public class Grid<T> extends AbstractListing<T> implements HasComponents,
* @throws IllegalStateException
* if not using a multiselection model
*/
- public MultiSelect<T> asMultiSelect() {
- GridSelectionModel<T> model = getSelectionModel();
- if (!(model instanceof MultiSelectionModel)) {
- throw new IllegalStateException(
- "Grid is not in multiselect mode, it needs to be explicitly set to such with setSelectionModel(MultiSelectionModel) before being able to use multiselection features.");
- }
- return ((MultiSelectionModel<T>) model).asMultiSelect();
+ public GridMultiSelect<T> asMultiSelect() {
+ return new GridMultiSelect<>(this);
}
/**
diff --git a/server/src/main/java/com/vaadin/ui/components/grid/GridMultiSelect.java b/server/src/main/java/com/vaadin/ui/components/grid/GridMultiSelect.java
new file mode 100644
index 0000000000..bf3c9d02d3
--- /dev/null
+++ b/server/src/main/java/com/vaadin/ui/components/grid/GridMultiSelect.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2000-2018 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.components.grid;
+
+import java.util.Optional;
+import java.util.Set;
+
+import com.vaadin.event.selection.MultiSelectionListener;
+import com.vaadin.event.selection.SelectionListener;
+import com.vaadin.shared.Registration;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.MultiSelect;
+import com.vaadin.ui.components.grid.MultiSelectionModel.SelectAllCheckBoxVisibility;
+
+/**
+ * Wrapper class to wrap Grid into a MultiSelect. This class also provides
+ * useful access to API of MultiSelectionModel.
+ *
+ * @param <T>
+ * the bean type of grid
+ * @since
+ */
+public class GridMultiSelect<T> implements MultiSelect<T> {
+
+ private MultiSelectionModel<T> model;
+
+ /**
+ * Constructs a MultiSelect wrapper for given Grid.
+ *
+ * @param grid
+ * the grid to wrap
+ */
+ public GridMultiSelect(Grid<T> grid) {
+ GridSelectionModel<T> selectionModel = grid.getSelectionModel();
+ if (!(selectionModel instanceof MultiSelectionModel)) {
+ throw new IllegalStateException(
+ "Grid is not in multiselect mode, it needs to be explicitly set to such with setSelectionModel(MultiSelectionModel) before being able to use multiselection features.");
+ }
+ model = (MultiSelectionModel<T>) selectionModel;
+ }
+
+ /* API for MultiSelectionModelImpl */
+
+ /**
+ * Get first selected data item.
+ *
+ * @return the first selected item.
+ */
+ public Optional<T> getFirstSelectedItem() {
+ return model.getFirstSelectedItem();
+ }
+
+ /**
+ * Selects all available the items.
+ */
+ public void selectAll() {
+ model.selectAll();
+ }
+
+ /**
+ * Selects the given item. Depending on the implementation, may cause other
+ * items to be deselected. If the item is already selected, does nothing.
+ *
+ * @param item
+ * the item to select, not null
+ */
+ public void deselect(T item) {
+ model.deselect(item);
+ }
+
+ /**
+ * Selects the given item. If another item was already selected, that item
+ * is deselected.
+ *
+ * @param item
+ * the item to select
+ */
+ public void select(T item) {
+ model.select(item);
+ }
+
+ /**
+ * Deselects all currently selected items, if any.
+ */
+ public void deselectAll() {
+ model.deselectAll();
+ }
+
+ /**
+ * Adds the given items to the set of currently selected items.
+ * <p>
+ * By default this does not clear any previous selection. To do that, use
+ * {@link #deselectAll()}.
+ * <p>
+ * If the all the items were already selected, this is a NO-OP.
+ * <p>
+ * This is a short-hand for {@link #updateSelection(Set, Set)} with nothing
+ * to deselect.
+ *
+ * @param items
+ * to add to selection, not {@code null}
+ */
+ public void selectItems(T... items) {
+ model.selectItems(items);
+ }
+
+ /**
+ * Removes the given items from the set of currently selected items.
+ * <p>
+ * If the none of the items were selected, this is a NO-OP.
+ * <p>
+ * This is a short-hand for {@link #updateSelection(Set, Set)} with nothing
+ * to select.
+ *
+ * @param items
+ * to remove from selection, not {@code null}
+ */
+ public void deselectItems(T... items) {
+ model.deselectItems(items);
+ }
+
+ /**
+ * Sets the select all checkbox visibility mode.
+ * <p>
+ * The default value is {@link SelectAllCheckBoxVisibility#DEFAULT}, which
+ * means that the checkbox is only visible if the grid's data provider is
+ * in- memory.
+ *
+ * @param visibility
+ * the visiblity mode to use
+ * @see SelectAllCheckBoxVisibility
+ */
+ public void setSelectAllCheckBoxVisibility(
+ SelectAllCheckBoxVisibility visibility) {
+ model.setSelectAllCheckBoxVisibility(visibility);
+ }
+
+ /**
+ * Gets the current mode for the select all checkbox visibility.
+ *
+ * @return the select all checkbox visibility mode
+ * @see SelectAllCheckBoxVisibility
+ * @see #isSelectAllCheckBoxVisible()
+ */
+ public SelectAllCheckBoxVisibility getSelectAllCheckBoxVisibility() {
+ return model.getSelectAllCheckBoxVisibility();
+ }
+
+ /**
+ * Returns whether the select all checkbox will be visible with the current
+ * setting of
+ * {@link #setSelectAllCheckBoxVisibility(SelectAllCheckBoxVisibility)}.
+ *
+ * @return {@code true} if the checkbox will be visible with the current
+ * settings
+ * @see SelectAllCheckBoxVisibility
+ * @see #setSelectAllCheckBoxVisibility(SelectAllCheckBoxVisibility)
+ */
+ public boolean isSelectAllCheckBoxVisible() {
+ return model.isSelectAllCheckBoxVisible();
+ }
+
+ /**
+ * Sets whether the user is allowed to change the selection.
+ * <p>
+ * The check is done only for the client side actions. It doesn't affect
+ * selection requests sent from the server side.
+ *
+ * @param allowed
+ * <code>true</code> if the user is allowed to change the
+ * selection, <code>false</code> otherwise
+ */
+ public void setUserSelectionAllowed(boolean allowed) {
+ model.setUserSelectionAllowed(allowed);
+ }
+
+ /**
+ * Checks if the user is allowed to change the selection.
+ * <p>
+ * The check is done only for the client side actions. It doesn't affect
+ * selection requests sent from the server side.
+ *
+ * @return <code>true</code> if the user is allowed to change the selection,
+ * <code>false</code> otherwise
+ */
+ public boolean isUserSelectionAllowed() {
+ return model.isUserSelectionAllowed();
+ }
+
+ /**
+ * Adds a generic listener to this selection model, accepting both single
+ * and multiselection events.
+ *
+ * @param listener
+ * the listener to add
+ * @return a registration handle for removing the listener
+ */
+ public Registration addSelectionListener(SelectionListener<T> listener) {
+ return model.addSelectionListener(listener);
+ }
+
+ /**
+ * Adds a selection listener that will be called when the selection is
+ * changed either by the user or programmatically.
+ *
+ * @param listener
+ * the value change listener, not {@code null}
+ * @return a registration for the listener
+ */
+ public Registration addMultiSelectionListener(
+ MultiSelectionListener<T> listener) {
+ return model.addMultiSelectionListener(listener);
+ }
+
+ /* MultiSelect implementation */
+
+ @Override
+ public void setValue(Set<T> value) {
+ model.asMultiSelect().setValue(value);
+ }
+
+ @Override
+ public Set<T> getValue() {
+ return model.asMultiSelect().getValue();
+ }
+
+ @Override
+ public Registration addValueChangeListener(
+ ValueChangeListener<Set<T>> listener) {
+ return model.asMultiSelect().addValueChangeListener(listener);
+ }
+
+ @Override
+ public void setRequiredIndicatorVisible(boolean requiredIndicatorVisible) {
+ model.asMultiSelect()
+ .setRequiredIndicatorVisible(requiredIndicatorVisible);
+ }
+
+ @Override
+ public boolean isRequiredIndicatorVisible() {
+ return model.asMultiSelect().isRequiredIndicatorVisible();
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly) {
+ model.asMultiSelect().setReadOnly(readOnly);
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return model.asMultiSelect().isReadOnly();
+ }
+
+ @Override
+ public void updateSelection(Set<T> addedItems, Set<T> removedItems) {
+ model.asMultiSelect().updateSelection(addedItems, removedItems);
+ }
+
+ @Override
+ public Set<T> getSelectedItems() {
+ return model.asMultiSelect().getSelectedItems();
+ }
+
+ @Override
+ public Registration addSelectionListener(
+ MultiSelectionListener<T> listener) {
+ return model.asMultiSelect().addSelectionListener(listener);
+ }
+}
diff --git a/server/src/main/java/com/vaadin/ui/components/grid/GridSingleSelect.java b/server/src/main/java/com/vaadin/ui/components/grid/GridSingleSelect.java
new file mode 100644
index 0000000000..41804ad617
--- /dev/null
+++ b/server/src/main/java/com/vaadin/ui/components/grid/GridSingleSelect.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2000-2018 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.components.grid;
+
+import java.util.Optional;
+import java.util.Set;
+
+import com.vaadin.event.selection.SelectionListener;
+import com.vaadin.event.selection.SingleSelectionListener;
+import com.vaadin.shared.Registration;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.SingleSelect;
+
+/**
+ * Wrapper class to wrap Grid into a SingleSelect. This class also provides
+ * useful access to API of SingleSelectionModel.
+ *
+ * @param <T>
+ * the bean type of grid
+ * @since
+ */
+public class GridSingleSelect<T> implements SingleSelect<T> {
+
+ private SingleSelectionModel<T> model;
+
+ /**
+ * Constructs a SingleSelect wrapper for given Grid.
+ *
+ * @param grid
+ * the grid to wrap
+ */
+ public GridSingleSelect(Grid<T> grid) {
+ GridSelectionModel<T> selectionModel = grid.getSelectionModel();
+ if (!(selectionModel instanceof SingleSelectionModel)) {
+ throw new IllegalStateException(
+ "Grid is not in singleiselect mode, it needs to be explicitly set to such with setSelectionModel(SingleSelectionModel) before being able to use singleselection features.");
+ }
+ model = (SingleSelectionModel<T>) selectionModel;
+ }
+
+ /* API for SingleSelectionModel */
+
+ /**
+ * 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) {
+ model.setDeselectAllowed(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() {
+ return model.isDeselectAllowed();
+ }
+
+ /**
+ * Adds a single selection listener that is called when the value of this
+ * select is changed either by the user or programmatically.
+ *
+ * @param listener
+ * the value change listener, not {@code null}
+ * @return a registration for the listener
+ */
+ public Registration addSingleSelectionListener(
+ SingleSelectionListener<T> listener) {
+ return model.addSingleSelectionListener(listener);
+ }
+
+ /**
+ * Returns the currently selected item, or an empty optional if no item is
+ * selected.
+ *
+ * @return an optional of the selected item if any, an empty optional
+ * otherwise
+ */
+ public Optional<T> getSelectedItem() {
+ return model.getSelectedItem();
+ }
+
+ /**
+ * Sets the current selection to the given item, or clears selection if
+ * given {@code null}.
+ *
+ * @param item
+ * the item to select or {@code null} to clear selection
+ */
+ public void setSelectedItem(T item) {
+ model.setSelectedItem(item);
+ }
+
+ /* Generic SelectionModel API */
+
+ /**
+ * Sets whether the user is allowed to change the selection.
+ * <p>
+ * The check is done only for the client side actions. It doesn't affect
+ * selection requests sent from the server side.
+ *
+ * @param allowed
+ * <code>true</code> if the user is allowed to change the
+ * selection, <code>false</code> otherwise
+ */
+ public void setUserSelectionAllowed(boolean allowed) {
+ model.setUserSelectionAllowed(allowed);
+ }
+
+ /**
+ * Checks if the user is allowed to change the selection.
+ * <p>
+ * The check is done only for the client side actions. It doesn't affect
+ * selection requests sent from the server side.
+ *
+ * @return <code>true</code> if the user is allowed to change the selection,
+ * <code>false</code> otherwise
+ */
+ public boolean isUserSelectionAllowed() {
+ return model.isUserSelectionAllowed();
+ }
+
+ /**
+ * Returns a singleton set of the currently selected item or an empty set if
+ * no item is selected.
+ *
+ * @return a singleton set of the selected item if any, an empty set
+ * otherwise
+ *
+ * @see #getSelectedItem()
+ */
+ public Set<T> getSelectedItems() {
+ return model.getSelectedItems();
+ }
+
+ /**
+ * Get first selected data item.
+ *
+ * @return the first selected item.
+ */
+ public Optional<T> getFirstSelectedItem() {
+ return model.getFirstSelectedItem();
+ }
+
+ /**
+ * Selects the given item. Depending on the implementation, may cause other
+ * items to be deselected. If the item is already selected, does nothing.
+ *
+ * @param item
+ * the item to select, not null
+ */
+ public void deselect(T item) {
+ model.deselect(item);
+ }
+
+ /**
+ * Deselects all currently selected items, if any.
+ */
+ public void deselectAll() {
+ model.deselectAll();
+ }
+
+ /**
+ * Adds a generic listener to this selection model, accepting both single
+ * and multiselection events.
+ * <p>
+ * Use {@link #addSingleSelectionListener(SingleSelectionListener)} for more
+ * specific single selection event.
+ *
+ * @see #addSingleSelectionListener(SingleSelectionListener)
+ *
+ * @param listener
+ * the listener to add
+ * @return a registration handle for removing the listener
+ */
+ public Registration addSelectionListener(SelectionListener<T> listener) {
+ return model.addSelectionListener(listener);
+ }
+
+ /**
+ * Returns whether the given item is currently selected.
+ *
+ * @param item
+ * the item to check, not null
+ * @return {@code true} if the item is selected, {@code false} otherwise
+ */
+ public boolean isSelected(T item) {
+ return model.isSelected(item);
+ }
+
+ /**
+ * Selects the given item. If another item was already selected, that item
+ * is deselected.
+ *
+ * @param item
+ * the item to select
+ */
+ public void select(T item) {
+ model.select(item);
+ }
+
+ /* SingleSelect implementation */
+
+ @Override
+ public void setValue(T value) {
+ model.asSingleSelect().setValue(value);
+ }
+
+ @Override
+ public T getValue() {
+ return model.asSingleSelect().getValue();
+ }
+
+ @Override
+ public Registration addValueChangeListener(
+ ValueChangeListener<T> listener) {
+ return model.asSingleSelect().addValueChangeListener(listener);
+ }
+
+ @Override
+ public void setRequiredIndicatorVisible(boolean requiredIndicatorVisible) {
+ model.asSingleSelect()
+ .setRequiredIndicatorVisible(requiredIndicatorVisible);
+ }
+
+ @Override
+ public boolean isRequiredIndicatorVisible() {
+ return model.asSingleSelect().isRequiredIndicatorVisible();
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly) {
+ model.asSingleSelect().setReadOnly(readOnly);
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return model.asSingleSelect().isReadOnly();
+ }
+}
diff --git a/server/src/test/java/com/vaadin/tests/components/grid/GridSelectionModeTest.java b/server/src/test/java/com/vaadin/tests/components/grid/GridSelectionModeTest.java
index c8ca4cf791..15413eb2d7 100644
--- a/server/src/test/java/com/vaadin/tests/components/grid/GridSelectionModeTest.java
+++ b/server/src/test/java/com/vaadin/tests/components/grid/GridSelectionModeTest.java
@@ -2,13 +2,26 @@ package com.vaadin.tests.components.grid;
import static org.junit.Assert.assertEquals;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import com.vaadin.data.SelectionModel;
+import com.vaadin.server.Extension;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.components.grid.GridMultiSelect;
+import com.vaadin.ui.components.grid.GridSingleSelect;
+import com.vaadin.ui.components.grid.MultiSelectionModel;
import com.vaadin.ui.components.grid.MultiSelectionModelImpl;
import com.vaadin.ui.components.grid.NoSelectionModel;
+import com.vaadin.ui.components.grid.SingleSelectionModel;
import com.vaadin.ui.components.grid.SingleSelectionModelImpl;
public class GridSelectionModeTest {
@@ -47,4 +60,53 @@ public class GridSelectionModeTest {
grid.setSelectionMode(null);
}
+ @Test
+ public void testGridAsMultiSelectHasAllAPI() {
+ assertAllAPIAvailable(GridMultiSelect.class, MultiSelectionModel.class,
+ "asMultiSelect");
+ }
+
+ @Test
+ public void testGridAsSingleSelectHasAllAPI() {
+ assertAllAPIAvailable(GridSingleSelect.class,
+ SingleSelectionModel.class, "asSingleSelect");
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected void assertAllAPIAvailable(Class<?> testedClass,
+ Class<? extends SelectionModel> selectionModelClass,
+ String... ignoredMethods) {
+ List<String> ignored = Arrays.asList(ignoredMethods);
+ List<Method> missing = new ArrayList<>();
+ Arrays.stream(selectionModelClass.getMethods()).filter(method -> {
+ if (ignored.contains(method.getName())) {
+ // Explicitly ignored method.
+ return false;
+ }
+
+ try {
+ // Skip methods from Extension interface
+ Extension.class.getMethod(method.getName(),
+ method.getParameterTypes());
+ return false;
+ } catch (Exception e) {
+ return true;
+ }
+ }).forEach(method ->
+
+ {
+ try {
+ testedClass.getMethod(method.getName(),
+ method.getParameterTypes());
+ } catch (Exception e) {
+ missing.add(method);
+ }
+ });
+ if (!missing.isEmpty()) {
+ Assert.fail("Methods "
+ + missing.stream().map(Method::getName)
+ .collect(Collectors.joining(", "))
+ + " not found in " + testedClass.getSimpleName());
+ }
+ }
}