Change-Id: I48192de092c6b6e6be7ca2580720d2765962e167tags/8.0.0.alpha1
import com.vaadin.client.connectors.data.HasDataSource; | import com.vaadin.client.connectors.data.HasDataSource; | ||||
import com.vaadin.client.data.DataSource; | import com.vaadin.client.data.DataSource; | ||||
import com.vaadin.client.ui.AbstractComponentConnector; | import com.vaadin.client.ui.AbstractComponentConnector; | ||||
import com.vaadin.shared.data.selection.SelectionModel; | |||||
import com.vaadin.ui.AbstractListing; | import com.vaadin.ui.AbstractListing; | ||||
import elemental.json.JsonObject; | import elemental.json.JsonObject; | ||||
private DataSource<JsonObject> dataSource = null; | private DataSource<JsonObject> dataSource = null; | ||||
private SelectionModel<String> selectionModel = null; | |||||
@Override | @Override | ||||
public void setDataSource(DataSource<JsonObject> dataSource) { | public void setDataSource(DataSource<JsonObject> dataSource) { | ||||
this.dataSource = dataSource; | this.dataSource = dataSource; | ||||
public DataSource<JsonObject> getDataSource() { | public DataSource<JsonObject> getDataSource() { | ||||
return dataSource; | 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; | |||||
} | |||||
} | } |
/* | |||||
* 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; | |||||
} | |||||
} |
/* | |||||
* 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)); | |||||
} | |||||
} |
import com.vaadin.client.ServerConnector; | import com.vaadin.client.ServerConnector; | ||||
import com.vaadin.client.ui.AbstractConnector; | import com.vaadin.client.ui.AbstractConnector; | ||||
/** | |||||
* An abstract implementation for extension connectors. | |||||
* | |||||
* @author Vaadin Ltd. | |||||
* @since 7.0 | |||||
*/ | |||||
public abstract class AbstractExtensionConnector extends AbstractConnector { | public abstract class AbstractExtensionConnector extends AbstractConnector { | ||||
boolean hasBeenAttached = false; | boolean hasBeenAttached = false; | ||||
* Register a selection change handler. | * Register a selection change handler. | ||||
* <p> | * <p> | ||||
* This handler is called whenever a | * 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. | * SelectionModel} detects a change in selection state. | ||||
* | * | ||||
* @param handler | * @param handler |
package com.vaadin.data; | package com.vaadin.data; | ||||
import java.io.Serializable; | import java.io.Serializable; | ||||
import java.util.function.Consumer; | |||||
import com.vaadin.event.ConnectorEvent; | import com.vaadin.event.ConnectorEvent; | ||||
import com.vaadin.event.ConnectorEventListener; | |||||
import com.vaadin.event.EventListener; | |||||
import com.vaadin.server.ClientConnector; | import com.vaadin.server.ClientConnector; | ||||
import com.vaadin.shared.Registration; | import com.vaadin.shared.Registration; | ||||
* that have a user-editable value. Emits change events whenever the value is | * that have a user-editable value. Emits change events whenever the value is | ||||
* changed, either by the user or programmatically. | * changed, either by the user or programmatically. | ||||
* | * | ||||
* @since | |||||
* @author Vaadin Ltd. | |||||
* | |||||
* @param <V> | * @param <V> | ||||
* the value type | * the value type | ||||
* | |||||
* @since | |||||
*/ | */ | ||||
public interface HasValue<V> extends Serializable { | public interface HasValue<V> extends Serializable { | ||||
* Creates a new {@code ValueChange} event containing the current value | * Creates a new {@code ValueChange} event containing the current value | ||||
* of the given value-bearing source connector. | * of the given value-bearing source connector. | ||||
* | * | ||||
* @param <C> | |||||
* @param <CONNECTOR> | |||||
* the type of the source connector | * the type of the source connector | ||||
* @param source | * @param source | ||||
* the source connector bearing the value, not null | * the source connector bearing the value, not null | ||||
* {@code true} if this event originates from the client, | * {@code true} if this event originates from the client, | ||||
* {@code false} otherwise. | * {@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) { | boolean userOriginated) { | ||||
super(source); | super(source); | ||||
this.value = source.getValue(); | |||||
this.value = value; | |||||
this.userOriginated = userOriginated; | this.userOriginated = userOriginated; | ||||
} | } | ||||
* @see Registration | * @see Registration | ||||
*/ | */ | ||||
@FunctionalInterface | @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 | * Invoked when this listener receives a value change event from an | ||||
* @param event | * @param event | ||||
* the received event, not null | * 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 | @Override | ||||
public void accept(ValueChange<V> event); | public void accept(ValueChange<V> event); | ||||
} | } | ||||
public V getValue(); | 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 | * @param listener | ||||
* the value change listener, not null | * the value change listener, not null |
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Set; | import java.util.Set; | ||||
import com.vaadin.data.selection.SelectionModel; | |||||
import com.vaadin.server.data.DataSource; | import com.vaadin.server.data.DataSource; | ||||
import com.vaadin.shared.data.selection.SelectionModel; | |||||
/** | /** | ||||
* A generic interface for components that show a list of data. | * A generic interface for components that show a list of data. |
/* | |||||
* 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) { | |||||
} | |||||
} |
/* | |||||
* 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)); | |||||
} | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} |
import java.util.Objects; | import java.util.Objects; | ||||
import com.vaadin.data.Listing; | import com.vaadin.data.Listing; | ||||
import com.vaadin.data.selection.SelectionModel; | |||||
import com.vaadin.server.AbstractExtension; | import com.vaadin.server.AbstractExtension; | ||||
import com.vaadin.server.data.DataCommunicator; | import com.vaadin.server.data.DataCommunicator; | ||||
import com.vaadin.server.data.DataGenerator; | import com.vaadin.server.data.DataGenerator; | ||||
import com.vaadin.server.data.DataSource; | import com.vaadin.server.data.DataSource; | ||||
import com.vaadin.shared.data.selection.SelectionModel; | |||||
/** | /** | ||||
* A base class for listing components. Provides common handling for fetching | * A base class for listing components. Provides common handling for fetching | ||||
* backend data items, selection logic, and server-client communication. | * backend data items, selection logic, and server-client communication. | ||||
* | * | ||||
* @author Vaadin Ltd. | |||||
* | |||||
* @param <T> | * @param <T> | ||||
* the item data type | * the item data type | ||||
* @param <SELECTIONMODEL> | * @param <SELECTIONMODEL> | ||||
* the selection logic supported by this listing | * the selection logic supported by this listing | ||||
* | |||||
* @since | |||||
*/ | */ | ||||
public abstract class AbstractListing<T, SELECTIONMODEL extends SelectionModel<T>> | public abstract class AbstractListing<T, SELECTIONMODEL extends SelectionModel<T>> | ||||
extends AbstractComponent implements Listing<T, SELECTIONMODEL> { | extends AbstractComponent implements Listing<T, SELECTIONMODEL> { | ||||
private SELECTIONMODEL selectionModel; | 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> | * <p> | ||||
* <strong>Note:</strong> This method is for creating an | * <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 | * @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, | Objects.requireNonNull(dataCommunicator, | ||||
"dataCommunicator cannot be null"); | "dataCommunicator cannot be null"); | ||||
this.selectionModel = selectionModel; | |||||
this.dataCommunicator = dataCommunicator; | this.dataCommunicator = dataCommunicator; | ||||
addExtension(dataCommunicator); | addExtension(dataCommunicator); | ||||
} | } | ||||
@Override | @Override | ||||
public SELECTIONMODEL getSelectionModel() { | public SELECTIONMODEL getSelectionModel() { | ||||
assert selectionModel != null : "No selection model set by " | |||||
+ getClass().getName() + " constructor"; | |||||
return selectionModel; | 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 | * Adds the given data generator to this listing. If the generator was | ||||
* already added, does nothing. | * already added, does nothing. |
import java.util.function.Function; | import java.util.function.Function; | ||||
import java.util.stream.Stream; | 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.AbstractExtension; | ||||
import com.vaadin.server.KeyMapper; | import com.vaadin.server.KeyMapper; | ||||
import com.vaadin.server.data.DataSource; | import com.vaadin.server.data.DataSource; | ||||
import com.vaadin.server.data.DataGenerator; | import com.vaadin.server.data.DataGenerator; | ||||
import com.vaadin.shared.MouseEventDetails; | import com.vaadin.shared.MouseEventDetails; | ||||
import com.vaadin.shared.data.DataCommunicatorConstants; | import com.vaadin.shared.data.DataCommunicatorConstants; | ||||
import com.vaadin.shared.data.selection.SelectionModel; | |||||
import com.vaadin.shared.data.sort.SortDirection; | import com.vaadin.shared.data.sort.SortDirection; | ||||
import com.vaadin.shared.ui.grid.ColumnState; | import com.vaadin.shared.ui.grid.ColumnState; | ||||
import com.vaadin.shared.ui.grid.GridConstants.Section; | import com.vaadin.shared.ui.grid.GridConstants.Section; | ||||
* Constructor for the {@link Grid} component. | * Constructor for the {@link Grid} component. | ||||
*/ | */ | ||||
public Grid() { | 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()); | setDataSource(DataSource.create()); | ||||
registerRpc(new GridServerRpcImpl()); | registerRpc(new GridServerRpcImpl()); | ||||
detailsManager = new DetailsManager<>(); | detailsManager = new DetailsManager<>(); |
package com.vaadin.tests.server.component.abstractlisting; | |||||
package com.vaadin.ui; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.Collections; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.Set; | |||||
import java.util.stream.Stream; | import java.util.stream.Stream; | ||||
import org.junit.Assert; | import org.junit.Assert; | ||||
import org.junit.Before; | import org.junit.Before; | ||||
import org.junit.Test; | 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.BackEndDataSource; | ||||
import com.vaadin.server.data.DataGenerator; | |||||
import com.vaadin.server.data.DataSource; | import com.vaadin.server.data.DataSource; | ||||
import com.vaadin.server.data.ListDataSource; | import com.vaadin.server.data.ListDataSource; | ||||
import com.vaadin.server.data.Query; | import com.vaadin.server.data.Query; | ||||
import com.vaadin.ui.AbstractListing; | |||||
import com.vaadin.ui.AbstractListing.AbstractListingExtension; | import com.vaadin.ui.AbstractListing.AbstractListingExtension; | ||||
import elemental.json.JsonObject; | import elemental.json.JsonObject; | ||||
public class AbstractListingTest { | public class AbstractListingTest { | ||||
private final class TestListing extends | private final class TestListing extends | ||||
AbstractListing<String, SelectionModel<String>> { | |||||
AbstractListing<String, SingleSelection<String>> { | |||||
protected TestListing() { | 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)); | |||||
} | } | ||||
/** | /** |
* License for the specific language governing permissions and limitations under | * License for the specific language governing permissions and limitations under | ||||
* the License. | * the License. | ||||
*/ | */ | ||||
package com.vaadin.data.selection; | |||||
package com.vaadin.shared.data.selection; | |||||
import java.io.Serializable; | import java.io.Serializable; | ||||
import java.util.Collection; | |||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.Optional; | import java.util.Optional; | ||||
import java.util.Set; | 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 | * Models the selection logic of a {@code Listing} component. Determines how | ||||
* items can be selected and deselected. | * items can be selected and deselected. | ||||
* @param <T> | * @param <T> | ||||
* the type of the items to select | * the type of the items to select | ||||
* @since | * @since | ||||
* | |||||
* @see Listing | |||||
*/ | */ | ||||
public interface SelectionModel<T> extends Serializable { | 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. | * Selecting another item deselects the originally selected item. | ||||
* | * | ||||
* @param <T> | * @param <T> | ||||
* the type of the items to select | * 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 | * Selects the given item. If another item was already selected, that | ||||
* @param <T> | * @param <T> | ||||
* the type of the items to select | * 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. | * Adds the given items to the set of currently selected items. | ||||
*/ | */ | ||||
@Override | @Override | ||||
public void select(T item); | 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> | * <p> | ||||
* <i>Implementation note:</i> the iteration order of the items in the | * <i>Implementation note:</i> the iteration order of the items in the | ||||
* returned set should be well-defined and documented by the implementing | * returned set should be well-defined and documented by the implementing |
/* | |||||
* 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); | |||||
} |