/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package uk.ac.cam.echo.TouchClient; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.concurrent.CopyOnWriteArrayList; import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener.Change; import javafx.collections.ObservableList; /** *a class that implements the ObservableList interface so that messages can be stored and passed tot the list view * * @author Philip * @param <T> the type of the list members */ public class MessageDisplayList<T> implements ObservableList<T>{ private final List<T> mlist; private final List<InvalidationListener> mInvalidationListenerList; private final List<ListChangeListener> mListChangeListenerList; private void onChange(Change change){ synchronized (mListChangeListenerList){ for (ListChangeListener l:mListChangeListenerList){ l.onChanged(change); } } } private void onInvalidation(Observable ob){ for (InvalidationListener l : mInvalidationListenerList){ l.invalidated(ob); } } public MessageDisplayList(){ mlist = new CopyOnWriteArrayList(); mInvalidationListenerList = new CopyOnWriteArrayList(); mListChangeListenerList = new CopyOnWriteArrayList(); } @Override public void addListener(ListChangeListener<? super T> ll) { synchronized (this){ mListChangeListenerList.add(ll); } } @Override public void removeListener(ListChangeListener<? super T> ll) { synchronized (this){ mListChangeListenerList.remove(ll); } } @Override public boolean addAll(T... es) { for (T e : es) { if (!add(e)){ return false; } } return true; } @Override public boolean setAll(T... es) { clear(); return addAll(es); } @Override public boolean setAll(Collection<? extends T> clctn) { clear(); return addAll(clctn); } @Override public boolean removeAll(T... es) { for (T e : es) { if (!remove(e)){ return false; } } return true; } @Override public boolean retainAll(T... es) { ArrayList<T> c = new ArrayList(); c.addAll(Arrays.asList(es)); return retainAll(c); } @Override public void remove(int i, int i1) { removeAll(subList(i,i1)); } @Override public int size() { synchronized (this){ return mlist.size(); } } @Override public boolean isEmpty() { synchronized (this){ return mlist.isEmpty(); } } @Override public boolean contains(Object o) { synchronized (this){ return mlist.contains(o); } } @Override public Iterator<T> iterator() { synchronized (this){ return mlist.iterator(); } } @Override public Object[] toArray() { synchronized (this){ return mlist.toArray(); } } @Override public <T> T[] toArray(T[] a) { synchronized (this){ return mlist.toArray(a); } } @Override public boolean add(T e) { synchronized (this){ boolean out = mlist.add(e); AddChange<T> c = new AddChange(e,this); onChange(c); return out; } } @Override public boolean remove(Object o) { synchronized (this){ boolean out = mlist.remove(o); RemoveChange<T> c = new RemoveChange((T)o,this); onChange(c); return out; } } public boolean removeQuiet(Object o) { synchronized (this){ boolean out = mlist.remove(o); return out; } } @Override public boolean containsAll(Collection<?> c) { synchronized (this){ return mlist.containsAll(c); } } @Override public boolean addAll(Collection<? extends T> c) { for (T s:c){ if (!(add(s))){ return false; } } return true; } @Override public boolean addAll(int index, Collection<? extends T> c) { Iterator i = c.iterator(); int temp = 0; while (temp<index && i.hasNext()){ i.next(); } while (i.hasNext()){ if(!(add((T)(i.next())))){ return false; } } return true; } @Override public boolean removeAll(Collection<?> c) { Iterator i = c.iterator(); while (i.hasNext()){ if (!add((T)(i.next()))){ return false; } } return true; } @Override public boolean retainAll(Collection<?> c) { return mlist.retainAll(c); } @Override public void clear() { synchronized (this){ synchronized (mListChangeListenerList){ mlist.clear(); for (InvalidationListener l:mInvalidationListenerList){ l.invalidated(this); } } } } @Override public T get(int index) { synchronized (this){ return mlist.get(index); } } @Override public T set(int index, T element) { synchronized (this){ return mlist.set(index, element); } } @Override public void add(int index, T element) { synchronized (this){ AddChange<T> c = new AddChange(element,this); onChange(c); mlist.add(index, element); } } @Override public T remove(int index) { synchronized (this){ RemoveChange<T> c = new RemoveChange(get(index),this); onChange(c); return mlist.remove(index); } } @Override public int indexOf(Object o) { synchronized (this){ return mlist.indexOf(o); } } @Override public int lastIndexOf(Object o) { synchronized (this){ return mlist.lastIndexOf(o); } } @Override public ListIterator<T> listIterator() { synchronized (this){ return mlist.listIterator(); } } @Override public ListIterator<T> listIterator(int index) { synchronized (this){ return mlist.listIterator(index); } } @Override public List<T> subList(int fromIndex, int toIndex) { synchronized (this){ return mlist.subList(fromIndex, toIndex); } } @Override public void addListener(InvalidationListener il) { synchronized (this){ mInvalidationListenerList.add(il); } } @Override public void removeListener(InvalidationListener il) { synchronized (this){ mInvalidationListenerList.remove(il); } } }