2 * Copyright 2000-2018 Vaadin Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
16 package com.vaadin.v7.client.widget.grid.selection;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.LinkedHashSet;
23 import java.util.List;
26 import com.vaadin.client.data.DataSource.RowHandle;
27 import com.vaadin.v7.client.renderers.Renderer;
28 import com.vaadin.v7.client.widgets.Grid;
31 * Multi-row selection model.
36 public class SelectionModelMulti<T> extends AbstractRowHandleSelectionModel<T>
37 implements SelectionModel.Multi.Batched<T>, HasUserSelectionAllowed<T> {
39 private final LinkedHashSet<RowHandle<T>> selectedRows;
40 private Renderer<Boolean> renderer;
43 private boolean batchStarted = false;
44 private final LinkedHashSet<RowHandle<T>> selectionBatch = new LinkedHashSet<RowHandle<T>>();
45 private final LinkedHashSet<RowHandle<T>> deselectionBatch = new LinkedHashSet<RowHandle<T>>();
47 /* Event handling for selection with space key */
48 private SpaceSelectHandler<T> spaceSelectHandler;
49 private boolean userSelectionAllowed = true;
51 public SelectionModelMulti() {
54 selectedRows = new LinkedHashSet<RowHandle<T>>();
58 public boolean isSelected(T row) {
59 return isSelectedByHandle(grid.getDataSource().getHandle(row));
63 public Renderer<Boolean> getSelectionColumnRenderer() {
68 public void setGrid(Grid<T> grid) {
69 if (this.grid != null && grid != null) {
70 // Trying to replace grid
71 throw new IllegalStateException(
72 "Selection model is already attached to a grid. "
73 + "Remove the selection model first from "
74 + "the grid and then add it.");
78 if (this.grid != null) {
79 spaceSelectHandler = new SpaceSelectHandler<T>(grid);
80 this.renderer = new MultiSelectionRenderer<T>(grid);
82 spaceSelectHandler.removeHandler();
83 spaceSelectHandler = null;
90 public boolean select(T... rows) {
92 throw new IllegalArgumentException("Rows cannot be null");
94 return select(Arrays.asList(rows));
98 public boolean deselect(T... rows) {
100 throw new IllegalArgumentException("Rows cannot be null");
102 return deselect(Arrays.asList(rows));
106 public boolean deselectAll() {
107 if (!selectedRows.isEmpty()) {
109 @SuppressWarnings("unchecked")
110 final LinkedHashSet<RowHandle<T>> selectedRowsClone = (LinkedHashSet<RowHandle<T>>) selectedRows
112 SelectionEvent<T> event = new SelectionEvent<T>(grid, null,
113 getSelectedRows(), isBeingBatchSelected());
114 selectedRows.clear();
116 if (isBeingBatchSelected()) {
117 selectionBatch.clear();
118 deselectionBatch.clear();
119 deselectionBatch.addAll(selectedRowsClone);
122 grid.fireEvent(event);
129 public boolean select(Collection<T> rows) {
131 throw new IllegalArgumentException("Rows cannot be null");
134 Set<T> added = new LinkedHashSet<T>();
137 RowHandle<T> handle = grid.getDataSource().getHandle(row);
138 if (selectByHandle(handle)) {
143 if (!added.isEmpty()) {
144 grid.fireEvent(new SelectionEvent<T>(grid, added, null,
145 isBeingBatchSelected()));
153 public boolean deselect(Collection<T> rows) {
155 throw new IllegalArgumentException("Rows cannot be null");
158 Set<T> removed = new LinkedHashSet<T>();
161 RowHandle<T> handle = grid.getDataSource().getHandle(row);
162 if (deselectByHandle(handle)) {
167 if (!removed.isEmpty()) {
168 grid.fireEvent(new SelectionEvent<T>(grid, null, removed,
169 isBeingBatchSelected()));
175 protected boolean isSelectedByHandle(RowHandle<T> handle) {
176 return selectedRows.contains(handle);
180 protected boolean selectByHandle(RowHandle<T> handle) {
181 if (selectedRows.add(handle)) {
184 if (isBeingBatchSelected()) {
185 deselectionBatch.remove(handle);
186 selectionBatch.add(handle);
195 protected boolean deselectByHandle(RowHandle<T> handle) {
196 if (selectedRows.remove(handle)) {
198 if (!isBeingBatchSelected()) {
201 selectionBatch.remove(handle);
202 deselectionBatch.add(handle);
210 public Collection<T> getSelectedRows() {
211 Set<T> selected = new LinkedHashSet<T>();
212 for (RowHandle<T> handle : selectedRows) {
213 selected.add(handle.getRow());
215 return Collections.unmodifiableSet(selected);
219 public void reset() {
224 public void startBatchSelect() {
225 assert !isBeingBatchSelected() : "Batch has already been started";
230 public void commitBatchSelect() {
231 assert isBeingBatchSelected() : "Batch was never started";
232 if (!isBeingBatchSelected()) {
236 batchStarted = false;
238 final Collection<T> added = getSelectedRowsBatch();
239 selectionBatch.clear();
241 final Collection<T> removed = getDeselectedRowsBatch();
243 // unpin deselected rows
244 for (RowHandle<T> handle : deselectionBatch) {
247 deselectionBatch.clear();
249 grid.fireEvent(new SelectionEvent<T>(grid, added, removed,
250 isBeingBatchSelected()));
254 public boolean isBeingBatchSelected() {
259 public Collection<T> getSelectedRowsBatch() {
260 return rowHandlesToRows(selectionBatch);
264 public Collection<T> getDeselectedRowsBatch() {
265 return rowHandlesToRows(deselectionBatch);
268 private List<T> rowHandlesToRows(Collection<RowHandle<T>> rowHandles) {
269 List<T> rows = new ArrayList<T>(rowHandles.size());
270 for (RowHandle<T> handle : rowHandles) {
271 rows.add(handle.getRow());
277 public boolean isUserSelectionAllowed() {
278 return userSelectionAllowed;
282 public void setUserSelectionAllowed(boolean userSelectionAllowed) {
283 this.userSelectionAllowed = userSelectionAllowed;