package uihelpers; import helpers.IObservable; import helpers.Observable.IObserver; import helpers.StatusObject; import helpers.StatusObject.ChangeType; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jface.viewers.TableViewer; public class DelayedTableUpdater<V> implements IObserver<StatusObject>{ private final TableViewer viewer; private final Object synchUser = new Object(); private final Set<V> add = new HashSet<V>(); private final Set<V> update = new HashSet<V>(); private final Set<V> remove = new HashSet<V>(); private final int delay; private List<DUEntry<V>> delayed = new ArrayList<DUEntry<V>>(); public DelayedTableUpdater(TableViewer viewer) { this(viewer,500); } public DelayedTableUpdater(TableViewer viewer,int millisecDelay) { this.viewer = viewer; this.delay = millisecDelay; } private boolean isPresent(V v) { return add.contains(v)|| update.contains(v)|| remove.contains(v); } public void put(ChangeType ct,V v) { switch(ct) { case ADDED: add(v); break; case CHANGED: change(v); break; case REMOVED: remove(v); break; } } @SuppressWarnings("unchecked") @Override public void update(IObservable<StatusObject> o, StatusObject arg) { put(arg.getType(),(V)arg.getValue()); } public void add(V v) { synchronized(synchUser) { if (isPresent(v)) { delayed.add(new DUEntry<V>(v, ChangeType.ADDED)); } else { add.add(v); } } ensureUpdate(); } public void change(V v) { synchronized(synchUser) { if (add.contains(v) || remove.contains(v)) { delayed.add(new DUEntry<V>(v, ChangeType.CHANGED)); } else { update.add(v); } } ensureUpdate(); } public void remove(V v) { synchronized(synchUser) { if (isPresent(v)) { delayed.add(new DUEntry<V>(v, ChangeType.REMOVED)); } else { remove.add(v); } } ensureUpdate(); } private void ensureUpdate() { new SUIJob(viewer.getControl()) { //"bulkupdate" public void run() { synchronized(synchUser) { while (!add.isEmpty() || !update.isEmpty() || !remove.isEmpty()) { if (!add.isEmpty()) { viewer.add(add.toArray()); add.clear(); } if (!update.isEmpty()) { Object[] updateArray = update.toArray(); // viewer.update(update.toArray(), null); viewer.remove(updateArray); viewer.add(updateArray); update.clear(); } if (!remove.isEmpty()) { viewer.remove(remove.toArray()); remove.clear(); } if (!delayed.isEmpty()) { List<DUEntry<V>> dlaLocal = delayed; delayed = new ArrayList<DUEntry<V>>(); for (DUEntry<V> de: dlaLocal) { put(de.ct,de.v); } } } } updateDone(); } }.scheduleIfNotRunning(delay,this); } /** * discards all running add/update/delete ops */ public void clear() { synchronized(synchUser) { add.clear(); update.clear(); remove.clear(); } } /** * method for overwriting.. called by UI thread.. */ protected void updateDone() {} private static class DUEntry<V> { private final V v; private final ChangeType ct; public DUEntry(V v, ChangeType ct) { super(); this.v = v; this.ct = ct; } } }