Home » openjdk-7 » javax » swing » table » [javadoc | source]

    1   /*
    2    * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   package javax.swing.table;
   26   
   27   import java.text.Collator;
   28   import java.util;
   29   import javax.swing.DefaultRowSorter;
   30   import javax.swing.RowFilter;
   31   import javax.swing.SortOrder;
   32   
   33   /**
   34    * An implementation of <code>RowSorter</code> that provides sorting
   35    * and filtering using a <code>TableModel</code>.
   36    * The following example shows adding sorting to a <code>JTable</code>:
   37    * <pre>
   38    *   TableModel myModel = createMyTableModel();
   39    *   JTable table = new JTable(myModel);
   40    *   table.setRowSorter(new TableRowSorter(myModel));
   41    * </pre>
   42    * This will do all the wiring such that when the user does the appropriate
   43    * gesture, such as clicking on the column header, the table will
   44    * visually sort.
   45    * <p>
   46    * <code>JTable</code>'s row-based methods and <code>JTable</code>'s
   47    * selection model refer to the view and not the underlying
   48    * model. Therefore, it is necessary to convert between the two.  For
   49    * example, to get the selection in terms of <code>myModel</code>
   50    * you need to convert the indices:
   51    * <pre>
   52    *   int[] selection = table.getSelectedRows();
   53    *   for (int i = 0; i &lt; selection.length; i++) {
   54    *     selection[i] = table.convertRowIndexToModel(selection[i]);
   55    *   }
   56    * </pre>
   57    * Similarly to select a row in <code>JTable</code> based on
   58    * a coordinate from the underlying model do the inverse:
   59    * <pre>
   60    *   table.setRowSelectionInterval(table.convertRowIndexToView(row),
   61    *                                 table.convertRowIndexToView(row));
   62    * </pre>
   63    * <p>
   64    * The previous example assumes you have not enabled filtering.  If you
   65    * have enabled filtering <code>convertRowIndexToView</code> will return
   66    * -1 for locations that are not visible in the view.
   67    * <p>
   68    * <code>TableRowSorter</code> uses <code>Comparator</code>s for doing
   69    * comparisons. The following defines how a <code>Comparator</code> is
   70    * chosen for a column:
   71    * <ol>
   72    * <li>If a <code>Comparator</code> has been specified for the column by the
   73    *     <code>setComparator</code> method, use it.
   74    * <li>If the column class as returned by <code>getColumnClass</code> is
   75    *     <code>String</code>, use the <code>Comparator</code> returned by
   76    *     <code>Collator.getInstance()</code>.
   77    * <li>If the column class implements <code>Comparable</code>, use a
   78    *     <code>Comparator</code> that invokes the <code>compareTo</code>
   79    *     method.
   80    * <li>If a <code>TableStringConverter</code> has been specified, use it
   81    *     to convert the values to <code>String</code>s and then use the
   82    *     <code>Comparator</code> returned by <code>Collator.getInstance()</code>.
   83    * <li>Otherwise use the <code>Comparator</code> returned by
   84    *     <code>Collator.getInstance()</code> on the results from
   85    *     calling <code>toString</code> on the objects.
   86    * </ol>
   87    * <p>
   88    * In addition to sorting <code>TableRowSorter</code> provides the ability
   89    * to filter.  A filter is specified using the <code>setFilter</code>
   90    * method. The following example will only show rows containing the string
   91    * "foo":
   92    * <pre>
   93    *   TableModel myModel = createMyTableModel();
   94    *   TableRowSorter sorter = new TableRowSorter(myModel);
   95    *   sorter.setRowFilter(RowFilter.regexFilter(".*foo.*"));
   96    *   JTable table = new JTable(myModel);
   97    *   table.setRowSorter(sorter);
   98    * </pre>
   99    * <p>
  100    * If the underlying model structure changes (the
  101    * <code>modelStructureChanged</code> method is invoked) the following
  102    * are reset to their default values: <code>Comparator</code>s by
  103    * column, current sort order, and whether each column is sortable. The default
  104    * sort order is natural (the same as the model), and columns are
  105    * sortable by default.
  106    * <p>
  107    * <code>TableRowSorter</code> has one formal type parameter: the type
  108    * of the model.  Passing in a type that corresponds exactly to your
  109    * model allows you to filter based on your model without casting.
  110    * Refer to the documentation of <code>RowFilter</code> for an example
  111    * of this.
  112    * <p>
  113    * <b>WARNING:</b> <code>DefaultTableModel</code> returns a column
  114    * class of <code>Object</code>.  As such all comparisons will
  115    * be done using <code>toString</code>.  This may be unnecessarily
  116    * expensive.  If the column only contains one type of value, such as
  117    * an <code>Integer</code>, you should override <code>getColumnClass</code> and
  118    * return the appropriate <code>Class</code>.  This will dramatically
  119    * increase the performance of this class.
  120    *
  121    * @param <M> the type of the model, which must be an implementation of
  122    *            <code>TableModel</code>
  123    * @see javax.swing.JTable
  124    * @see javax.swing.RowFilter
  125    * @see javax.swing.table.DefaultTableModel
  126    * @see java.text.Collator
  127    * @see java.util.Comparator
  128    * @since 1.6
  129    */
  130   public class TableRowSorter<M extends TableModel> extends DefaultRowSorter<M, Integer> {
  131       /**
  132        * Comparator that uses compareTo on the contents.
  133        */
  134       private static final Comparator COMPARABLE_COMPARATOR =
  135               new ComparableComparator();
  136   
  137       /**
  138        * Underlying model.
  139        */
  140       private M tableModel;
  141   
  142       /**
  143        * For toString conversions.
  144        */
  145       private TableStringConverter stringConverter;
  146   
  147   
  148       /**
  149        * Creates a <code>TableRowSorter</code> with an empty model.
  150        */
  151       public TableRowSorter() {
  152           this(null);
  153       }
  154   
  155       /**
  156        * Creates a <code>TableRowSorter</code> using <code>model</code>
  157        * as the underlying <code>TableModel</code>.
  158        *
  159        * @param model the underlying <code>TableModel</code> to use,
  160        *        <code>null</code> is treated as an empty model
  161        */
  162       public TableRowSorter(M model) {
  163           setModel(model);
  164       }
  165   
  166       /**
  167        * Sets the <code>TableModel</code> to use as the underlying model
  168        * for this <code>TableRowSorter</code>.  A value of <code>null</code>
  169        * can be used to set an empty model.
  170        *
  171        * @param model the underlying model to use, or <code>null</code>
  172        */
  173       public void setModel(M model) {
  174           tableModel = model;
  175           setModelWrapper(new TableRowSorterModelWrapper());
  176       }
  177   
  178       /**
  179        * Sets the object responsible for converting values from the
  180        * model to strings.  If non-<code>null</code> this
  181        * is used to convert any object values, that do not have a
  182        * registered <code>Comparator</code>, to strings.
  183        *
  184        * @param stringConverter the object responsible for converting values
  185        *        from the model to strings
  186        */
  187       public void setStringConverter(TableStringConverter stringConverter) {
  188           this.stringConverter = stringConverter;
  189       }
  190   
  191       /**
  192        * Returns the object responsible for converting values from the
  193        * model to strings.
  194        *
  195        * @return object responsible for converting values to strings.
  196        */
  197       public TableStringConverter getStringConverter() {
  198           return stringConverter;
  199       }
  200   
  201       /**
  202        * Returns the <code>Comparator</code> for the specified
  203        * column.  If a <code>Comparator</code> has not been specified using
  204        * the <code>setComparator</code> method a <code>Comparator</code>
  205        * will be returned based on the column class
  206        * (<code>TableModel.getColumnClass</code>) of the specified column.
  207        * If the column class is <code>String</code>,
  208        * <code>Collator.getInstance</code> is returned.  If the
  209        * column class implements <code>Comparable</code> a private
  210        * <code>Comparator</code> is returned that invokes the
  211        * <code>compareTo</code> method.  Otherwise
  212        * <code>Collator.getInstance</code> is returned.
  213        *
  214        * @throws IndexOutOfBoundsException {@inheritDoc}
  215        */
  216       public Comparator<?> getComparator(int column) {
  217           Comparator comparator = super.getComparator(column);
  218           if (comparator != null) {
  219               return comparator;
  220           }
  221           Class columnClass = getModel().getColumnClass(column);
  222           if (columnClass == String.class) {
  223               return Collator.getInstance();
  224           }
  225           if (Comparable.class.isAssignableFrom(columnClass)) {
  226               return COMPARABLE_COMPARATOR;
  227           }
  228           return Collator.getInstance();
  229       }
  230   
  231       /**
  232        * {@inheritDoc}
  233        *
  234        * @throws IndexOutOfBoundsException {@inheritDoc}
  235        */
  236       protected boolean useToString(int column) {
  237           Comparator comparator = super.getComparator(column);
  238           if (comparator != null) {
  239               return false;
  240           }
  241           Class columnClass = getModel().getColumnClass(column);
  242           if (columnClass == String.class) {
  243               return false;
  244           }
  245           if (Comparable.class.isAssignableFrom(columnClass)) {
  246               return false;
  247           }
  248           return true;
  249       }
  250   
  251       /**
  252        * Implementation of DefaultRowSorter.ModelWrapper that delegates to a
  253        * TableModel.
  254        */
  255       private class TableRowSorterModelWrapper extends ModelWrapper<M,Integer> {
  256           public M getModel() {
  257               return tableModel;
  258           }
  259   
  260           public int getColumnCount() {
  261               return (tableModel == null) ? 0 : tableModel.getColumnCount();
  262           }
  263   
  264           public int getRowCount() {
  265               return (tableModel == null) ? 0 : tableModel.getRowCount();
  266           }
  267   
  268           public Object getValueAt(int row, int column) {
  269               return tableModel.getValueAt(row, column);
  270           }
  271   
  272           public String getStringValueAt(int row, int column) {
  273               TableStringConverter converter = getStringConverter();
  274               if (converter != null) {
  275                   // Use the converter
  276                   String value = converter.toString(
  277                           tableModel, row, column);
  278                   if (value != null) {
  279                       return value;
  280                   }
  281                   return "";
  282               }
  283   
  284               // No converter, use getValueAt followed by toString
  285               Object o = getValueAt(row, column);
  286               if (o == null) {
  287                   return "";
  288               }
  289               String string = o.toString();
  290               if (string == null) {
  291                   return "";
  292               }
  293               return string;
  294           }
  295   
  296           public Integer getIdentifier(int index) {
  297               return index;
  298           }
  299       }
  300   
  301   
  302       private static class ComparableComparator implements Comparator {
  303           @SuppressWarnings("unchecked")
  304           public int compare(Object o1, Object o2) {
  305               return ((Comparable)o1).compareTo(o2);
  306           }
  307       }
  308   }

Home » openjdk-7 » javax » swing » table » [javadoc | source]