SelectionManager.java revision b9c6617bdc063b3b4aa760a0a45190ee069139fd
1package autotest.common.table;
2
3import autotest.common.Utils;
4import autotest.common.table.DataTable.TableWidgetFactory;
5import autotest.common.table.TableClickWidget.TableWidgetClickListener;
6import autotest.common.ui.TableSelectionPanel.SelectionPanelListener;
7
8import com.google.gwt.json.client.JSONObject;
9import com.google.gwt.user.client.ui.CheckBox;
10import com.google.gwt.user.client.ui.Widget;
11
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.List;
16import java.util.Set;
17
18/**
19 * This class manages a selection of rows on a DataTable.  It keeps track of selected objects and
20 * takes care of highlighting rows.  It can also be used for a DynamicTable, with support for paging
21 * etc., if you use DynamicTableSelectionManager.
22 *
23 * For convenience, it can also act as a TableWidgetFactory to supply checkboxes for selecting rows
24 * in a table, and as a SelectionPanelListener.
25 *
26 */
27public class SelectionManager implements TableWidgetFactory, TableWidgetClickListener,
28                                         SelectionPanelListener {
29    private Set<JSONObject> selectedObjects = new JSONObjectSet<JSONObject>();
30    private boolean selectOnlyOne = false;
31    private DataTable attachedTable;
32    private List<SelectionListener> listeners = new ArrayList<SelectionListener>();
33    private SelectableRowFilter selectableRowFilter;
34
35    public interface SelectionListener {
36        public void onAdd(Collection<JSONObject> objects);
37        public void onRemove(Collection<JSONObject> objects);
38    }
39
40    public interface SelectableRowFilter {
41        public boolean isRowSelectable(JSONObject row);
42    }
43
44    public SelectionManager(DataTable table, boolean selectOnlyOne) {
45        attachedTable = table;
46        this.selectOnlyOne = selectOnlyOne;
47    }
48
49    public void setSelectableRowFilter(SelectableRowFilter filter) {
50        selectableRowFilter = filter;
51    }
52
53    public void refreshSelection() {
54        for (int i = 0; i < attachedTable.getRowCount(); i++) {
55            JSONObject row = attachedTable.getRow(i);
56            if (!isSelectable(row)) {
57                continue;
58            }
59            if (selectedObjects.contains(row)) {
60                attachedTable.highlightRow(i);
61            } else {
62                attachedTable.unhighlightRow(i);
63            }
64        }
65        attachedTable.refreshWidgets();
66    }
67
68    private boolean isSelectable(JSONObject row) {
69        if (selectableRowFilter != null) {
70            return selectableRowFilter.isRowSelectable(row);
71        }
72        return true;
73    }
74
75    public void selectObject(JSONObject object) {
76        selectObjects(Utils.wrapObjectWithList(object));
77    }
78
79    public void selectObjects(Collection<? extends JSONObject> objects) {
80        if (selectOnlyOne) {
81            assert objects.size() == 1;
82            deselectAll();
83        }
84        addOrRemoveObjects(objects, true);
85    }
86
87    public void deselectObject(JSONObject object) {
88        deselectObjects(Utils.wrapObjectWithList(object));
89    }
90
91    public void deselectObjects(Collection<JSONObject> objects) {
92        addOrRemoveObjects(objects, false);
93    }
94
95    protected void addOrRemoveObjects(Collection<? extends JSONObject> objects,
96                                      boolean add) {
97        List<JSONObject> actuallyUsed = new ArrayList<JSONObject>();
98        for (JSONObject object : objects) {
99            if (!isSelectable(object)) {
100                continue;
101            }
102            boolean used = false;
103            if (add) {
104                used = selectedObjects.add(object);
105            } else {
106                used = selectedObjects.remove(object);
107            }
108            if (used) {
109                actuallyUsed.add(object);
110            }
111        }
112        notifyListeners(actuallyUsed, add);
113    }
114
115    /*
116     * Select all objects in the table.
117     */
118    public void selectAll() {
119        selectVisible();
120    }
121
122    public void deselectAll() {
123        List<JSONObject> removed = new ArrayList<JSONObject>(selectedObjects);
124        selectedObjects.clear();
125        notifyListeners(removed, false);
126    }
127
128    public void selectVisible() {
129        selectObjects(attachedTable.getAllRows());
130    }
131
132    public void toggleSelected(JSONObject object) {
133        if (selectedObjects.contains(object))
134            deselectObject(object);
135        else
136            selectObject(object);
137    }
138
139    public JSONObject getSelectedOne() {
140        assert selectOnlyOne;
141        if (selectedObjects.isEmpty())
142            return null;
143        return selectedObjects.iterator().next();
144    }
145
146    public Set<JSONObject> getSelectedObjects() {
147        return Collections.unmodifiableSet(selectedObjects);
148    }
149
150    public boolean isEmpty() {
151        return selectedObjects.isEmpty();
152    }
153
154    public void addListener(SelectionListener listener) {
155        listeners.add(listener);
156    }
157
158    public void removeListener(SelectionListener listener) {
159        listeners.remove(listener);
160    }
161
162    protected void notifyListeners(Collection<JSONObject> objects,
163                                   boolean add) {
164        refreshSelection();
165        for (SelectionListener listener : listeners) {
166            if (add)
167                listener.onAdd(objects);
168            else
169                listener.onRemove(objects);
170        }
171    }
172
173    // code for acting as a TableWidgetFactory/TableWidgetClickListener
174
175    public Widget createWidget(int row, int cell, JSONObject rowObject) {
176        if (!isSelectable(rowObject)) {
177            return null;
178        }
179
180        CheckBox checkBox = new CheckBox();
181        if(selectedObjects.contains(rowObject)) {
182            checkBox.setValue(true);
183        }
184        return new TableClickWidget(checkBox, this, row, cell);
185    }
186
187    public void onClick(TableClickWidget widget) {
188        toggleSelected(attachedTable.getRow(widget.getRow()));
189        refreshSelection();
190    }
191
192    // code for acting as a SelectionPanelListener
193
194    public void onSelectAll(boolean visibleOnly) {
195        if (visibleOnly) {
196            selectVisible();
197        } else {
198            selectAll();
199        }
200    }
201
202    public void onSelectNone() {
203        deselectAll();
204    }
205}
206