X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Futil%2FTableSorter.java;h=a6ead1524b1fc6ede8ccca6d7252d8bc967c74f0;hb=506d60f0e188723ddc91c26824b41ac7034df3fe;hp=469bd7f594ef7045d20a79d8b7e8221a0e3017d5;hpb=60f2d6c034560415fd0139c8bc7df0c19cae1186;p=jalview.git
diff --git a/src/jalview/util/TableSorter.java b/src/jalview/util/TableSorter.java
index 469bd7f..a6ead15 100755
--- a/src/jalview/util/TableSorter.java
+++ b/src/jalview/util/TableSorter.java
@@ -1,17 +1,17 @@
/*
- * Jalview - A Sequence Alignment Editor and Viewer
- * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
- *
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
+ * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
@@ -28,50 +28,39 @@ import javax.swing.event.*;
import javax.swing.table.*;
/**
- * TableSorter is a decorator for TableModels; adding sorting
- * functionality to a supplied TableModel. TableSorter does
- * not store or copy the data in its TableModel; instead it maintains
- * a map from the row indexes of the view to the row indexes of the
- * model. As requests are made of the sorter (like getValueAt(row, col))
- * they are passed to the underlying model after the row numbers
- * have been translated via the internal mapping array. This way,
- * the TableSorter appears to hold another copy of the table
- * with the rows in a different order.
- *
- * TableSorter registers itself as a listener to the underlying model,
- * just as the JTable itself would. Events recieved from the model
- * are examined, sometimes manipulated (typically widened), and then
- * passed on to the TableSorter's listeners (typically the JTable).
- * If a change to the model has invalidated the order of TableSorter's
- * rows, a note of this is made and the sorter will resort the
- * rows the next time a value is requested.
- *
- * When the tableHeader property is set, either by using the
- * setTableHeader() method or the two argument constructor, the
- * table header may be used as a complete UI for TableSorter.
- * The default renderer of the tableHeader is decorated with a renderer
- * that indicates the sorting status of each column. In addition,
- * a mouse listener is installed with the following behavior:
+ * TableSorter is a decorator for TableModels; adding sorting functionality to a
+ * supplied TableModel. TableSorter does not store or copy the data in its
+ * TableModel; instead it maintains a map from the row indexes of the view to
+ * the row indexes of the model. As requests are made of the sorter (like
+ * getValueAt(row, col)) they are passed to the underlying model after the row
+ * numbers have been translated via the internal mapping array. This way, the
+ * TableSorter appears to hold another copy of the table with the rows in a
+ * different order. TableSorter registers itself as a listener to the
+ * underlying model, just as the JTable itself would. Events recieved from the
+ * model are examined, sometimes manipulated (typically widened), and then
+ * passed on to the TableSorter's listeners (typically the JTable). If a change
+ * to the model has invalidated the order of TableSorter's rows, a note of this
+ * is made and the sorter will resort the rows the next time a value is
+ * requested. When the tableHeader property is set, either by using the
+ * setTableHeader() method or the two argument constructor, the table header may
+ * be used as a complete UI for TableSorter. The default renderer of the
+ * tableHeader is decorated with a renderer that indicates the sorting status of
+ * each column. In addition, a mouse listener is installed with the following
+ * behavior:
*
- * -
- * Mouse-click: Clears the sorting status of all other columns
- * and advances the sorting status of that column through three
- * values: {NOT_SORTED, ASCENDING, DESCENDING} (then back to
- * NOT_SORTED again).
- *
-
- * SHIFT-mouse-click: Clears the sorting status of all other columns
- * and cycles the sorting status of the column through the same
- * three values, in the opposite order: {NOT_SORTED, DESCENDING, ASCENDING}.
- *
-
- * CONTROL-mouse-click and CONTROL-SHIFT-mouse-click: as above except
- * that the changes to the column do not cancel the statuses of columns
- * that are already sorting - giving a way to initiate a compound
- * sort.
+ *
- Mouse-click: Clears the sorting status of all other columns and advances
+ * the sorting status of that column through three values: {NOT_SORTED,
+ * ASCENDING, DESCENDING} (then back to NOT_SORTED again).
+ *
- SHIFT-mouse-click: Clears the sorting status of all other columns and
+ * cycles the sorting status of the column through the same three values, in the
+ * opposite order: {NOT_SORTED, DESCENDING, ASCENDING}.
+ *
- CONTROL-mouse-click and CONTROL-SHIFT-mouse-click: as above except that
+ * the changes to the column do not cancel the statuses of columns that are
+ * already sorting - giving a way to initiate a compound sort.
*
- *
- * This is a long overdue rewrite of a class of the same name that
- * first appeared in the swing table demos in 1997.
- *
+ * This is a long overdue rewrite of a class of the same name that first
+ * appeared in the swing table demos in 1997.
+ *
* @author Philip Milne
* @author Brendon McLean
* @author Dan van Enckevort
@@ -79,24 +68,26 @@ import javax.swing.table.*;
* @version 2.0 02/27/04
*/
-public class TableSorter
- extends AbstractTableModel
+public class TableSorter extends AbstractTableModel
{
protected TableModel tableModel;
public static final int DESCENDING = -1;
+
public static final int NOT_SORTED = 0;
+
public static final int ASCENDING = 1;
- private static Directive EMPTY_DIRECTIVE = new Directive( -1, NOT_SORTED);
+ private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED);
public static final Comparator COMPARABLE_COMAPRATOR = new Comparator()
{
public int compare(Object o1, Object o2)
{
- return ( (Comparable) o1).compareTo(o2);
+ return ((Comparable) o1).compareTo(o2);
}
};
+
public static final Comparator LEXICAL_COMPARATOR = new Comparator()
{
public int compare(Object o1, Object o2)
@@ -106,12 +97,17 @@ public class TableSorter
};
private Row[] viewToModel;
+
private int[] modelToView;
private JTableHeader tableHeader;
+
private MouseListener mouseListener;
+
private TableModelListener tableModelListener;
+
private Map columnComparators = new HashMap();
+
private List sortingColumns = new ArrayList();
public TableSorter()
@@ -171,20 +167,20 @@ public class TableSorter
if (this.tableHeader != null)
{
this.tableHeader.removeMouseListener(mouseListener);
- TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer();
+ TableCellRenderer defaultRenderer = this.tableHeader
+ .getDefaultRenderer();
if (defaultRenderer instanceof SortableHeaderRenderer)
{
- this.tableHeader.setDefaultRenderer( ( (SortableHeaderRenderer)
- defaultRenderer).
- tableCellRenderer);
+ this.tableHeader
+ .setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer);
}
}
this.tableHeader = tableHeader;
if (this.tableHeader != null)
{
this.tableHeader.addMouseListener(mouseListener);
- this.tableHeader.setDefaultRenderer(
- new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer()));
+ this.tableHeader.setDefaultRenderer(new SortableHeaderRenderer(
+ this.tableHeader.getDefaultRenderer()));
}
}
@@ -243,7 +239,7 @@ public class TableSorter
return null;
}
return new Arrow(directive.direction == DESCENDING, size,
- sortingColumns.indexOf(directive));
+ sortingColumns.indexOf(directive));
}
private void cancelSorting()
@@ -356,8 +352,7 @@ public class TableSorter
// Helper classes
- private class Row
- implements Comparable
+ private class Row implements Comparable
{
private int modelIndex;
@@ -369,9 +364,9 @@ public class TableSorter
public int compareTo(Object o)
{
int row1 = modelIndex;
- int row2 = ( (Row) o).modelIndex;
+ int row2 = ((Row) o).modelIndex;
- for (Iterator it = sortingColumns.iterator(); it.hasNext(); )
+ for (Iterator it = sortingColumns.iterator(); it.hasNext();)
{
Directive directive = (Directive) it.next();
int column = directive.column;
@@ -398,15 +393,15 @@ public class TableSorter
}
if (comparison != 0)
{
- return directive.direction == DESCENDING ? -comparison : comparison;
+ return directive.direction == DESCENDING ? -comparison
+ : comparison;
}
}
return 0;
}
}
- private class TableModelHandler
- implements TableModelListener
+ private class TableModelHandler implements TableModelListener
{
public void tableChanged(TableModelEvent e)
{
@@ -431,12 +426,16 @@ public class TableSorter
// We can map a cell event through to the view without widening
// when the following conditions apply:
//
- // a) all the changes are on one row (e.getFirstRow() == e.getLastRow()) and,
- // b) all the changes are in one column (column != TableModelEvent.ALL_COLUMNS) and,
- // c) we are not sorting on that column (getSortingStatus(column) == NOT_SORTED) and,
+ // a) all the changes are on one row (e.getFirstRow() == e.getLastRow())
+ // and,
+ // b) all the changes are in one column (column !=
+ // TableModelEvent.ALL_COLUMNS) and,
+ // c) we are not sorting on that column (getSortingStatus(column) ==
+ // NOT_SORTED) and,
// d) a reverse lookup will not trigger a sort (modelToView != null)
//
- // Note: INSERT and DELETE events fail this test as they have column == ALL_COLUMNS.
+ // Note: INSERT and DELETE events fail this test as they have column ==
+ // ALL_COLUMNS.
//
// The last check, for (modelToView != null) is to see if modelToView
// is already allocated. If we don't do this check; sorting can become
@@ -448,26 +447,25 @@ public class TableSorter
// clause avoids this problem.
int column = e.getColumn();
if (e.getFirstRow() == e.getLastRow()
- && column != TableModelEvent.ALL_COLUMNS
- && getSortingStatus(column) == NOT_SORTED
- && modelToView != null)
+ && column != TableModelEvent.ALL_COLUMNS
+ && getSortingStatus(column) == NOT_SORTED
+ && modelToView != null)
{
int viewIndex = getModelToView()[e.getFirstRow()];
- fireTableChanged(new TableModelEvent(TableSorter.this,
- viewIndex, viewIndex,
- column, e.getType()));
+ fireTableChanged(new TableModelEvent(TableSorter.this, viewIndex,
+ viewIndex, column, e.getType()));
return;
}
- // Something has happened to the data that may have invalidated the row order.
+ // Something has happened to the data that may have invalidated the row
+ // order.
clearSortingState();
fireTableDataChanged();
return;
}
}
- private class MouseHandler
- extends MouseAdapter
+ private class MouseHandler extends MouseAdapter
{
public void mouseClicked(MouseEvent e)
{
@@ -482,8 +480,10 @@ public class TableSorter
{
cancelSorting();
}
- // Cycle the sorting states through {NOT_SORTED, ASCENDING, DESCENDING} or
- // {NOT_SORTED, DESCENDING, ASCENDING} depending on whether shift is pressed.
+ // Cycle the sorting states through {NOT_SORTED, ASCENDING, DESCENDING}
+ // or
+ // {NOT_SORTED, DESCENDING, ASCENDING} depending on whether shift is
+ // pressed.
status = status + (e.isShiftDown() ? -1 : 1);
status = (status + 4) % 3 - 1; // signed mod, returning {-1, 0, 1}
setSortingStatus(column, status);
@@ -491,11 +491,12 @@ public class TableSorter
}
}
- private static class Arrow
- implements Icon
+ private static class Arrow implements Icon
{
private boolean descending;
+
private int size;
+
private int priority;
public Arrow(boolean descending, int size, int priority)
@@ -539,7 +540,7 @@ public class TableSorter
g.drawLine(dx, 0, 0, 0);
g.setColor(color);
- g.translate( -x, -y);
+ g.translate(-x, -y);
}
public int getIconWidth()
@@ -553,8 +554,7 @@ public class TableSorter
}
}
- private class SortableHeaderRenderer
- implements TableCellRenderer
+ private class SortableHeaderRenderer implements TableCellRenderer
{
private TableCellRenderer tableCellRenderer;
@@ -564,20 +564,19 @@ public class TableSorter
}
public Component getTableCellRendererComponent(JTable table,
- Object value,
- boolean isSelected,
- boolean hasFocus,
- int row,
- int column)
+ Object value, boolean isSelected, boolean hasFocus, int row,
+ int column)
{
Component c = tableCellRenderer.getTableCellRendererComponent(table,
- value, isSelected, hasFocus, row, column);
+ value, isSelected, hasFocus, row, column);
if (c instanceof JLabel)
{
JLabel l = (JLabel) c;
l.setHorizontalTextPosition(JLabel.LEFT);
int modelColumn = table.convertColumnIndexToModel(column);
- l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize()));
+ l
+ .setIcon(getHeaderRendererIcon(modelColumn, l.getFont()
+ .getSize()));
}
return c;
}
@@ -586,6 +585,7 @@ public class TableSorter
private static class Directive
{
private int column;
+
private int direction;
public Directive(int column, int direction)