diff options
author | Johannes Dahlström <johannesd@vaadin.com> | 2016-08-24 11:26:12 +0300 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2016-08-31 13:08:47 +0000 |
commit | 277b1a5c2884291ea9312d555dc45545430c1d9c (patch) | |
tree | bb44b2af9da21f0ca10287e31c24b540df89aad2 | |
parent | ff3a48e73bb7318793746aa9c9ff1cf61b632c7f (diff) | |
download | vaadin-framework-277b1a5c2884291ea9312d555dc45545430c1d9c.tar.gz vaadin-framework-277b1a5c2884291ea9312d555dc45545430c1d9c.zip |
Implement SingleSelection on client and server
Change-Id: I48192de092c6b6e6be7ca2580720d2765962e167
15 files changed, 583 insertions, 104 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/AbstractListingConnector.java b/client/src/main/java/com/vaadin/client/connectors/AbstractListingConnector.java index 06d3ecf97d..c00807ed2c 100644 --- a/client/src/main/java/com/vaadin/client/connectors/AbstractListingConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/AbstractListingConnector.java @@ -18,6 +18,7 @@ package com.vaadin.client.connectors; import com.vaadin.client.connectors.data.HasDataSource; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.shared.data.selection.SelectionModel; import com.vaadin.ui.AbstractListing; import elemental.json.JsonObject; @@ -32,6 +33,8 @@ public abstract class AbstractListingConnector private DataSource<JsonObject> dataSource = null; + private SelectionModel<String> selectionModel = null; + @Override public void setDataSource(DataSource<JsonObject> dataSource) { this.dataSource = dataSource; @@ -41,4 +44,18 @@ public abstract class AbstractListingConnector public DataSource<JsonObject> getDataSource() { return dataSource; } + + /** + * Sets the selection model to use. Passing {@code null} disables selection. + * + * @param selectionModel + * the selection model or null to disable + */ + public void setSelectionModel(SelectionModel<String> selectionModel) { + this.selectionModel = selectionModel; + } + + public SelectionModel<String> getSelectionModel() { + return selectionModel; + } } diff --git a/client/src/main/java/com/vaadin/client/connectors/selection/AbstractSelectionConnector.java b/client/src/main/java/com/vaadin/client/connectors/selection/AbstractSelectionConnector.java new file mode 100644 index 0000000000..b295fb0cc3 --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/selection/AbstractSelectionConnector.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.client.connectors.selection; + +import com.vaadin.client.ServerConnector; +import com.vaadin.client.connectors.AbstractListingConnector; +import com.vaadin.client.extensions.AbstractExtensionConnector; +import com.vaadin.shared.data.selection.SelectionModel; + +/** + * The client-side connector for selection extensions. + * + * @author Vaadin Ltd. + * + * @since + */ +public abstract class AbstractSelectionConnector extends + AbstractExtensionConnector { + + private SelectionModel<String> model = null; + + @Override + protected void extend(ServerConnector target) { + if (!(target instanceof AbstractListingConnector)) { + throw new IllegalArgumentException( + "Cannot extend a connector that is not an " + + AbstractListingConnector.class.getSimpleName()); + } + model = createSelectionModel(); + ((AbstractListingConnector) target).setSelectionModel(model); + } + + /** + * Creates a selection model object to be used by the Connector. + * + * @return created selection model + */ + protected abstract SelectionModel<String> createSelectionModel(); + + @Override + public AbstractListingConnector getParent() { + return (AbstractListingConnector) super.getParent(); + } + + /** + * Returns the client-side selection model associated with this connector. + * + * @return the selection model in use + */ + protected SelectionModel<String> getSelectionModel() { + return model; + } +} diff --git a/client/src/main/java/com/vaadin/client/connectors/selection/SingleSelectionConnector.java b/client/src/main/java/com/vaadin/client/connectors/selection/SingleSelectionConnector.java new file mode 100644 index 0000000000..70844d1ae7 --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/selection/SingleSelectionConnector.java @@ -0,0 +1,91 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.client.connectors.selection; + +import java.util.Optional; + +import com.vaadin.client.ServerConnector; +import com.vaadin.client.connectors.AbstractListingConnector; +import com.vaadin.shared.data.selection.SelectionModel; +import com.vaadin.shared.data.selection.SelectionServerRpc; +import com.vaadin.shared.ui.Connect; + +/** + * A connector for single selection extensions. + * + * @author Vaadin Ltd. + */ +@Connect(com.vaadin.data.selection.SingleSelection.class) +public class SingleSelectionConnector extends AbstractSelectionConnector { + + private static class SingleSelection implements + SelectionModel.Single<String> { + + private String value; + private SelectionServerRpc rpc; + + SingleSelection(SelectionServerRpc rpc) { + this.rpc = rpc; + } + + @Override + public void select(String item) { + if (item != null && !item.equals(value)) { + rpc.select(item); + value = item; + } + } + + @Override + public void deselect(String item) { + if (item != null && item.equals(value)) { + rpc.deselect(item); + value = null; + } + } + + @Override + public boolean isSelected(String item) { + return value != null && value.equals(item); + } + + @Override + public Optional<String> getSelectedItem() { + return Optional.ofNullable(value); + } + } + + private AbstractListingConnector parent; + + @Override + public void onUnregister() { + super.onUnregister(); + if (parent.getSelectionModel() == getSelectionModel()) { + parent.setSelectionModel(null); + } + } + + @Override + protected void extend(ServerConnector target) { + super.extend(target); + parent = getParent(); + } + + @Override + protected SelectionModel<String> createSelectionModel() { + return new SingleSelection(getRpcProxy(SelectionServerRpc.class)); + } +} diff --git a/client/src/main/java/com/vaadin/client/extensions/AbstractExtensionConnector.java b/client/src/main/java/com/vaadin/client/extensions/AbstractExtensionConnector.java index fd7a109e29..d98b7d65b6 100644 --- a/client/src/main/java/com/vaadin/client/extensions/AbstractExtensionConnector.java +++ b/client/src/main/java/com/vaadin/client/extensions/AbstractExtensionConnector.java @@ -19,6 +19,12 @@ package com.vaadin.client.extensions; import com.vaadin.client.ServerConnector; import com.vaadin.client.ui.AbstractConnector; +/** + * An abstract implementation for extension connectors. + * + * @author Vaadin Ltd. + * @since 7.0 + */ public abstract class AbstractExtensionConnector extends AbstractConnector { boolean hasBeenAttached = false; diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/HasSelectionHandlers.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/HasSelectionHandlers.java index 5e5cc6263d..edb226fa4f 100644 --- a/client/src/main/java/com/vaadin/client/widget/grid/selection/HasSelectionHandlers.java +++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/HasSelectionHandlers.java @@ -29,7 +29,7 @@ public interface HasSelectionHandlers<T> { * Register a selection change handler. * <p> * This handler is called whenever a - * {@link com.vaadin.ui.components.grid.selection.SelectionModel + * {@link com.vaadin.client.data.selection.components.grid.selection.SelectionModel * SelectionModel} detects a change in selection state. * * @param handler diff --git a/server/src/main/java/com/vaadin/data/HasValue.java b/server/src/main/java/com/vaadin/data/HasValue.java index cbd6bc390f..86b97be9c0 100644 --- a/server/src/main/java/com/vaadin/data/HasValue.java +++ b/server/src/main/java/com/vaadin/data/HasValue.java @@ -16,10 +16,9 @@ package com.vaadin.data; import java.io.Serializable; -import java.util.function.Consumer; import com.vaadin.event.ConnectorEvent; -import com.vaadin.event.ConnectorEventListener; +import com.vaadin.event.EventListener; import com.vaadin.server.ClientConnector; import com.vaadin.shared.Registration; @@ -28,9 +27,12 @@ import com.vaadin.shared.Registration; * that have a user-editable value. Emits change events whenever the value is * changed, either by the user or programmatically. * - * @since + * @author Vaadin Ltd. + * * @param <V> * the value type + * + * @since */ public interface HasValue<V> extends Serializable { @@ -49,7 +51,7 @@ public interface HasValue<V> extends Serializable { * Creates a new {@code ValueChange} event containing the current value * of the given value-bearing source connector. * - * @param <C> + * @param <CONNECTOR> * the type of the source connector * @param source * the source connector bearing the value, not null @@ -57,10 +59,27 @@ public interface HasValue<V> extends Serializable { * {@code true} if this event originates from the client, * {@code false} otherwise. */ - public <C extends ClientConnector & HasValue<V>> ValueChange(C source, + public <CONNECTOR extends ClientConnector & HasValue<V>> ValueChange( + CONNECTOR source, boolean userOriginated) { + this(source, source.getValue(), userOriginated); + } + + /** + * Creates a new {@code ValueChange} event containing the given value, + * originating from the given source connector. + * + * @param source + * the source connector, not null + * @param value + * the new value, may be null + * @param userOriginated + * {@code true} if this event originates from the client, + * {@code false} otherwise. + */ + public ValueChange(ClientConnector source, V value, boolean userOriginated) { super(source); - this.value = source.getValue(); + this.value = value; this.userOriginated = userOriginated; } @@ -95,8 +114,8 @@ public interface HasValue<V> extends Serializable { * @see Registration */ @FunctionalInterface - public interface ValueChangeListener<V> - extends Consumer<ValueChange<V>>, ConnectorEventListener { + public interface ValueChangeListener<V> extends + EventListener<ValueChange<V>> { /** * Invoked when this listener receives a value change event from an @@ -105,11 +124,6 @@ public interface HasValue<V> extends Serializable { * @param event * the received event, not null */ - // In addition to customizing the Javadoc, this override is needed - // to make ReflectTools.findMethod work as expected. It uses - // Class.getDeclaredMethod, but even if it used getMethod instead, the - // superinterface argument type is Object, not Event, after type - // erasure. @Override public void accept(ValueChange<V> event); } @@ -140,9 +154,8 @@ public interface HasValue<V> extends Serializable { public V getValue(); /** - * Adds an {@link ValueChangeListener}. The listener is called when the - * value of this {@code hasValue} is changed either by the user or - * programmatically. + * Adds a value change listener. The listener is called when the value of + * this {@code hasValue} is changed either by the user or programmatically. * * @param listener * the value change listener, not null diff --git a/server/src/main/java/com/vaadin/data/Listing.java b/server/src/main/java/com/vaadin/data/Listing.java index 818389f8b7..38cfecb9bb 100644 --- a/server/src/main/java/com/vaadin/data/Listing.java +++ b/server/src/main/java/com/vaadin/data/Listing.java @@ -19,8 +19,8 @@ import java.io.Serializable; import java.util.Collection; import java.util.Set; -import com.vaadin.data.selection.SelectionModel; import com.vaadin.server.data.DataSource; +import com.vaadin.shared.data.selection.SelectionModel; /** * A generic interface for components that show a list of data. diff --git a/server/src/main/java/com/vaadin/data/selection/AbstractSelectionModel.java b/server/src/main/java/com/vaadin/data/selection/AbstractSelectionModel.java new file mode 100644 index 0000000000..8294df0918 --- /dev/null +++ b/server/src/main/java/com/vaadin/data/selection/AbstractSelectionModel.java @@ -0,0 +1,47 @@ +/* + * 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.data.selection; + +import com.vaadin.shared.data.DataCommunicatorConstants; +import com.vaadin.shared.data.selection.SelectionModel; +import com.vaadin.ui.AbstractListing.AbstractListingExtension; + +import elemental.json.JsonObject; + +/** + * An astract base class for {@code SelectionModel}s. + * + * @author Vaadin Ltd. + * + * @param <T> + * type of selected data + * + * @since + */ +public abstract class AbstractSelectionModel<T> extends + AbstractListingExtension<T> implements SelectionModel<T> { + + @Override + public void generateData(T data, JsonObject jsonObject) { + if (isSelected(data)) { + jsonObject.put(DataCommunicatorConstants.SELECTED, true); + } + } + + @Override + public void destroyData(T data) { + } +} diff --git a/server/src/main/java/com/vaadin/data/selection/SingleSelection.java b/server/src/main/java/com/vaadin/data/selection/SingleSelection.java new file mode 100644 index 0000000000..6bb0ac5f66 --- /dev/null +++ b/server/src/main/java/com/vaadin/data/selection/SingleSelection.java @@ -0,0 +1,187 @@ +/* + * 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.data.selection; + +import java.lang.reflect.Method; +import java.util.Objects; +import java.util.Optional; + +import com.vaadin.data.HasValue.ValueChange; +import com.vaadin.event.EventListener; +import com.vaadin.shared.Registration; +import com.vaadin.shared.data.selection.SelectionModel.Single; +import com.vaadin.shared.data.selection.SelectionServerRpc; +import com.vaadin.ui.AbstractListing; +import com.vaadin.util.ReflectTools; + +/** + * A {@code SelectionModel} for selecting a single value. Implements + * {@code Extension} to provide the communication logic for single selection for + * the listing it extends. + * + * @author Vaadin Ltd. + * + * @param <T> + * the type of the items to select + * + * @since + */ +public class SingleSelection<T> extends AbstractSelectionModel<T> + implements Single<T> { + + /** + * Fired when the selection changes. + * + * @param <T> + * the type of the selected item + */ + public static class SingleSelectionChange<T> extends ValueChange<T> { + + /** + * Creates a new selection change event. + * + * @param source + * the listing that fired the event + * @param selectedItem + * the selected item or {@code null} if deselected + * @param userOriginated + * {@code true} if this event originates from the client, + * {@code false} otherwise. + */ + public SingleSelectionChange(AbstractListing<T, ?> source, + T selectedItem, boolean userOriginated) { + super(source, selectedItem, userOriginated); + } + + /** + * Returns an optional of the item that was selected, or an empty + * optional if a previously selected item was deselected. + * + * @return the selected item or an empty optional if deselected + * + * @see SelectionModel.Single#getSelectedItem() + */ + public Optional<T> getSelectedItem() { + return Optional.ofNullable(getValue()); + } + } + + /** + * A listener for selection events. + * + * @param <T> + * the type of the selected item + * + * @see SingleSelectionChange + */ + @FunctionalInterface + public interface SingleSelectionListener<T> extends + EventListener<SingleSelectionChange<T>> { + + @Override + public void accept(SingleSelectionChange<T> event); + } + + @Deprecated + private static final Method SELECTION_CHANGE_METHOD = ReflectTools + .findMethod(SingleSelectionListener.class, "accept", + SingleSelectionChange.class); + + /** + * Creates a new {@code SingleSelection} extending the given parent listing. + * + * @param parent + * the parent listing + */ + public SingleSelection( + AbstractListing<T, ? super SingleSelection<T>> parent) { + registerRpc(new SelectionServerRpc() { + + @Override + public void select(String key) { + doSelect(getData(key), true); + } + + @Override + public void deselect(String key) { + if (getData(key).equals(selectedItem)) { + doSelect(null, true); + } + } + }); + extend(parent); + } + + private T selectedItem = null; + + @Override + public Optional<T> getSelectedItem() { + return Optional.ofNullable(selectedItem); + } + + @Override + public void select(T value) { + doSelect(value, false); + } + + @Override + public void deselect(T value) { + this.selectedItem = null; + } + + @Override + public void remove() { + if (selectedItem != null) { + refresh(selectedItem); + } + super.remove(); + } + + /** + * Adds a selection listener. The listener is called when the value of this + * {@code SingleSelection} is changed either by the user or + * programmatically. + * + * @param listener + * the value change listener, not null + * @return a registration for the listener + */ + public Registration addSelectionListener( + SingleSelectionListener<T> listener) { + Objects.requireNonNull(listener, "listener cannot be null"); + addListener(SingleSelectionChange.class, listener, + SELECTION_CHANGE_METHOD); + return () -> removeListener(SingleSelectionChange.class, listener); + } + + /** + * Selects the given item or deselects the current one if given + * {@code null}. + * + * @param value + * the item to select or {@code null} to deselect + * @param userOriginated + * {@code true} if this event originates from the client, + * {@code false} otherwise. + */ + protected void doSelect(T value, boolean userOriginated) { + if (!Objects.equals(value, this.selectedItem)) { + this.selectedItem = value; + fireEvent(new SingleSelectionChange<>(getParent(), value, + userOriginated)); + } + } +} diff --git a/server/src/main/java/com/vaadin/event/EventListener.java b/server/src/main/java/com/vaadin/event/EventListener.java new file mode 100644 index 0000000000..c5bb811712 --- /dev/null +++ b/server/src/main/java/com/vaadin/event/EventListener.java @@ -0,0 +1,50 @@ +/* + * 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.event; + +import java.util.function.Consumer; + +/** + * A generic interface for connector event listeners. + * + * @author Vaadin Ltd. + * + * @param <EVENT> + * the event type + * + * @since 8.0 + */ +@FunctionalInterface +public interface EventListener<EVENT extends ConnectorEvent> + extends Consumer<EVENT>, ConnectorEventListener { + + /** + * Invoked when this listener receives an event from the event source to + * which it has been added. + * <p> + * <strong>Implementation note:</strong>In addition to customizing the + * Javadoc, this override is needed in all extending interfaces to make + * ReflectTools.findMethod work as expected. It uses + * Class.getDeclaredMethod, but even if it used getMethod instead, the + * superinterface argument type is ConnectorEvent, not the actual event + * type, after type erasure. + * + * @param event + * the received event, not null + */ + @Override + public void accept(EVENT event); +} diff --git a/server/src/main/java/com/vaadin/ui/AbstractListing.java b/server/src/main/java/com/vaadin/ui/AbstractListing.java index 58117e6df8..45c81fc7bd 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractListing.java +++ b/server/src/main/java/com/vaadin/ui/AbstractListing.java @@ -18,20 +18,24 @@ package com.vaadin.ui; import java.util.Objects; import com.vaadin.data.Listing; -import com.vaadin.data.selection.SelectionModel; import com.vaadin.server.AbstractExtension; import com.vaadin.server.data.DataCommunicator; import com.vaadin.server.data.DataGenerator; import com.vaadin.server.data.DataSource; +import com.vaadin.shared.data.selection.SelectionModel; /** * A base class for listing components. Provides common handling for fetching * backend data items, selection logic, and server-client communication. * + * @author Vaadin Ltd. + * * @param <T> * the item data type * @param <SELECTIONMODEL> * the selection logic supported by this listing + * + * @since */ public abstract class AbstractListing<T, SELECTIONMODEL extends SelectionModel<T>> extends AbstractComponent implements Listing<T, SELECTIONMODEL> { @@ -99,35 +103,35 @@ public abstract class AbstractListing<T, SELECTIONMODEL extends SelectionModel<T private SELECTIONMODEL selectionModel; /** - * Creates a new {@code AbstractListing} using the given selection model. - * - * @param selectionModel - * the selection model to use, not null + * Creates a new {@code AbstractListing} with a default data communicator. + * <p> + * <strong>Note:</strong> This constructor does not set a selection model + * for the new listing. The invoking constructor must explicitly call + * {@link #setSelectionModel(SelectionModel)}. */ - protected AbstractListing(SELECTIONMODEL selectionModel) { - this(selectionModel, new DataCommunicator<>()); + protected AbstractListing() { + this(new DataCommunicator<>()); } /** - * Creates a new {@code AbstractListing} with the given selection model and - * data communicator. + * Creates a new {@code AbstractListing} with the given custom data + * communicator. * <p> * <strong>Note:</strong> This method is for creating an - * {@link AbstractListing} with a custom {@link DataCommunicator}. In the - * common case {@link AbstractListing#AbstractListing()} should be used. - * - * @param selectionModel - * the selection model to use, not null + * {@code AbstractListing} with a custom communicator. In the common case + * {@link AbstractListing#AbstractListing()} should be used. + * <p> + * <strong>Note:</strong> This constructor does not set a selection model + * for the new listing. The invoking constructor must explicitly call + * {@link #setSelectionModel(SelectionModel)}. + * * @param dataCommunicator - * the custom data communicator to use, not null + * the data communicator to use, not null */ - protected AbstractListing(SELECTIONMODEL selectionModel, - DataCommunicator<T> dataCommunicator) { - Objects.requireNonNull(selectionModel, "selectionModel cannot be null"); + protected AbstractListing(DataCommunicator<T> dataCommunicator) { Objects.requireNonNull(dataCommunicator, "dataCommunicator cannot be null"); - this.selectionModel = selectionModel; this.dataCommunicator = dataCommunicator; addExtension(dataCommunicator); } @@ -144,10 +148,23 @@ public abstract class AbstractListing<T, SELECTIONMODEL extends SelectionModel<T @Override public SELECTIONMODEL getSelectionModel() { + assert selectionModel != null : "No selection model set by " + + getClass().getName() + " constructor"; return selectionModel; } /** + * Sets the selection model for this listing. + * + * @param model + * the selection model to use, not null + */ + protected void setSelectionModel(SELECTIONMODEL model) { + Objects.requireNonNull(model, "selection model cannot be null"); + selectionModel = model; + } + + /** * Adds the given data generator to this listing. If the generator was * already added, does nothing. * diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 47335e4462..c236a9c5f6 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -31,7 +31,7 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; -import com.vaadin.data.selection.SelectionModel; +import com.vaadin.data.selection.SingleSelection; import com.vaadin.server.AbstractExtension; import com.vaadin.server.KeyMapper; import com.vaadin.server.data.DataSource; @@ -39,6 +39,7 @@ import com.vaadin.server.data.SortOrder; import com.vaadin.server.data.DataGenerator; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.data.DataCommunicatorConstants; +import com.vaadin.shared.data.selection.SelectionModel; import com.vaadin.shared.data.sort.SortDirection; import com.vaadin.shared.ui.grid.ColumnState; import com.vaadin.shared.ui.grid.GridConstants.Section; @@ -527,21 +528,7 @@ public class Grid<T> extends AbstractListing<T, SelectionModel<T>> * Constructor for the {@link Grid} component. */ public Grid() { - super(new SelectionModel<T>() { - // Stub no-op selection model until selection models are implemented - @Override - public Set<T> getSelectedItems() { - return Collections.emptySet(); - } - - @Override - public void select(T item) { - } - - @Override - public void deselect(T item) { - } - }); + setSelectionModel(new SingleSelection<>(this)); setDataSource(DataSource.create()); registerRpc(new GridServerRpcImpl()); detailsManager = new DetailsManager<>(); diff --git a/server/src/test/java/com/vaadin/tests/server/component/abstractlisting/AbstractListingTest.java b/server/src/test/java/com/vaadin/ui/AbstractListingTest.java index f29d1dd00b..cbab429748 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/abstractlisting/AbstractListingTest.java +++ b/server/src/test/java/com/vaadin/ui/AbstractListingTest.java @@ -1,23 +1,19 @@ -package com.vaadin.tests.server.component.abstractlisting; +package com.vaadin.ui; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; -import java.util.Set; import java.util.stream.Stream; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.vaadin.data.selection.SelectionModel; +import com.vaadin.data.selection.SingleSelection; import com.vaadin.server.data.BackEndDataSource; -import com.vaadin.server.data.DataGenerator; import com.vaadin.server.data.DataSource; import com.vaadin.server.data.ListDataSource; import com.vaadin.server.data.Query; -import com.vaadin.ui.AbstractListing; import com.vaadin.ui.AbstractListing.AbstractListingExtension; import elemental.json.JsonObject; @@ -25,36 +21,10 @@ import elemental.json.JsonObject; public class AbstractListingTest { private final class TestListing extends - AbstractListing<String, SelectionModel<String>> { + AbstractListing<String, SingleSelection<String>> { protected TestListing() { - // Stub for now, implement (and test) when adding concrete - // SelectionModels - super(new SelectionModel<String>() { - - @Override - public Set<String> getSelectedItems() { - return Collections.emptySet(); - } - - @Override - public void select(String item) { - } - - @Override - public void deselect(String item) { - } - }); - } - - @Override - public void addDataGenerator(DataGenerator<String> generator) { - super.addDataGenerator(generator); - } - - @Override - public void removeDataGenerator(DataGenerator<String> generator) { - super.removeDataGenerator(generator); + setSelectionModel(new SingleSelection<>(this)); } /** diff --git a/server/src/main/java/com/vaadin/data/selection/SelectionModel.java b/shared/src/main/java/com/vaadin/shared/data/selection/SelectionModel.java index 1730d26319..8fff6ee434 100644 --- a/server/src/main/java/com/vaadin/data/selection/SelectionModel.java +++ b/shared/src/main/java/com/vaadin/shared/data/selection/SelectionModel.java @@ -13,17 +13,13 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.data.selection; +package com.vaadin.shared.data.selection; import java.io.Serializable; -import java.util.Collection; import java.util.Collections; import java.util.Optional; import java.util.Set; -import com.vaadin.data.HasValue; -import com.vaadin.data.Listing; - /** * Models the selection logic of a {@code Listing} component. Determines how * items can be selected and deselected. @@ -33,19 +29,17 @@ import com.vaadin.data.Listing; * @param <T> * the type of the items to select * @since - * - * @see Listing */ public interface SelectionModel<T> extends Serializable { /** - * A selection model in which a single item can be selected at a time. + * A selection model in which at most one item can be selected at a time. * Selecting another item deselects the originally selected item. * * @param <T> * the type of the items to select */ - public interface Single<T> extends SelectionModel<T>, HasValue<T> { + public interface Single<T> extends SelectionModel<T> { /** * Selects the given item. If another item was already selected, that @@ -84,23 +78,17 @@ public interface SelectionModel<T> extends Serializable { * @param <T> * the type of the items to select */ - public interface Multi<T> extends SelectionModel<T>, - HasValue<Collection<T>> { + public interface Multi<T> extends SelectionModel<T> { /** * Adds the given items to the set of currently selected items. */ @Override public void select(T item); - - /** - * Adds the given items to the set of currently selected items. - */ - public void select(@SuppressWarnings("unchecked") T... items); } /** - * Returns an immutable set of the currently selected item. + * Returns an immutable set of the currently selected items. * <p> * <i>Implementation note:</i> the iteration order of the items in the * returned set should be well-defined and documented by the implementing diff --git a/shared/src/main/java/com/vaadin/shared/data/selection/SelectionServerRpc.java b/shared/src/main/java/com/vaadin/shared/data/selection/SelectionServerRpc.java new file mode 100644 index 0000000000..65cc55aebd --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/data/selection/SelectionServerRpc.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.shared.data.selection; + +import com.vaadin.shared.communication.ServerRpc; + +/** + * Transmits SelectionModel selection events from the client to the server. + */ +public interface SelectionServerRpc extends ServerRpc { + + /** + * Selects an item based on its key. + * + * @param key + * the key of the item to select + */ + void select(String key); + + /** + * Deselects an item based on its key. + * + * @param key + * the key of the item to deselect + */ + void deselect(String key); +} |