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 /server | |
parent | ff3a48e73bb7318793746aa9c9ff1cf61b632c7f (diff) | |
download | vaadin-framework-277b1a5c2884291ea9312d555dc45545430c1d9c.tar.gz vaadin-framework-277b1a5c2884291ea9312d555dc45545430c1d9c.zip |
Implement SingleSelection on client and server
Change-Id: I48192de092c6b6e6be7ca2580720d2765962e167
Diffstat (limited to 'server')
-rw-r--r-- | server/src/main/java/com/vaadin/data/HasValue.java | 45 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/data/Listing.java | 2 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/data/selection/AbstractSelectionModel.java | 47 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/data/selection/SelectionModel.java | 141 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/data/selection/SingleSelection.java | 187 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/event/EventListener.java | 50 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/ui/AbstractListing.java | 55 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/ui/Grid.java | 19 | ||||
-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 |
9 files changed, 357 insertions, 227 deletions
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/SelectionModel.java b/server/src/main/java/com/vaadin/data/selection/SelectionModel.java deleted file mode 100644 index 1730d26319..0000000000 --- a/server/src/main/java/com/vaadin/data/selection/SelectionModel.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.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. - * - * @author Vaadin Ltd. - * - * @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. - * 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> { - - /** - * Selects the given item. If another item was already selected, that - * item is deselected. - */ - @Override - public void select(T item); - - /** - * Returns the currently selected item, or an empty optional if no item - * is selected. - * - * @return an optional of the selected item if any, an empty optional - * otherwise - */ - public Optional<T> getSelectedItem(); - - /** - * Returns a singleton set of the currently selected item or an empty - * set if no item is selected. - * - * @return a singleton set of the selected item if any, an empty set - * otherwise - */ - @Override - default Set<T> getSelectedItems() { - return getSelectedItem().map(Collections::singleton) - .orElse(Collections.emptySet()); - } - } - - /** - * A selection model in which multiple items can be selected at the same - * time. Selecting an item adds it to the selection. - * - * @param <T> - * the type of the items to select - */ - public interface Multi<T> extends SelectionModel<T>, - HasValue<Collection<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. - * <p> - * <i>Implementation note:</i> the iteration order of the items in the - * returned set should be well-defined and documented by the implementing - * class. - * - * @return the items in the current selection, not null - */ - public Set<T> getSelectedItems(); - - /** - * Selects the given item. Depending on the implementation, may cause other - * items to be deselected. If the item is already selected, does nothing. - * - * @param item - * the item to select, not null - */ - public void select(T item); - - /** - * Deselects the given item. If the item is not currently selected, does - * nothing. - * - * @param item - * the item to deselect, not null - */ - public void deselect(T item); - - /** - * Returns whether the given item is currently selected. - * - * @param item - * the item to check, not null - * @return {@code true} if the item is selected, {@code false} otherwise - */ - public default boolean isSelected(T item) { - return getSelectedItems().contains(item); - } -} 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)); } /** |