SelectionManager.java revision c3afc99304e4d6ada6eaaaa0a1513e408ecca6eb
1package autotest.common.table; 2 3import autotest.common.JSONArrayList; 4import autotest.common.Utils; 5import autotest.common.table.DataSource.DataCallback; 6 7import com.google.gwt.json.client.JSONArray; 8import com.google.gwt.json.client.JSONObject; 9 10import java.util.AbstractSet; 11import java.util.ArrayList; 12import java.util.Collection; 13import java.util.HashMap; 14import java.util.Iterator; 15import java.util.List; 16import java.util.Map; 17import java.util.Set; 18 19public class SelectionManager { 20 protected Set<JSONObject> selectedObjects = new JSONValueSet<JSONObject>(); 21 protected boolean selectOnlyOne = false; 22 protected DynamicTable attachedTable; 23 protected List<SelectionListener> listeners = 24 new ArrayList<SelectionListener>(); 25 26 public interface SelectionListener { 27 public void onAdd(Collection<JSONObject> objects); 28 public void onRemove(Collection<JSONObject> objects); 29 } 30 31 32 /** 33 * Set that hashes JSONObjects by their ID, so that identical objects get 34 * matched together. 35 */ 36 static class JSONValueSet<T extends JSONObject> extends AbstractSet<T> { 37 protected Map<String, T> backingMap = new HashMap<String, T>(); 38 39 protected String getKey(Object obj) { 40 return ((JSONObject) obj).get("id").toString(); 41 } 42 43 @Override 44 public boolean add(T arg0) { 45 return backingMap.put(getKey(arg0), arg0) == null; 46 } 47 48 @Override 49 public Iterator<T> iterator() { 50 return backingMap.values().iterator(); 51 } 52 53 @Override 54 public boolean remove(Object arg0) { 55 return backingMap.remove(getKey(arg0)) != null; 56 } 57 58 @Override 59 public boolean contains(Object o) { 60 return backingMap.containsKey(getKey(o)); 61 } 62 63 @Override 64 public int size() { 65 return backingMap.size(); 66 } 67 } 68 69 public SelectionManager(DynamicTable table, boolean selectOnlyOne) { 70 attachedTable = table; 71 this.selectOnlyOne = selectOnlyOne; 72 } 73 74 public void refreshSelection() { 75 for (int i = 0; i < attachedTable.getRowCount(); i++) { 76 if (selectedObjects.contains(attachedTable.getRow(i))) 77 attachedTable.highlightRow(i); 78 else 79 attachedTable.unhighlightRow(i); 80 } 81 } 82 83 public void selectObject(JSONObject object) { 84 selectObjects(Utils.wrapObjectWithList(object)); 85 } 86 87 public void selectObjects(Collection<? extends JSONObject> objects) { 88 if (selectOnlyOne) { 89 assert objects.size() == 1; 90 deselectAll(); 91 } 92 addOrRemoveObjects(objects, true); 93 } 94 95 public void deselectObject(JSONObject object) { 96 deselectObjects(Utils.wrapObjectWithList(object)); 97 } 98 99 public void deselectObjects(Collection<JSONObject> objects) { 100 addOrRemoveObjects(objects, false); 101 } 102 103 protected void addOrRemoveObjects(Collection<? extends JSONObject> objects, 104 boolean add) { 105 List<JSONObject> actuallyUsed = new ArrayList<JSONObject>(); 106 for (JSONObject object : objects) { 107 boolean used = false; 108 if (add) 109 used = selectedObjects.add(object); 110 else 111 used = selectedObjects.remove(object); 112 if (used) 113 actuallyUsed.add(object); 114 } 115 notifyListeners(actuallyUsed, add); 116 } 117 118 /* 119 * Select all objects covering all pages, not just the currently displayed page in the table. 120 */ 121 public void selectAll() { 122 DataSource dataSource = attachedTable.getDataSource(); 123 dataSource.getPage(null, null, null, new DataCallback() { 124 public void handlePage(JSONArray data) { 125 selectObjects(new JSONArrayList<JSONObject>(data)); 126 } 127 128 public void onGotData(int totalCount) {} 129 }); 130 } 131 132 public void deselectAll() { 133 List<JSONObject> removed = new ArrayList<JSONObject>(selectedObjects); 134 selectedObjects.clear(); 135 notifyListeners(removed, false); 136 } 137 138 public void selectVisible() { 139 List<JSONObject> rowsToAdd = new ArrayList<JSONObject>(); 140 for (int i = 0; i < attachedTable.getRowCount(); i++) { 141 rowsToAdd.add(attachedTable.getRow(i)); 142 } 143 selectObjects(rowsToAdd); 144 } 145 146 public void toggleSelected(JSONObject object) { 147 if (selectedObjects.contains(object)) 148 deselectObject(object); 149 else 150 selectObject(object); 151 } 152 153 public JSONObject getSelectedOne() { 154 assert selectOnlyOne; 155 if (selectedObjects.isEmpty()) 156 return null; 157 return selectedObjects.iterator().next(); 158 } 159 160 public Set<JSONObject> getSelectedObjects() { 161 // TODO: return a copy or an unmodifiable view 162 return selectedObjects; 163 } 164 165 public boolean isEmpty() { 166 return selectedObjects.isEmpty(); 167 } 168 169 public void addListener(SelectionListener listener) { 170 listeners.add(listener); 171 } 172 173 public void removeListener(SelectionListener listener) { 174 listeners.remove(listener); 175 } 176 177 protected void notifyListeners(JSONObject object, boolean add) { 178 List<JSONObject> objectList = new ArrayList<JSONObject>(); 179 objectList.add(object); 180 notifyListeners(objectList, add); 181 } 182 183 protected void notifyListeners(Collection<JSONObject> objects, 184 boolean add) { 185 for (SelectionListener listener : listeners) { 186 if (add) 187 listener.onAdd(objects); 188 else 189 listener.onRemove(objects); 190 } 191 } 192} 193