The Java Program: SortTableModel.java

  1 import java.util.TreeSet;
  2 import javax.swing.table.TableModel;
  3 import javax.swing.table.AbstractTableModel;
  4 
  5 /*
  6   A TableModel for JTable that wraps an underlying table model
  7   with the additional functionality for sorting.
  8 */
  9 
 10 public class SortTableModel extends AbstractTableModel {
 11 
 12    protected TableModel sourceModel;
 13    protected int[] indexValues;
 14 
 15    public SortTableModel (final TableModel model) {
 16       sourceModel = model;
 17    }
 18 
 19    public int getRowCount()    { return sourceModel.getRowCount(); }
 20 
 21    public int getColumnCount() { return sourceModel.getColumnCount(); }
 22 
 23    public Object getValueAt (int row, final int column) {
 24       if (indexValues != null) {
 25          row = getSourceIndex(row);
 26       }
 27       return sourceModel.getValueAt (row, column);
 28    }
 29 
 30    public void setValueAt (final Object value, int row, final int column) {
 31       if (indexValues != null) {
 32          row = getSourceIndex(row);
 33       }
 34       sourceModel.setValueAt (value, row, column);
 35    }
 36 
 37    public boolean isCellEditable (final int row, final int column) {
 38       return sourceModel.isCellEditable (row, column);
 39    } 
 40 
 41    public String getColumnName (final int column) {
 42       return sourceModel.getColumnName (column);
 43    } 
 44 
 45    public Class getColumnClass (final int column) {
 46       return sourceModel.getColumnClass(column);
 47    }
 48 
 49    public int getSourceIndex (final int index) {
 50       if (indexValues != null) {
 51          return indexValues[index];
 52       }
 53       return -1;
 54    }
 55 
 56    /*
 57      State of the all colunms.  All the sorted columns must share this information.
 58      If "sortColumn"==-1, then no column is sorted.
 59      If "sortColumn">=0,  then the column is sorted, according to bool "sortAscending"
 60    */
 61 
 62    private int sortColumn = -1;
 63    private boolean sortAscending = true;
 64 
 65    public int getSortColumn () { return sortColumn; }
 66    public boolean isSortAscending () { return sortAscending; }
 67 
 68    private void columnSelected (final int column) {
 69       if (column != sortColumn) {
 70          /*
 71            The column "column" must now be sorted, because either some other column
 72            was sorted before or no column is sorted.  It is sorted first in
 73            ascending order.
 74          */
 75          sortColumn = column;
 76          sortAscending = true;
 77       } else {
 78          /*
 79            The column "column" must already sorted.  Now sort it in descending order,
 80            or if all ready in descending order, then restore original order.
 81          */
 82          sortAscending = !sortAscending;
 83          if (sortAscending) sortColumn = -1;
 84       }
 85    }
 86 
 87    public final void sortRows (final int column) {
 88       columnSelected (column);
 89       if (sortColumn == -1) {
 90          clearSort();
 91       } else {
 92          sortRows (sortColumn, sortAscending);
 93       }
 94    }
 95 
 96    private void sortRows (final int column, final boolean ascending) {
 97       final TreeSet<SortedItemHolder> sortedList = new TreeSet<SortedItemHolder>();
 98       final int count = getRowCount();
 99       for (int i=0; i<count; i++) {
100          // We assume all objects in the column are comparable!
101          final Comparable<Object> o =
102             (Comparable<Object>) sourceModel.getValueAt (i, column);
103          final SortedItemHolder holder = new SortedItemHolder (o, i);
104          sortedList.add (holder);
105       }
106       indexValues = new int[count];
107       int index = (ascending ? 0 : count-1);
108       for (SortedItemHolder holder: sortedList) {
109          indexValues[index] = holder.position;
110          index += (ascending ? 1 : -1);
111       } 
112       fireTableDataChanged();
113    } 
114 
115    public final void clearSort() {
116       indexValues = null;  // now getValue will return data in original order
117       fireTableDataChanged();
118    }
119 
120    private static class SortedItemHolder implements Comparable <SortedItemHolder> {
121 
122       public final Comparable<Object> value;
123       public final int position;
124 
125       public SortedItemHolder (final Comparable<Object> v, final int p) {
126          this.value = v;
127          this.position = p;
128       }
129 
130       public int compareTo (final SortedItemHolder holder) {
131          final int result = value.compareTo (holder.value);
132          if (result == 0) {
133             return (position < holder.position) ? -1 : 1;
134          } else {
135             return result;
136          }
137       }
138 
139       // Not very promising
140       public int hashCode() {
141          return position;
142       }
143 
144       @Override
145       public boolean equals (final Object comp) {
146          if (comp instanceof SortedItemHolder) {
147             final SortedItemHolder other = (SortedItemHolder) comp;
148             if ((position==other.position) && (value==other.value)) {
149                return true;
150             }
151          }
152          return false;
153       }
154    }
155 }