package eu.doppel_helix.netbeans.mantisintegration.swing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.ComboBoxModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
public class ListBackedComboBoxModel<E> implements ComboBoxModel<E> {
private final List<E> backingList = new ArrayList<>();
private final Class<E> klass;
Set<ListDataListener> listener = new HashSet<>();
private E selectedItem = null;
public ListBackedComboBoxModel(Class<E> klass) {
this.klass = klass;
}
/**
* Set the backing List for this ComboBoxModel (the list is copied)
*
* @param elements
*/
public void setBackingList(final List<E> elements) {
int oldLength = backingList.size();
backingList.clear();
if (oldLength > 0) {
fireIntervalRemoved(0, oldLength - 1);
}
backingList.addAll(elements);
if (selectedItem != null) {
if (!backingList.contains(selectedItem)) {
backingList.add(selectedItem);
}
}
if (backingList.size() > 0) {
fireIntervalAdded(0, backingList.size() - 1);
}
}
public void addElement(final E element) {
backingList.add(element);
fireIntervalAdded(backingList.size() - 1, backingList.size() - 1);
}
public void addElement(final int position, final E element) {
backingList.add(position, element);
fireIntervalAdded(position, position);
}
/**
* Retrieve an unmodifiable reference to the backing list
*
* WARNING: This reference is only unmodifiable for the caller!
*
* @return
*/
public List<E> getBackingList() {
return Collections.unmodifiableList(backingList);
}
protected void fireIntervalAdded(int start, int end) {
Iterator<ListDataListener> i = listener.iterator();
ListDataEvent lde = new ListDataEvent(
this, ListDataEvent.INTERVAL_ADDED, start, end);
while(i.hasNext()) {
i.next().intervalAdded(lde);
}
}
protected void fireIntervalRemoved(int start, int end) {
Iterator<ListDataListener> i = listener.iterator();
ListDataEvent lde = new ListDataEvent(
this, ListDataEvent.INTERVAL_REMOVED, start, end);
while(i.hasNext()) {
i.next().intervalAdded(lde);
}
}
protected void fireContentsChanged(int start, int end) {
Iterator<ListDataListener> i = listener.iterator();
ListDataEvent lde = new ListDataEvent(
this, ListDataEvent.CONTENTS_CHANGED, start, end);
while (i.hasNext()) {
i.next().contentsChanged(lde);
}
}
@Override
public void setSelectedItem(Object anItem) {
if(anItem != null && (! (klass.isAssignableFrom(anItem.getClass())))) {
throw new IllegalArgumentException("Wrong type for List");
} else {
selectedItem = (E) anItem;
if(selectedItem != null) {
if(! backingList.contains(selectedItem)) {
backingList.add(selectedItem);
fireIntervalAdded(backingList.size() - 1, backingList.size() - 1);
}
}
if(! backingList.isEmpty()) {
fireContentsChanged(0, backingList.size() - 1);
}
}
}
@Override
public E getSelectedItem() {
return selectedItem;
}
@Override
public int getSize() {
return backingList.size();
}
@Override
public E getElementAt(int index) {
return backingList.get(index);
}
@Override
public void addListDataListener(ListDataListener l) {
listener.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listener.remove(l);
}
}