package org.obo.app.model; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collections; import java.util.EventListener; import java.util.List; import org.jdesktop.observablecollections.ObservableList; import org.jdesktop.observablecollections.ObservableListListener; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.ObservableElementList; import ca.odell.glazedlists.event.ListEvent; import ca.odell.glazedlists.event.ListEventListener; /** * @author Jim Balhoff */ public class ObservableEventList<T extends PropertyChangeObject> extends ObservableElementList<T> implements ObservableList<T> { private final List<T> observedElements; private final List<ObservableListListener> listeners = new ArrayList<ObservableListListener>(); public ObservableEventList(EventList<T> source) { super(source, new PropertyChangeConnector<T>()); this.observedElements = new ArrayList<T>(source); this.addListEventListener(new ListChangeListener()); } @Override public void addObservableListListener(ObservableListListener listener) { this.listeners.add(listener); } @Override public void removeObservableListListener(ObservableListListener listener) { this.listeners.remove(listener); } @Override public boolean supportsElementPropertyChanged() { return true; } public void listDidChange(ListEvent<T> listChanges) { while (listChanges.hasNext()) { listChanges.next(); final int index = listChanges.getIndex(); if (listChanges.getType() == ListEvent.UPDATE) { this.observedElements.set(index, listChanges.getSourceList().get(index)); this.fireListElementPropertyChanged(index); } else if (listChanges.getType() == ListEvent.DELETE) { final T deleted = this.observedElements.get(index); this.observedElements.remove(index); this.fireListElementsRemoved(listChanges.getIndex(), Collections.singletonList(deleted)); } else if (listChanges.getType() == ListEvent.INSERT) { this.observedElements.add(index, listChanges.getSourceList().get(index)); this.fireListElementsAdded(index, 1); } } } @Override protected boolean isWritable() { return true; } private void fireListElementPropertyChanged(int index) { for (ObservableListListener listener : this.listeners) { listener.listElementPropertyChanged(this, index); } } private void fireListElementsRemoved(int index, List<T> oldElements) { for (ObservableListListener listener : this.listeners) { listener.listElementsRemoved(this, index, oldElements); } } private void fireListElementsAdded(int index, int length) { for (ObservableListListener listener : this.listeners) { listener.listElementsAdded(this, index, length); } } private class ListChangeListener implements ListEventListener<T> { @Override public void listChanged(ListEvent<T> listChanges) { listDidChange(listChanges); } } private static class PropertyChangeConnector<T extends PropertyChangeObject> implements Connector<T> { private ObservableElementList<T> list; @Override public EventListener installListener(T element) { final Observer observer = new Observer(); element.addPropertyChangeListener(observer); return observer; } @Override public void setObservableElementList(ObservableElementList<T> list) { this.list = list; } @Override public void uninstallListener(T element, EventListener listener) { element.removePropertyChangeListener((Observer)listener); } private class Observer implements PropertyChangeListener { @Override @SuppressWarnings("unchecked") public void propertyChange(PropertyChangeEvent evt) { list.elementChanged((T)evt.getSource()); } } } }