summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Dahlström <johannesd@vaadin.com>2016-08-24 11:26:12 +0300
committerVaadin Code Review <review@vaadin.com>2016-08-31 13:08:47 +0000
commit277b1a5c2884291ea9312d555dc45545430c1d9c (patch)
treebb44b2af9da21f0ca10287e31c24b540df89aad2
parentff3a48e73bb7318793746aa9c9ff1cf61b632c7f (diff)
downloadvaadin-framework-277b1a5c2884291ea9312d555dc45545430c1d9c.tar.gz
vaadin-framework-277b1a5c2884291ea9312d555dc45545430c1d9c.zip
Implement SingleSelection on client and server
Change-Id: I48192de092c6b6e6be7ca2580720d2765962e167
-rw-r--r--client/src/main/java/com/vaadin/client/connectors/AbstractListingConnector.java17
-rw-r--r--client/src/main/java/com/vaadin/client/connectors/selection/AbstractSelectionConnector.java66
-rw-r--r--client/src/main/java/com/vaadin/client/connectors/selection/SingleSelectionConnector.java91
-rw-r--r--client/src/main/java/com/vaadin/client/extensions/AbstractExtensionConnector.java6
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/selection/HasSelectionHandlers.java2
-rw-r--r--server/src/main/java/com/vaadin/data/HasValue.java45
-rw-r--r--server/src/main/java/com/vaadin/data/Listing.java2
-rw-r--r--server/src/main/java/com/vaadin/data/selection/AbstractSelectionModel.java47
-rw-r--r--server/src/main/java/com/vaadin/data/selection/SingleSelection.java187
-rw-r--r--server/src/main/java/com/vaadin/event/EventListener.java50
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractListing.java55
-rw-r--r--server/src/main/java/com/vaadin/ui/Grid.java19
-rw-r--r--server/src/test/java/com/vaadin/ui/AbstractListingTest.java (renamed from server/src/test/java/com/vaadin/tests/server/component/abstractlisting/AbstractListingTest.java)38
-rw-r--r--shared/src/main/java/com/vaadin/shared/data/selection/SelectionModel.java (renamed from server/src/main/java/com/vaadin/data/selection/SelectionModel.java)22
-rw-r--r--shared/src/main/java/com/vaadin/shared/data/selection/SelectionServerRpc.java40
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);
+}