]> source.dussan.org Git - vaadin-framework.git/blob
5d6a0305fd5d1af35aaf097240440475ea1ad0e2
[vaadin-framework.git] /
1 /*
2  * Copyright 2000-2018 Vaadin Ltd.
3  *
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
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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
14  * the License.
15  */
16 package com.vaadin.v7.client.widget.grid.selection;
17
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;
24 import java.util.Set;
25
26 import com.vaadin.client.data.DataSource.RowHandle;
27 import com.vaadin.v7.client.renderers.Renderer;
28 import com.vaadin.v7.client.widgets.Grid;
29
30 /**
31  * Multi-row selection model.
32  *
33  * @author Vaadin Ltd
34  * @since 7.4
35  */
36 public class SelectionModelMulti<T> extends AbstractRowHandleSelectionModel<T>
37         implements SelectionModel.Multi.Batched<T>, HasUserSelectionAllowed<T> {
38
39     private final LinkedHashSet<RowHandle<T>> selectedRows;
40     private Renderer<Boolean> renderer;
41     private Grid<T> grid;
42
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>>();
46
47     /* Event handling for selection with space key */
48     private SpaceSelectHandler<T> spaceSelectHandler;
49     private boolean userSelectionAllowed = true;
50
51     public SelectionModelMulti() {
52         grid = null;
53         renderer = null;
54         selectedRows = new LinkedHashSet<RowHandle<T>>();
55     }
56
57     @Override
58     public boolean isSelected(T row) {
59         return isSelectedByHandle(grid.getDataSource().getHandle(row));
60     }
61
62     @Override
63     public Renderer<Boolean> getSelectionColumnRenderer() {
64         return renderer;
65     }
66
67     @Override
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.");
75         }
76
77         this.grid = grid;
78         if (this.grid != null) {
79             spaceSelectHandler = new SpaceSelectHandler<T>(grid);
80             this.renderer = new MultiSelectionRenderer<T>(grid);
81         } else {
82             spaceSelectHandler.removeHandler();
83             spaceSelectHandler = null;
84             this.renderer = null;
85         }
86
87     }
88
89     @Override
90     public boolean select(T... rows) {
91         if (rows == null) {
92             throw new IllegalArgumentException("Rows cannot be null");
93         }
94         return select(Arrays.asList(rows));
95     }
96
97     @Override
98     public boolean deselect(T... rows) {
99         if (rows == null) {
100             throw new IllegalArgumentException("Rows cannot be null");
101         }
102         return deselect(Arrays.asList(rows));
103     }
104
105     @Override
106     public boolean deselectAll() {
107         if (!selectedRows.isEmpty()) {
108
109             @SuppressWarnings("unchecked")
110             final LinkedHashSet<RowHandle<T>> selectedRowsClone = (LinkedHashSet<RowHandle<T>>) selectedRows
111                     .clone();
112             SelectionEvent<T> event = new SelectionEvent<T>(grid, null,
113                     getSelectedRows(), isBeingBatchSelected());
114             selectedRows.clear();
115
116             if (isBeingBatchSelected()) {
117                 selectionBatch.clear();
118                 deselectionBatch.clear();
119                 deselectionBatch.addAll(selectedRowsClone);
120             }
121
122             grid.fireEvent(event);
123             return true;
124         }
125         return false;
126     }
127
128     @Override
129     public boolean select(Collection<T> rows) {
130         if (rows == null) {
131             throw new IllegalArgumentException("Rows cannot be null");
132         }
133
134         Set<T> added = new LinkedHashSet<T>();
135
136         for (T row : rows) {
137             RowHandle<T> handle = grid.getDataSource().getHandle(row);
138             if (selectByHandle(handle)) {
139                 added.add(row);
140             }
141         }
142
143         if (!added.isEmpty()) {
144             grid.fireEvent(new SelectionEvent<T>(grid, added, null,
145                     isBeingBatchSelected()));
146
147             return true;
148         }
149         return false;
150     }
151
152     @Override
153     public boolean deselect(Collection<T> rows) {
154         if (rows == null) {
155             throw new IllegalArgumentException("Rows cannot be null");
156         }
157
158         Set<T> removed = new LinkedHashSet<T>();
159
160         for (T row : rows) {
161             RowHandle<T> handle = grid.getDataSource().getHandle(row);
162             if (deselectByHandle(handle)) {
163                 removed.add(row);
164             }
165         }
166
167         if (!removed.isEmpty()) {
168             grid.fireEvent(new SelectionEvent<T>(grid, null, removed,
169                     isBeingBatchSelected()));
170             return true;
171         }
172         return false;
173     }
174
175     protected boolean isSelectedByHandle(RowHandle<T> handle) {
176         return selectedRows.contains(handle);
177     }
178
179     @Override
180     protected boolean selectByHandle(RowHandle<T> handle) {
181         if (selectedRows.add(handle)) {
182             handle.pin();
183
184             if (isBeingBatchSelected()) {
185                 deselectionBatch.remove(handle);
186                 selectionBatch.add(handle);
187             }
188
189             return true;
190         }
191         return false;
192     }
193
194     @Override
195     protected boolean deselectByHandle(RowHandle<T> handle) {
196         if (selectedRows.remove(handle)) {
197
198             if (!isBeingBatchSelected()) {
199                 handle.unpin();
200             } else {
201                 selectionBatch.remove(handle);
202                 deselectionBatch.add(handle);
203             }
204             return true;
205         }
206         return false;
207     }
208
209     @Override
210     public Collection<T> getSelectedRows() {
211         Set<T> selected = new LinkedHashSet<T>();
212         for (RowHandle<T> handle : selectedRows) {
213             selected.add(handle.getRow());
214         }
215         return Collections.unmodifiableSet(selected);
216     }
217
218     @Override
219     public void reset() {
220         deselectAll();
221     }
222
223     @Override
224     public void startBatchSelect() {
225         assert !isBeingBatchSelected() : "Batch has already been started";
226         batchStarted = true;
227     }
228
229     @Override
230     public void commitBatchSelect() {
231         assert isBeingBatchSelected() : "Batch was never started";
232         if (!isBeingBatchSelected()) {
233             return;
234         }
235
236         batchStarted = false;
237
238         final Collection<T> added = getSelectedRowsBatch();
239         selectionBatch.clear();
240
241         final Collection<T> removed = getDeselectedRowsBatch();
242
243         // unpin deselected rows
244         for (RowHandle<T> handle : deselectionBatch) {
245             handle.unpin();
246         }
247         deselectionBatch.clear();
248
249         grid.fireEvent(new SelectionEvent<T>(grid, added, removed,
250                 isBeingBatchSelected()));
251     }
252
253     @Override
254     public boolean isBeingBatchSelected() {
255         return batchStarted;
256     }
257
258     @Override
259     public Collection<T> getSelectedRowsBatch() {
260         return rowHandlesToRows(selectionBatch);
261     }
262
263     @Override
264     public Collection<T> getDeselectedRowsBatch() {
265         return rowHandlesToRows(deselectionBatch);
266     }
267
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());
272         }
273         return rows;
274     }
275
276     @Override
277     public boolean isUserSelectionAllowed() {
278         return userSelectionAllowed;
279     }
280
281     @Override
282     public void setUserSelectionAllowed(boolean userSelectionAllowed) {
283         this.userSelectionAllowed = userSelectionAllowed;
284     }
285 }