package com.robonobo.gui.model;
import java.util.*;
import javax.swing.AbstractListModel;
@SuppressWarnings("serial")
public class SortedListModel<T extends Comparable<T>> extends AbstractListModel implements Iterable<T> {
protected List<T> list = new ArrayList<T>();
public SortedListModel() {
}
public void insertSorted(T element) {
// If we're empty, just whack it in
if (list.size() == 0) {
list.add(element);
fireIntervalAdded(this, list.size()-1, list.size()-1);
return;
}
// If it's before the first one or after the last one, put at start/end
if (element.compareTo(list.get(0)) < 0) {
list.add(0, element);
fireIntervalAdded(this, 0, 0);
return;
}
if (element.compareTo(list.get(list.size() - 1)) >= 0) {
list.add(element);
fireIntervalAdded(this, list.size()-1, list.size()-1);
return;
}
// Pick the index by binary search and plonk it in
int idx = insertIndex(element, 0, getSize() - 1);
list.add(idx, element);
fireIntervalAdded(this, idx, idx);
}
public void remove(T element) {
int idx = list.indexOf(element);
if(idx >= 0) {
list.remove(idx);
fireIntervalRemoved(this, idx, idx);
}
}
@Override
public int getSize() {
return list.size();
}
public void clear() {
int oldSz = list.size();
list.clear();
if(oldSz > 0)
fireIntervalRemoved(this, 0, oldSz-1);
}
/**
* Returns the object that will be displayed in the list (might not be the same as get(index), e.g.
* get(index).someProperty)
*/
@Override
public Object getElementAt(int index) {
return get(index);
}
/**
* Returns the object in our sorted list
*/
protected T get(int index) {
return list.get(index);
}
private int insertIndex(T element, int low, int high) {
if (low == high || high == (low + 1))
return high;
int pivot = (high + low) / 2;
T pEl = list.get(pivot);
int cmp = element.compareTo(pEl);
if (cmp == 0)
return pivot;
else if (cmp < 0)
return insertIndex(element, low, pivot);
else
return insertIndex(element, pivot, high);
}
@Override
public Iterator<T> iterator() {
return list.iterator();
}
}