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