private DataSource<JsonObject> dataSource = null;
- private SelectionModel<String> selectionModel = null;
+ private SelectionModel<JsonObject> selectionModel = null;
@Override
public void setDataSource(DataSource<JsonObject> 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) {
+ public void setSelectionModel(SelectionModel<JsonObject> selectionModel) {
this.selectionModel = selectionModel;
}
- public SelectionModel<String> getSelectionModel() {
+ public SelectionModel<JsonObject> getSelectionModel() {
return selectionModel;
}
}
import com.vaadin.client.data.DataSource;
import com.vaadin.client.ui.SimpleManagedLayout;
import com.vaadin.client.widget.grid.selection.ClickSelectHandler;
+import com.vaadin.client.widget.grid.selection.SpaceSelectHandler;
import com.vaadin.client.widget.grid.sort.SortEvent;
import com.vaadin.client.widget.grid.sort.SortOrder;
import com.vaadin.client.widgets.Grid;
import com.vaadin.client.widgets.Grid.Column;
+import com.vaadin.shared.data.selection.SelectionModel;
+import com.vaadin.shared.data.selection.SelectionModel.Single;
import com.vaadin.shared.data.sort.SortDirection;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.grid.GridServerRpc;
private Map<Column<?, JsonObject>, String> columnToIdMap = new HashMap<>();
/* Child component list for HasComponentsConnector */
private List<ComponentConnector> childComponents;
+ private SpaceSelectHandler<JsonObject> spaceSelectHandler;
+ private ClickSelectHandler<JsonObject> clickSelectHandler;
@Override
public Grid<JsonObject> getWidget() {
protected void init() {
super.init();
- new ClickSelectHandler<>(getWidget());
+ // Default selection style is space key.
+ spaceSelectHandler = new SpaceSelectHandler<JsonObject>(getWidget());
getWidget().addSortHandler(this::handleSortEvent);
layout();
@Override
public void setDataSource(DataSource<JsonObject> dataSource) {
+ super.setDataSource(dataSource);
getWidget().setDataSource(dataSource);
}
+ @Override
+ public void setSelectionModel(SelectionModel<JsonObject> selectionModel) {
+ removeClickHandler();
+
+ super.setSelectionModel(selectionModel);
+ getWidget().setSelectionModel(selectionModel);
+
+ if (selectionModel instanceof Single) {
+ // Single selection should be moved by a click.
+ clickSelectHandler = new ClickSelectHandler<>(getWidget());
+ }
+ }
+
/**
* Adds a column to the Grid widget. For each column a communication id
* stored for client to server communication.
super.onUnregister();
columnToIdMap.clear();
+ removeClickHandler();
+
+ if (spaceSelectHandler != null) {
+ spaceSelectHandler.removeHandler();
+ spaceSelectHandler = null;
+ }
}
@Override
public GridState getState() {
return (GridState) super.getState();
}
+
+ private void removeClickHandler() {
+ if (clickSelectHandler != null) {
+ clickSelectHandler.removeHandler();
+ clickSelectHandler = null;
+ }
+ }
}
/*
* 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
import com.vaadin.client.ServerConnector;
import com.vaadin.client.connectors.AbstractListingConnector;
import com.vaadin.client.extensions.AbstractExtensionConnector;
+import com.vaadin.shared.data.DataCommunicatorConstants;
import com.vaadin.shared.data.selection.SelectionModel;
+import elemental.json.JsonObject;
+
/**
* The client-side connector for selection extensions.
- *
+ *
* @author Vaadin Ltd.
- *
+ *
* @since
*/
-public abstract class AbstractSelectionConnector extends
- AbstractExtensionConnector {
+public abstract class AbstractSelectionConnector
+ extends AbstractExtensionConnector {
- private SelectionModel<String> model = null;
+ private SelectionModel<JsonObject> model = null;
@Override
protected void extend(ServerConnector target) {
/**
* Creates a selection model object to be used by the Connector.
- *
+ *
* @return created selection model
*/
- protected abstract SelectionModel<String> createSelectionModel();
+ protected abstract SelectionModel<JsonObject> createSelectionModel();
@Override
public AbstractListingConnector getParent() {
/**
* Returns the client-side selection model associated with this connector.
- *
+ *
* @return the selection model in use
*/
- protected SelectionModel<String> getSelectionModel() {
+ protected SelectionModel<JsonObject> getSelectionModel() {
return model;
}
+
+ /**
+ * Gets the selected state from a given json object. This is a helper method
+ * for selection model connectors.
+ *
+ * @param item
+ * a json object
+ * @return {@code true} if the json object is marked as selected;
+ * {@code false} if not
+ */
+ public static boolean isItemSelected(JsonObject item) {
+ return item.hasKey(DataCommunicatorConstants.SELECTED)
+ && item.getBoolean(DataCommunicatorConstants.SELECTED);
+ }
+
+ /**
+ * Gets the item key from given json object. This is a helper method for
+ * selection model connectors.
+ *
+ * @param item
+ * a json object
+ * @return item key; {@code null} if there is no key
+ */
+ public static String getKey(JsonObject item) {
+ if (item.hasKey(DataCommunicatorConstants.KEY)) {
+ return item.getString(DataCommunicatorConstants.KEY);
+ } else {
+ return null;
+ }
+ }
+
}
/*
* 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
import com.vaadin.shared.data.selection.SelectionServerRpc;
import com.vaadin.shared.ui.Connect;
+import elemental.json.JsonObject;
+
/**
* 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 static class SingleSelection
+ implements SelectionModel.Single<JsonObject> {
- private String value;
private SelectionServerRpc rpc;
SingleSelection(SelectionServerRpc rpc) {
}
@Override
- public void select(String item) {
- if (item != null && !item.equals(value)) {
- rpc.select(item);
- value = item;
+ public void select(JsonObject item) {
+ if (!isSelected(item)) {
+ rpc.select(getKey(item));
}
}
@Override
- public void deselect(String item) {
- if (item != null && item.equals(value)) {
- rpc.deselect(item);
- value = null;
+ public void deselect(JsonObject item) {
+ if (isSelected(item)) {
+ rpc.deselect(getKey(item));
}
}
@Override
- public boolean isSelected(String item) {
- return value != null && value.equals(item);
+ public boolean isSelected(JsonObject item) {
+ return isItemSelected(item);
}
@Override
- public Optional<String> getSelectedItem() {
- return Optional.ofNullable(value);
+ public Optional<JsonObject> getSelectedItem() {
+ throw new UnsupportedOperationException(
+ "A client-side selection model does not know the full selection");
}
}
}
@Override
- protected SelectionModel<String> createSelectionModel() {
+ protected SelectionModel<JsonObject> createSelectionModel() {
return new SingleSelection(getRpcProxy(SelectionServerRpc.class));
}
}
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.widget.grid.selection.SelectionModelWithSelectionColumn;
import com.vaadin.client.widgets.Grid;
/**
private int getRealFrozenColumnCount() {
if (grid.getFrozenColumnCount() < 0) {
return 0;
- } else if (grid.getSelectionModel()
- .getSelectionColumnRenderer() != null) {
+ } else if (grid
+ .getSelectionModel() instanceof SelectionModelWithSelectionColumn) {
// includes the selection column
return grid.getFrozenColumnCount() + 1;
} else {
return new SelectAllHandler<T>() {
@Override
public void onSelectAll(SelectAllEvent<T> event) {
- event.getSelectionModel().select(asList());
+ asList().forEach(event.getSelectionModel()::select);
}
};
}
Set<DataChangeHandler> copy = new LinkedHashSet<>(changeHandlers);
return copy.stream();
}
-
}
package com.vaadin.client.widget.grid.events;
import com.google.gwt.event.shared.GwtEvent;
-import com.vaadin.client.widget.grid.selection.SelectionModel;
+import com.vaadin.shared.data.selection.SelectionModel;
/**
* A select all event, fired by the Grid when it needs all rows in data source
+++ /dev/null
-/*
- * 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.widget.grid.selection;
-
-import com.vaadin.client.data.DataSource.RowHandle;
-
-/**
- * An abstract class that adds a consistent API for common methods that's needed
- * by Vaadin's server-based selection models to work.
- * <p>
- * <em>Note:</em> This should be an interface instead of an abstract class, if
- * only we could define protected methods in an interface.
- *
- * @author Vaadin Ltd
- * @param <T>
- * The grid's row type
- * @since 7.4
- */
-public abstract class AbstractRowHandleSelectionModel<T>
- implements SelectionModel<T> {
- /**
- * Select a row, based on its
- * {@link com.vaadin.client.data.DataSource.RowHandle RowHandle}.
- * <p>
- * <em>Note:</em> this method may not fire selection change events.
- *
- * @param handle
- * the handle to select by
- * @return <code>true</code> iff the selection state was changed by this
- * call
- * @throws UnsupportedOperationException
- * if the selection model does not support either handles or
- * selection
- */
- protected abstract boolean selectByHandle(RowHandle<T> handle);
-
- /**
- * Deselect a row, based on its
- * {@link com.vaadin.client.data.DataSource.RowHandle RowHandle}.
- * <p>
- * <em>Note:</em> this method may not fire selection change events.
- *
- * @param handle
- * the handle to deselect by
- * @return <code>true</code> iff the selection state was changed by this
- * call
- * @throws UnsupportedOperationException
- * if the selection model does not support either handles or
- * deselection
- */
- protected abstract boolean deselectByHandle(RowHandle<T> handle)
- throws UnsupportedOperationException;
-}
import com.vaadin.client.widget.grid.RendererCellReference;
import com.vaadin.client.widget.grid.events.GridEnabledEvent;
import com.vaadin.client.widget.grid.events.GridEnabledHandler;
-import com.vaadin.client.widget.grid.selection.SelectionModel.Multi.Batched;
import com.vaadin.client.widgets.Grid;
/**
private int gradientArea;
public void start(int logicalRowIndex) {
-
- SelectionModel<T> model = grid.getSelectionModel();
- if (model instanceof Batched) {
- Batched<?> batchedModel = (Batched<?>) model;
- batchedModel.startBatchSelect();
- }
-
/*
* bounds are updated whenever the autoscroll cycle starts, to make
* sure that the widget hasn't changed in size, moved around, or
autoScroller = null;
}
- SelectionModel<T> model = grid.getSelectionModel();
- if (model instanceof Batched) {
- Batched<?> batchedModel = (Batched<?>) model;
- batchedModel.commitBatchSelect();
- }
-
removeNativeHandler();
}
}
+++ /dev/null
-/*
- * 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.widget.grid.selection;
-
-import java.util.Collection;
-
-import com.vaadin.client.renderers.Renderer;
-import com.vaadin.client.widgets.Grid;
-
-/**
- * Common interface for all selection models.
- * <p>
- * Selection models perform tracking of selected rows in the Grid, as well as
- * dispatching events when the selection state changes.
- *
- * @author Vaadin Ltd
- * @param <T>
- * Grid's row type
- * @since 7.4
- */
-public interface SelectionModel<T> {
-
- /**
- * Return true if the provided row is considered selected under the
- * implementing selection model.
- *
- * @param row
- * row object instance
- * @return <code>true</code>, if the row given as argument is considered
- * selected.
- */
- public boolean isSelected(T row);
-
- /**
- * Return the {@link Renderer} responsible for rendering the selection
- * column.
- *
- * @return a renderer instance. If null is returned, a selection column will
- * not be drawn.
- */
- public Renderer<Boolean> getSelectionColumnRenderer();
-
- /**
- * Tells this SelectionModel which Grid it belongs to.
- * <p>
- * Implementations are free to have this be a no-op. This method is called
- * internally by Grid.
- *
- * @param grid
- * a {@link Grid} instance; <code>null</code> when removing from
- * Grid
- */
- public void setGrid(Grid<T> grid);
-
- /**
- * Resets the SelectionModel to the initial state.
- * <p>
- * This method can be called internally, for example, when the attached
- * Grid's data source changes.
- */
- public void reset();
-
- /**
- * Returns a Collection containing all selected rows.
- *
- * @return a non-null collection.
- */
- public Collection<T> getSelectedRows();
-
- /**
- * Selection model that allows a maximum of one row to be selected at any
- * one time.
- *
- * @param <T>
- * type parameter corresponding with Grid row type
- */
- public interface Single<T> extends SelectionModel<T> {
-
- /**
- * Selects a row.
- *
- * @param row
- * a {@link Grid} row object
- * @return true, if this row as not previously selected.
- */
- public boolean select(T row);
-
- /**
- * Deselects a row.
- * <p>
- * This is a no-op unless {@link row} is the currently selected row.
- *
- * @param row
- * a {@link Grid} row object
- * @return true, if the currently selected row was deselected.
- */
- public boolean deselect(T row);
-
- /**
- * Returns the currently selected row.
- *
- * @return a {@link Grid} row object or null, if nothing is selected.
- */
- public T getSelectedRow();
-
- /**
- * Sets whether it's allowed to deselect the selected row through the
- * UI. Deselection is allowed by default.
- *
- * @param deselectAllowed
- * <code>true</code> if the selected row can be deselected
- * without selecting another row instead; otherwise
- * <code>false</code>.
- */
- public void setDeselectAllowed(boolean deselectAllowed);
-
- /**
- * Sets whether it's allowed to deselect the selected row through the
- * UI.
- *
- * @return <code>true</code> if deselection is allowed; otherwise
- * <code>false</code>
- */
- public boolean isDeselectAllowed();
-
- }
-
- /**
- * Selection model that allows for several rows to be selected at once.
- *
- * @param <T>
- * type parameter corresponding with Grid row type
- */
- public interface Multi<T> extends SelectionModel<T> {
-
- /**
- * A multi selection model that can send selections and deselections in
- * a batch, instead of committing them one-by-one.
- *
- * @param <T>
- * type parameter corresponding with Grid row type
- */
- public interface Batched<T> extends Multi<T> {
- /**
- * Starts a batch selection.
- * <p>
- * Any commands to any select or deselect method will be batched
- * into one, and a final selection event will be fired when
- * {@link #commitBatchSelect()} is called.
- * <p>
- * <em>Note:</em> {@link SelectionEvent SelectionChangeEvents} will
- * still be fired for each selection/deselection. You should check
- * whether the event is a part of a batch or not with
- * {@link SelectionEvent#isBatchedSelection()}.
- */
- public void startBatchSelect();
-
- /**
- * Commits and ends a batch selection.
- * <p>
- * Any and all selections and deselections since the last invocation
- * of {@link #startBatchSelect()} will be fired at once as one
- * collated {@link SelectionEvent}.
- */
- public void commitBatchSelect();
-
- /**
- * Checks whether or not a batch has been started.
- *
- * @return <code>true</code> iff a batch has been started
- */
- public boolean isBeingBatchSelected();
-
- /**
- * Gets all the rows that would become selected in this batch.
- *
- * @return a collection of the rows that would become selected
- */
- public Collection<T> getSelectedRowsBatch();
-
- /**
- * Gets all the rows that would become deselected in this batch.
- *
- * @return a collection of the rows that would become deselected
- */
- public Collection<T> getDeselectedRowsBatch();
- }
-
- /**
- * Selects one or more rows.
- *
- * @param rows
- * {@link Grid} row objects
- * @return true, if the set of selected rows was changed.
- */
- public boolean select(T... rows);
-
- /**
- * Deselects one or more rows.
- *
- * @param rows
- * Grid row objects
- * @return true, if the set of selected rows was changed.
- */
- public boolean deselect(T... rows);
-
- /**
- * De-selects all rows.
- *
- * @return true, if any row was previously selected.
- */
- public boolean deselectAll();
-
- /**
- * Select all rows in a {@link Collection}.
- *
- * @param rows
- * a collection of Grid row objects
- * @return true, if the set of selected rows was changed.
- */
- public boolean select(Collection<T> rows);
-
- /**
- * Deselect all rows in a {@link Collection}.
- *
- * @param rows
- * a collection of Grid row objects
- * @return true, if the set of selected rows was changed.
- */
- public boolean deselect(Collection<T> rows);
-
- }
-
- /**
- * Interface for a selection model that does not allow anything to be
- * selected.
- *
- * @param <T>
- * type parameter corresponding with Grid row type
- */
- public interface None<T> extends SelectionModel<T> {
-
- }
-
-}
+++ /dev/null
-/*
- * 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.widget.grid.selection;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import com.vaadin.client.data.DataSource.RowHandle;
-import com.vaadin.client.renderers.Renderer;
-import com.vaadin.client.widgets.Grid;
-
-/**
- * Multi-row selection model.
- *
- * @author Vaadin Ltd
- * @since 7.4
- */
-public class SelectionModelMulti<T> extends AbstractRowHandleSelectionModel<T>
- implements SelectionModel.Multi.Batched<T> {
-
- private final LinkedHashSet<RowHandle<T>> selectedRows;
- private Renderer<Boolean> renderer;
- private Grid<T> grid;
-
- private boolean batchStarted = false;
- private final LinkedHashSet<RowHandle<T>> selectionBatch = new LinkedHashSet<>();
- private final LinkedHashSet<RowHandle<T>> deselectionBatch = new LinkedHashSet<>();
-
- /* Event handling for selection with space key */
- private SpaceSelectHandler<T> spaceSelectHandler;
-
- public SelectionModelMulti() {
- grid = null;
- renderer = null;
- selectedRows = new LinkedHashSet<>();
- }
-
- @Override
- public boolean isSelected(T row) {
- return isSelectedByHandle(grid.getDataSource().getHandle(row));
- }
-
- @Override
- public Renderer<Boolean> getSelectionColumnRenderer() {
- return renderer;
- }
-
- @Override
- public void setGrid(Grid<T> grid) {
- if (this.grid != null && grid != null) {
- // Trying to replace grid
- throw new IllegalStateException(
- "Selection model is already attached to a grid. "
- + "Remove the selection model first from "
- + "the grid and then add it.");
- }
-
- this.grid = grid;
- if (this.grid != null) {
- spaceSelectHandler = new SpaceSelectHandler<>(grid);
- this.renderer = new MultiSelectionRenderer<>(grid);
- } else {
- spaceSelectHandler.removeHandler();
- spaceSelectHandler = null;
- this.renderer = null;
- }
-
- }
-
- @Override
- public boolean select(T... rows) {
- if (rows == null) {
- throw new IllegalArgumentException("Rows cannot be null");
- }
- return select(Arrays.asList(rows));
- }
-
- @Override
- public boolean deselect(T... rows) {
- if (rows == null) {
- throw new IllegalArgumentException("Rows cannot be null");
- }
- return deselect(Arrays.asList(rows));
- }
-
- @Override
- public boolean deselectAll() {
- if (selectedRows.size() > 0) {
-
- @SuppressWarnings("unchecked")
- final LinkedHashSet<RowHandle<T>> selectedRowsClone = (LinkedHashSet<RowHandle<T>>) selectedRows
- .clone();
- SelectionEvent<T> event = new SelectionEvent<>(grid, null,
- getSelectedRows(), isBeingBatchSelected());
- selectedRows.clear();
-
- if (isBeingBatchSelected()) {
- selectionBatch.clear();
- deselectionBatch.clear();
- deselectionBatch.addAll(selectedRowsClone);
- }
-
- grid.fireEvent(event);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean select(Collection<T> rows) {
- if (rows == null) {
- throw new IllegalArgumentException("Rows cannot be null");
- }
-
- Set<T> added = new LinkedHashSet<>();
-
- for (T row : rows) {
- RowHandle<T> handle = grid.getDataSource().getHandle(row);
- if (selectByHandle(handle)) {
- added.add(row);
- }
- }
-
- if (added.size() > 0) {
- grid.fireEvent(new SelectionEvent<>(grid, added, null,
- isBeingBatchSelected()));
-
- return true;
- }
- return false;
- }
-
- @Override
- public boolean deselect(Collection<T> rows) {
- if (rows == null) {
- throw new IllegalArgumentException("Rows cannot be null");
- }
-
- Set<T> removed = new LinkedHashSet<>();
-
- for (T row : rows) {
- RowHandle<T> handle = grid.getDataSource().getHandle(row);
- if (deselectByHandle(handle)) {
- removed.add(row);
- }
- }
-
- if (removed.size() > 0) {
- grid.fireEvent(new SelectionEvent<>(grid, null, removed,
- isBeingBatchSelected()));
- return true;
- }
- return false;
- }
-
- protected boolean isSelectedByHandle(RowHandle<T> handle) {
- return selectedRows.contains(handle);
- }
-
- @Override
- protected boolean selectByHandle(RowHandle<T> handle) {
- if (selectedRows.add(handle)) {
- handle.pin();
-
- if (isBeingBatchSelected()) {
- deselectionBatch.remove(handle);
- selectionBatch.add(handle);
- }
-
- return true;
- }
- return false;
- }
-
- @Override
- protected boolean deselectByHandle(RowHandle<T> handle) {
- if (selectedRows.remove(handle)) {
-
- if (!isBeingBatchSelected()) {
- handle.unpin();
- } else {
- selectionBatch.remove(handle);
- deselectionBatch.add(handle);
- }
- return true;
- }
- return false;
- }
-
- @Override
- public Collection<T> getSelectedRows() {
- Set<T> selected = new LinkedHashSet<>();
- for (RowHandle<T> handle : selectedRows) {
- selected.add(handle.getRow());
- }
- return Collections.unmodifiableSet(selected);
- }
-
- @Override
- public void reset() {
- deselectAll();
- }
-
- @Override
- public void startBatchSelect() {
- assert !isBeingBatchSelected() : "Batch has already been started";
- batchStarted = true;
- }
-
- @Override
- public void commitBatchSelect() {
- assert isBeingBatchSelected() : "Batch was never started";
- if (!isBeingBatchSelected()) {
- return;
- }
-
- batchStarted = false;
-
- final Collection<T> added = getSelectedRowsBatch();
- selectionBatch.clear();
-
- final Collection<T> removed = getDeselectedRowsBatch();
-
- // unpin deselected rows
- for (RowHandle<T> handle : deselectionBatch) {
- handle.unpin();
- }
- deselectionBatch.clear();
-
- grid.fireEvent(new SelectionEvent<>(grid, added, removed,
- isBeingBatchSelected()));
- }
-
- @Override
- public boolean isBeingBatchSelected() {
- return batchStarted;
- }
-
- @Override
- public Collection<T> getSelectedRowsBatch() {
- return rowHandlesToRows(selectionBatch);
- }
-
- @Override
- public Collection<T> getDeselectedRowsBatch() {
- return rowHandlesToRows(deselectionBatch);
- }
-
- private ArrayList<T> rowHandlesToRows(Collection<RowHandle<T>> rowHandles) {
- ArrayList<T> rows = new ArrayList<>(rowHandles.size());
- for (RowHandle<T> handle : rowHandles) {
- rows.add(handle.getRow());
- }
- return rows;
- }
-}
+++ /dev/null
-/*
- * 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.widget.grid.selection;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import com.vaadin.client.data.DataSource.RowHandle;
-import com.vaadin.client.renderers.Renderer;
-import com.vaadin.client.widgets.Grid;
-
-/**
- * No-row selection model.
- *
- * @author Vaadin Ltd
- * @since 7.4
- */
-public class SelectionModelNone<T> extends AbstractRowHandleSelectionModel<T>
- implements SelectionModel.None<T> {
-
- @Override
- public boolean isSelected(T row) {
- return false;
- }
-
- @Override
- public Renderer<Boolean> getSelectionColumnRenderer() {
- return null;
- }
-
- @Override
- public void setGrid(Grid<T> grid) {
- // noop
- }
-
- @Override
- public void reset() {
- // noop
- }
-
- @Override
- public Collection<T> getSelectedRows() {
- return Collections.emptySet();
- }
-
- @Override
- protected boolean selectByHandle(RowHandle<T> handle)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "This selection model " + "does not support selection");
- }
-
- @Override
- protected boolean deselectByHandle(RowHandle<T> handle)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException(
- "This selection model " + "does not support deselection");
- }
-
-}
+++ /dev/null
-/*
- * 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.widget.grid.selection;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import com.vaadin.client.data.DataSource.RowHandle;
-import com.vaadin.client.renderers.Renderer;
-import com.vaadin.client.widgets.Grid;
-
-/**
- * Single-row selection model.
- *
- * @author Vaadin Ltd
- * @since 7.4
- */
-public class SelectionModelSingle<T> extends AbstractRowHandleSelectionModel<T>
- implements SelectionModel.Single<T> {
-
- private Grid<T> grid;
- private RowHandle<T> selectedRow;
-
- /** Event handling for selection with space key */
- private SpaceSelectHandler<T> spaceSelectHandler;
-
- /** Event handling for selection by clicking cells */
- private ClickSelectHandler<T> clickSelectHandler;
-
- private boolean deselectAllowed = true;
-
- @Override
- public boolean isSelected(T row) {
- return selectedRow != null
- && selectedRow.equals(grid.getDataSource().getHandle(row));
- }
-
- @Override
- public Renderer<Boolean> getSelectionColumnRenderer() {
- // No Selection column renderer for single selection
- return null;
- }
-
- @Override
- public void setGrid(Grid<T> grid) {
- if (this.grid != null && grid != null) {
- // Trying to replace grid
- throw new IllegalStateException(
- "Selection model is already attached to a grid. "
- + "Remove the selection model first from "
- + "the grid and then add it.");
- }
-
- this.grid = grid;
- if (this.grid != null) {
- spaceSelectHandler = new SpaceSelectHandler<>(grid);
- clickSelectHandler = new ClickSelectHandler<>(grid);
- updateHandlerDeselectAllowed();
- } else {
- spaceSelectHandler.removeHandler();
- clickSelectHandler.removeHandler();
- spaceSelectHandler = null;
- clickSelectHandler = null;
- }
- }
-
- @Override
- public boolean select(T row) {
-
- if (row == null) {
- throw new IllegalArgumentException("Row cannot be null");
- }
-
- T removed = getSelectedRow();
- if (selectByHandle(grid.getDataSource().getHandle(row))) {
- grid.fireEvent(new SelectionEvent<>(grid, row, removed, false));
-
- return true;
- }
- return false;
- }
-
- @Override
- public boolean deselect(T row) {
-
- if (row == null) {
- throw new IllegalArgumentException("Row cannot be null");
- }
-
- if (isSelected(row)) {
- deselectByHandle(selectedRow);
- grid.fireEvent(new SelectionEvent<>(grid, null, row, false));
- return true;
- }
-
- return false;
- }
-
- @Override
- public T getSelectedRow() {
- return (selectedRow != null ? selectedRow.getRow() : null);
- }
-
- @Override
- public void reset() {
- if (selectedRow != null) {
- deselect(getSelectedRow());
- }
- }
-
- @Override
- public Collection<T> getSelectedRows() {
- if (getSelectedRow() != null) {
- return Collections.singleton(getSelectedRow());
- }
- return Collections.emptySet();
- }
-
- @Override
- protected boolean selectByHandle(RowHandle<T> handle) {
- if (handle != null && !handle.equals(selectedRow)) {
- deselectByHandle(selectedRow);
- selectedRow = handle;
- selectedRow.pin();
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- protected boolean deselectByHandle(RowHandle<T> handle) {
- if (handle != null && handle.equals(selectedRow)) {
- selectedRow.unpin();
- selectedRow = null;
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public void setDeselectAllowed(boolean deselectAllowed) {
- this.deselectAllowed = deselectAllowed;
- updateHandlerDeselectAllowed();
- }
-
- @Override
- public boolean isDeselectAllowed() {
- return deselectAllowed;
- }
-
- private void updateHandlerDeselectAllowed() {
- if (spaceSelectHandler != null) {
- spaceSelectHandler.setDeselectAllowed(deselectAllowed);
- }
- if (clickSelectHandler != null) {
- clickSelectHandler.setDeselectAllowed(deselectAllowed);
- }
- }
-
-}
--- /dev/null
+/*
+ * 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.widget.grid.selection;
+
+import com.vaadin.client.renderers.Renderer;
+import com.vaadin.shared.data.selection.SelectionModel;
+
+/**
+ * Interface for SelectionModels that wants Grid to display a selection column.
+ *
+ * @author Vaadin Ltd
+ * @since
+ *
+ * @param <T>
+ * selected item type
+ *
+ * @see Renderer
+ */
+public interface SelectionModelWithSelectionColumn<T>
+ extends SelectionModel<T> {
+
+ /**
+ * Returns a new instance of the Renderer for selection column.
+ *
+ * @return selection column renderer
+ */
+ public Renderer<Boolean> getRenderer();
+
+}
import com.vaadin.client.widget.grid.selection.MultiSelectionRenderer;
import com.vaadin.client.widget.grid.selection.SelectionEvent;
import com.vaadin.client.widget.grid.selection.SelectionHandler;
-import com.vaadin.client.widget.grid.selection.SelectionModel;
-import com.vaadin.client.widget.grid.selection.SelectionModel.Multi;
-import com.vaadin.client.widget.grid.selection.SelectionModel.Single;
-import com.vaadin.client.widget.grid.selection.SelectionModelMulti;
-import com.vaadin.client.widget.grid.selection.SelectionModelNone;
-import com.vaadin.client.widget.grid.selection.SelectionModelSingle;
+import com.vaadin.client.widget.grid.selection.SelectionModelWithSelectionColumn;
import com.vaadin.client.widget.grid.sort.Sort;
import com.vaadin.client.widget.grid.sort.SortEvent;
import com.vaadin.client.widget.grid.sort.SortHandler;
import com.vaadin.client.widgets.Grid.StaticSection.StaticRow;
import com.vaadin.shared.Range;
import com.vaadin.shared.Registration;
+import com.vaadin.shared.data.selection.SelectionModel;
+import com.vaadin.shared.data.selection.SelectionModel.Multi;
import com.vaadin.shared.data.sort.SortDirection;
import com.vaadin.shared.ui.grid.GridConstants;
import com.vaadin.shared.ui.grid.GridConstants.Section;
private int getSelectionAndFrozenColumnCount() {
// no matter if selection column is frozen or not, it is considered
// frozen for column dnd reorder
- if (getSelectionModel().getSelectionColumnRenderer() != null) {
+ if (getSelectionModel() instanceof SelectionModelWithSelectionColumn) {
return Math.max(0, getFrozenColumnCount()) + 1;
} else {
return Math.max(0, getFrozenColumnCount());
};
- /**
- * Enumeration for easy setting of selection mode.
- */
- public enum SelectionMode {
-
- /**
- * Shortcut for {@link SelectionModelSingle}.
- */
- SINGLE {
-
- @Override
- protected <T> SelectionModel<T> createModel() {
- return GWT.create(SelectionModelSingle.class);
- }
- },
-
- /**
- * Shortcut for {@link SelectionModelMulti}.
- */
- MULTI {
-
- @Override
- protected <T> SelectionModel<T> createModel() {
- return GWT.create(SelectionModelMulti.class);
- }
- },
-
- /**
- * Shortcut for {@link SelectionModelNone}.
- */
- NONE {
-
- @Override
- protected <T> SelectionModel<T> createModel() {
- return GWT.create(SelectionModelNone.class);
- }
- };
-
- protected abstract <T> SelectionModel<T> createModel();
- }
-
/**
* Base class for grid columns internally used by the Grid. The user should
* use {@link Column} when creating new columns.
}
/**
- * Returns the current header caption for this column
+ * Returns the current header caption for this column.
*
* @since 7.6
* @return the header caption string
*
* @param pixels
* the width in pixels or negative for auto sizing
+ * @return this column
*/
public Column<C, T> setWidth(double pixels) {
if (!WidgetUtil.pixelValuesEqual(widthUser, pixels)) {
* @param resizable
* {@code true} if this column should be resizable,
* {@code false} otherwise
+ * @return this column
*/
public Column<C, T> setResizable(boolean resizable) {
if (this.resizable != resizable) {
* @param hidden
* <code>true</code> to hide the column, <code>false</code>
* to show
+ * @return this column
*/
public Column<C, T> setHidden(boolean hidden) {
setHidden(hidden, false);
* @param hidable
* {@code true} the user can hide this column, {@code false}
* otherwise
+ * @return this column
*/
public Column<C, T> setHidable(boolean hidable) {
if (this.hidable != hidable) {
* @since 7.5.0
* @param hidingToggleCaption
* the caption for the hiding toggle for this column
+ * @return this column
*/
public Column<C, T> setHidingToggleCaption(String hidingToggleCaption) {
this.hidingToggleCaption = hidingToggleCaption;
*
* @param pixels
* the maximum width
- * @param immediately
- * <code>true</code> if the widths should be executed
- * immediately (ignoring lazy loading completely), or
- * <code>false</code> if the command should be run after a
- * while (duplicate non-immediately invocations are ignored).
* @return this column
*/
public Column<C, T> setMaximumWidth(double pixels) {
* returns. This is done to reduce overhead of unintentionally always
* recalculate all columns, when modifying several columns at once.
*
- * @param expandRatio
+ * @param ratio
* the expand ratio of this column. {@code 0} to not have it
* expand at all. A negative number to clear the expand
* value.
editor.setGrid(this);
- setSelectionMode(SelectionMode.SINGLE);
+ setSelectionModel(new SelectionModel<T>() {
+
+ @Override
+ public Set<T> getSelectedItems() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void select(T item) {
+ }
+
+ @Override
+ public void deselect(T item) {
+ }
+
+ });
escalator.getBody().setSpacerUpdater(gridSpacerUpdater);
/**
* Removes the row at the given position from the header section.
*
- * @param index
+ * @param rowIndex
* the position of the row
*
* @throws IllegalArgumentException
/**
* Removes the row at the given position from the footer section.
*
- * @param index
+ * @param rowIndex
* the position of the row
*
* @throws IllegalArgumentException
throw new IllegalArgumentException("dataSource can't be null.");
}
- selectionModel.reset();
-
if (changeHandler != null) {
changeHandler.remove();
changeHandler = null;
}
/**
- * Gets the vertical scroll offset
+ * Gets the vertical scroll offset.
*
* @return the number of pixels this grid is scrolled down
*/
}
/**
- * Sets the horizontal scroll offset
+ * Sets the horizontal scroll offset.
*
* @since 7.5.0
* @param px
}
/**
- * Gets the horizontal scroll offset
+ * Gets the horizontal scroll offset.
*
* @return the number of pixels this grid is scrolled to the right
*/
throw new IllegalArgumentException("Selection model can't be null");
}
- if (this.selectionModel != null) {
- // Detach selection model from Grid.
- this.selectionModel.setGrid(null);
- }
-
this.selectionModel = selectionModel;
- selectionModel.setGrid(this);
- setSelectColumnRenderer(
- this.selectionModel.getSelectionColumnRenderer());
+ if (selectionModel instanceof SelectionModelWithSelectionColumn) {
+ setSelectColumnRenderer(
+ ((SelectionModelWithSelectionColumn<T>) selectionModel)
+ .getRenderer());
+ } else {
+ setSelectColumnRenderer(null);
+ }
// Refresh rendered rows to update selection, if it has changed
refreshBody();
}
/**
- * Sets current selection mode.
- * <p>
- * This is a shorthand method for {@link Grid#setSelectionModel}.
- *
- * @param mode
- * a selection mode value
- * @see {@link SelectionMode}.
- */
- public void setSelectionMode(SelectionMode mode) {
- SelectionModel<T> model = mode.createModel();
- setSelectionModel(model);
- }
-
- /**
- * Test if a row is selected.
+ * Returns if a row is selected.
*
* @param row
* a row object
- * @return true, if the current selection model considers the provided row
- * object selected.
+ * @return {@code true}, if the current selection model considers the
+ * provided row object selected.
*/
public boolean isSelected(T row) {
return selectionModel.isSelected(row);
}
/**
- * Select a row using the current selection model.
+ * Selects a row using the current selection model.
* <p>
* Only selection models implementing {@link SelectionModel.Single} and
* {@link SelectionModel.Multi} are supported; for anything else, an
*
* @param row
* a row object
- * @return <code>true</code> iff the current selection changed
* @throws IllegalStateException
* if the current selection model is not an instance of
* {@link SelectionModel.Single} or {@link SelectionModel.Multi}
*/
- public boolean select(T row) {
- if (selectionModel instanceof SelectionModel.Single<?>) {
- return ((SelectionModel.Single<T>) selectionModel).select(row);
- } else if (selectionModel instanceof SelectionModel.Multi<?>) {
- return ((SelectionModel.Multi<T>) selectionModel)
- .select(Collections.singleton(row));
- } else {
- throw new IllegalStateException("Unsupported selection model");
- }
+ public void select(T row) {
+ getSelectionModel().select(row);
}
/**
- * Deselect a row using the current selection model.
+ * Deselects a row using the current selection model.
* <p>
* Only selection models implementing {@link SelectionModel.Single} and
* {@link SelectionModel.Multi} are supported; for anything else, an
*
* @param row
* a row object
- * @return <code>true</code> iff the current selection changed
* @throws IllegalStateException
* if the current selection model is not an instance of
* {@link SelectionModel.Single} or {@link SelectionModel.Multi}
*/
- public boolean deselect(T row) {
- if (selectionModel instanceof SelectionModel.Single<?>) {
- return ((SelectionModel.Single<T>) selectionModel).deselect(row);
- } else if (selectionModel instanceof SelectionModel.Multi<?>) {
- return ((SelectionModel.Multi<T>) selectionModel)
- .deselect(Collections.singleton(row));
- } else {
- throw new IllegalStateException("Unsupported selection model");
- }
+ public void deselect(T row) {
+ getSelectionModel().deselect(row);
}
/**
- * Deselect all rows using the current selection model.
+ * Deselects all rows using the current selection model.
*
- * @param row
- * a row object
- * @return <code>true</code> iff the current selection changed
* @throws IllegalStateException
* if the current selection model is not an instance of
* {@link SelectionModel.Single} or {@link SelectionModel.Multi}
*/
- public boolean deselectAll() {
- if (selectionModel instanceof SelectionModel.Single<?>) {
- Single<T> single = ((SelectionModel.Single<T>) selectionModel);
- if (single.getSelectedRow() != null) {
- return single.deselect(single.getSelectedRow());
- } else {
- return false;
- }
- } else if (selectionModel instanceof SelectionModel.Multi<?>) {
- return ((SelectionModel.Multi<T>) selectionModel).deselectAll();
- } else {
- throw new IllegalStateException("Unsupported selection model");
- }
+ public void deselectAll() {
+ getSelectionModel().deselectAll();
}
/**
* {@link SelectionModel.Single}
*/
public T getSelectedRow() {
- if (selectionModel instanceof SelectionModel.Single<?>) {
- return ((SelectionModel.Single<T>) selectionModel).getSelectedRow();
- } else {
- throw new IllegalStateException(
- "Unsupported selection model; can not get single selected row");
- }
+ return getSelectionModel().getSelectedItems().stream().findFirst()
+ .orElse(null);
}
/**
* @return a non-null collection containing all currently selected rows.
*/
public Collection<T> getSelectedRows() {
- return selectionModel.getSelectedRows();
+ return getSelectionModel().getSelectedItems();
}
@Override
*
* @param handler
* a select all event handler
+ * @return the registration for the event
*/
public HandlerRegistration addSelectAllHandler(
SelectAllHandler<T> handler) {
}
/**
- * Sets the style generator that is used for generating styles for cells
+ * Sets the style generator that is used for generating styles for cells.
*
* @param cellStyleGenerator
* the cell style generator to set, or <code>null</code> to
}
/**
- * Gets the style generator that is used for generating styles for cells
+ * Gets the style generator that is used for generating styles for cells.
*
* @return the cell style generator, or <code>null</code> if no generator is
* set
}
/**
- * Sets the style generator that is used for generating styles for rows
+ * Sets the style generator that is used for generating styles for rows.
*
* @param rowStyleGenerator
* the row style generator to set, or <code>null</code> to remove
}
/**
- * Gets the style generator that is used for generating styles for rows
+ * Gets the style generator that is used for generating styles for rows.
*
* @return the row style generator, or <code>null</code> if no generator is
* set
* Sets the handler responsible for binding data and editor widgets to the
* editor.
*
- * @param rowHandler
+ * @param handler
* the new editor handler
*
* @throws IllegalStateException
if (visible && !isVisible) {
escalator.getBody().setSpacer(rowIndex, DETAILS_ROW_INITIAL_HEIGHT);
visibleDetails.add(rowIndexInteger);
- }
-
- else if (!visible && isVisible) {
+ } else if (!visible && isVisible) {
escalator.getBody().setSpacer(rowIndex, -1);
visibleDetails.remove(rowIndexInteger);
}
* Sets the buffered editor mode.
*
* @since 7.6
- * @param editorUnbuffered
+ * @param editorBuffered
* <code>true</code> to enable buffered editor,
* <code>false</code> to disable it
*/
* @see SingleSelectionChange
*/
@FunctionalInterface
- public interface SingleSelectionListener<T> extends
- EventListener<SingleSelectionChange<T>> {
+ public interface SingleSelectionListener<T>
+ extends EventListener<SingleSelectionChange<T>> {
@Override
public void accept(SingleSelectionChange<T> event);
@Override
public void select(String key) {
- doSelect(getData(key), true);
+ if (!Objects.equals(selectedItem, getData(key))) {
+ doSelect(getData(key), true);
+ }
}
@Override
public void deselect(String key) {
- if (getData(key).equals(selectedItem)) {
+ if (Objects.equals(selectedItem, getData(key))) {
doSelect(null, true);
}
}
}
@Override
- public void select(T value) {
- doSelect(value, false);
+ public void select(T item) {
+ doSelect(item, false);
}
@Override
public void deselect(T value) {
- if(Objects.equals(selectedItem,value))
+ if (Objects.equals(selectedItem, value)) {
doSelect(null, false);
+ }
}
@Override
* Selects the given item or deselects the current one if given
* {@code null}.
*
- * @param value
+ * @param item
* 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,
+ protected void doSelect(T item, boolean userOriginated) {
+ if (!Objects.equals(item, selectedItem)) {
+ if (selectedItem != null) {
+ refresh(selectedItem);
+ }
+ selectedItem = item;
+ if (selectedItem != null) {
+ refresh(selectedItem);
+ }
+ fireEvent(new SingleSelectionChange<>(getParent(), selectedItem,
userOriginated));
}
}
* updated data object
*/
public void refresh(T data) {
+ if (!handler.getActiveData().contains(data)) {
+ // Item is not currently available at the client-side
+ return;
+ }
+
if (updatedData.isEmpty()) {
markAsDirty();
}
* the selection model to use, not null
*/
protected void setSelectionModel(SELECTIONMODEL model) {
+ if (selectionModel != null) {
+ throw new IllegalStateException(
+ "A selection model can't be changed.");
+ }
+
Objects.requireNonNull(model, "selection model cannot be null");
selectionModel = model;
}
import com.vaadin.data.selection.SingleSelection;
import com.vaadin.server.AbstractExtension;
import com.vaadin.server.KeyMapper;
+import com.vaadin.server.data.DataGenerator;
import com.vaadin.server.data.DataSource;
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;
--- /dev/null
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.ui.Grid;
+
+public class GridSelectionTest {
+
+ Grid<String> grid;
+
+ @Before
+ public void setUp() {
+ grid = new Grid<>();
+ grid.setItems("Foo", "Bar");
+ }
+
+ @Test
+ public void testGridWithSingleSelection() {
+ Assert.assertFalse(grid.isSelected("Foo"));
+ grid.select("Foo");
+ Assert.assertTrue(grid.isSelected("Foo"));
+ Assert.assertEquals(1, grid.getSelectedItems().size());
+ Assert.assertEquals("Foo", grid.getSelectedItems().iterator().next());
+ grid.select("Bar");
+ Assert.assertFalse(grid.isSelected("Foo"));
+ Assert.assertTrue(grid.isSelected("Bar"));
+ grid.deselect("Bar");
+ Assert.assertFalse(grid.isSelected("Bar"));
+ Assert.assertEquals(0, grid.getSelectedItems().size());
+ }
+
+}
/*
* 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
/**
* 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
/**
* 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
*/
/**
* 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
public void select(T item);
+
}
/**
* <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
*/
/**
* 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);
+ /**
+ * Deselects all currently selected items.
+ */
+ public default void deselectAll() {
+ getSelectedItems().forEach(this::deselect);
+ }
+
/**
* 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
this.date = date;
}
+ @Override
+ public String toString() {
+ return "DataObject[" + rowNumber + "]";
+ }
+
static List<DataObject> generateObjects() {
List<DataObject> data = new ArrayList<>();
import java.util.stream.Stream;
import com.vaadin.annotations.Widgetset;
+import com.vaadin.data.selection.SingleSelection;
import com.vaadin.server.VaadinRequest;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.tests.components.AbstractTestUIWithLog;
grid = new Grid<>();
grid.setItems(data);
+ grid.addColumn("Column 0", String.class,
+ dataObj -> "(" + dataObj.getRowNumber() + ", 0)");
+ grid.addColumn("Column 1", String.class,
+ dataObj -> "(" + dataObj.getRowNumber() + ", 1)");
grid.addColumn("Row Number", Integer.class, DataObject::getRowNumber);
grid.addColumn("Date", Date.class, DataObject::getDate);
grid.addColumn("HTML String", String.class, DataObject::getHtmlString);
grid.addColumn("Small Random", Integer.class,
DataObject::getSmallRandom);
+ ((SingleSelection<DataObject>) grid.getSelectionModel())
+ .addSelectionListener(e -> log("Selected: " + e.getValue()));
+
layout.addComponent(createMenu());
layout.addComponent(grid);
addComponent(layout);
createStateMenu(componentMenu.addItem("State", null));
createSizeMenu(componentMenu.addItem("Size", null));
createDetailsMenu(componentMenu.addItem("Details", null));
+ createBodyMenu(componentMenu.addItem("Body rows", null));
return menu;
}
parent.addItem(name, menuItem -> method.accept(value));
}
+ private void createBodyMenu(MenuItem rowMenu) {
+ rowMenu.addItem("Toggle first row selection", menuItem -> {
+ DataObject item = data.get(0);
+ if (grid.isSelected(item)) {
+ grid.deselect(item);
+ } else {
+ grid.select(item);
+ }
+ });
+ }
+
/* DetailsGenerator related things */
private void createDetailsMenu(MenuItem detailsMenu) {
--- /dev/null
+package com.vaadin.tests.components.grid.basics;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.customelements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridRowElement;
+
+public class GridBasicSelectionTest extends GridBasicsTest {
+
+ @Test
+ public void testKeyboardWithSingleSelection() {
+
+ GridElement grid = getGridElement();
+ grid.getCell(3, 1).click();
+
+ assertTrue("Grid row 3 was not selected with clicking.",
+ grid.getRow(3).isSelected());
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not deselected with space key.",
+ !grid.getRow(3).isSelected());
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not selected with space key.",
+ grid.getRow(3).isSelected());
+
+ grid.scrollToRow(500);
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not deselected with space key.",
+ !grid.getRow(3).isSelected());
+ }
+
+ @Test
+ public void testSingleSelectionUpdatesFromServer() {
+ GridElement grid = getGridElement();
+ assertFalse("First row was selected from start",
+ grid.getRow(0).isSelected());
+ toggleFirstRowSelection();
+ assertTrue("First row was not selected.", getRow(0).isSelected());
+ assertTrue("Selection event was not correct",
+ logContainsText("Selected: DataObject[0]"));
+ grid.getCell(5, 0).click();
+ assertTrue("Fifth row was not selected.", getRow(5).isSelected());
+ assertFalse("First row was still selected.", getRow(0).isSelected());
+ assertTrue("Selection event was not correct",
+ logContainsText("Selected: DataObject[5]"));
+ grid.getCell(0, 6).click();
+ assertTrue("Selection event was not correct",
+ logContainsText("Selected: DataObject[0]"));
+ toggleFirstRowSelection();
+ assertTrue("Selection event was not correct",
+ logContainsText("Selected: null"));
+ assertFalse("First row was still selected.", getRow(0).isSelected());
+ assertFalse("Fifth row was still selected.", getRow(5).isSelected());
+
+ grid.scrollToRow(600);
+ grid.getCell(595, 3).click();
+ assertTrue("Row 595 was not selected.", getRow(595).isSelected());
+ assertTrue("Selection event was not correct",
+ logContainsText("Selected: DataObject[595]"));
+ toggleFirstRowSelection();
+ assertFalse("Row 595 was still selected.", getRow(595).isSelected());
+ assertTrue("First row was not selected.", getRow(0).isSelected());
+ assertTrue("Selection event was not correct",
+ logContainsText("Selected: DataObject[0]"));
+ }
+
+ private void toggleFirstRowSelection() {
+ selectMenuPath("Component", "Body rows", "Toggle first row selection");
+ }
+
+ private GridRowElement getRow(int i) {
+ return getGridElement().getRow(i);
+ }
+}