Home » openjdk-7 » javax » swing » [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;
   26   
   27   import javax.swing.SortOrder;
   28   import javax.swing.event;
   29   import java.util;
   30   
   31   /**
   32    * <code>RowSorter</code> provides the basis for sorting and filtering.
   33    * Beyond creating and installing a <code>RowSorter</code>, you very rarely
   34    * need to interact with one directly.  Refer to
   35    * {@link javax.swing.table.TableRowSorter TableRowSorter} for a concrete
   36    * implementation of <code>RowSorter</code> for <code>JTable</code>.
   37    * <p>
   38    * <code>RowSorter</code>'s primary role is to provide a mapping between
   39    * two coordinate systems: that of the view (for example a
   40    * <code>JTable</code>) and that of the underlying data source, typically a
   41    * model.
   42    * <p>
   43    * The view invokes the following methods on the <code>RowSorter</code>:
   44    * <ul>
   45    * <li><code>toggleSortOrder</code> &#151; The view invokes this when the
   46    *     appropriate user gesture has occurred to trigger a sort.  For example,
   47    *     the user clicked a column header in a table.
   48    * <li>One of the model change methods &#151; The view invokes a model
   49    *     change method when the underlying model
   50    *     has changed.  There may be order dependencies in how the events are
   51    *     delivered, so a <code>RowSorter</code> should not update its mapping
   52    *     until one of these methods is invoked.
   53    * </ul>
   54    * Because the view makes extensive use of  the
   55    * <code>convertRowIndexToModel</code>,
   56    * <code>convertRowIndexToView</code> and <code>getViewRowCount</code> methods,
   57    * these methods need to be fast.
   58    * <p>
   59    * <code>RowSorter</code> provides notification of changes by way of
   60    * <code>RowSorterListener</code>.  Two types of notification are sent:
   61    * <ul>
   62    * <li><code>RowSorterEvent.Type.SORT_ORDER_CHANGED</code> &#151; notifies
   63    *     listeners that the sort order has changed.  This is typically followed
   64    *     by a notification that the sort has changed.
   65    * <li><code>RowSorterEvent.Type.SORTED</code> &#151; notifies listeners that
   66    *     the mapping maintained by the <code>RowSorter</code> has changed in
   67    *     some way.
   68    * </ul>
   69    * <code>RowSorter</code> implementations typically don't have a one-to-one
   70    * mapping with the underlying model, but they can.
   71    * For example, if a database does the sorting,
   72    * <code>toggleSortOrder</code> might call through to the database
   73    * (on a background thread), and override the mapping methods to return the
   74    * argument that is passed in.
   75    * <p>
   76    * Concrete implementations of <code>RowSorter</code>
   77    * need to reference a model such as <code>TableModel</code> or
   78    * <code>ListModel</code>.  The view classes, such as
   79    * <code>JTable</code> and <code>JList</code>, will also have a
   80    * reference to the model.  To avoid ordering dependencies,
   81    * <code>RowSorter</code> implementations should not install a
   82    * listener on the model.  Instead the view class will call into the
   83    * <code>RowSorter</code> when the model changes.  For
   84    * example, if a row is updated in a <code>TableModel</code>
   85    * <code>JTable</code> invokes <code>rowsUpdated</code>.
   86    * When the model changes, the view may call into any of the following methods:
   87    * <code>modelStructureChanged</code>, <code>allRowsChanged</code>,
   88    * <code>rowsInserted</code>, <code>rowsDeleted</code> and
   89    * <code>rowsUpdated</code>.
   90    *
   91    * @param <M> the type of the underlying model
   92    * @see javax.swing.table.TableRowSorter
   93    * @since 1.6
   94    */
   95   public abstract class RowSorter<M> {
   96       private EventListenerList listenerList = new EventListenerList();
   97   
   98       /**
   99        * Creates a <code>RowSorter</code>.
  100        */
  101       public RowSorter() {
  102       }
  103   
  104       /**
  105        * Returns the underlying model.
  106        *
  107        * @return the underlying model
  108        */
  109       public abstract M getModel();
  110   
  111       /**
  112        * Reverses the sort order of the specified column.  It is up to
  113        * subclasses to provide the exact behavior when invoked.  Typically
  114        * this will reverse the sort order from ascending to descending (or
  115        * descending to ascending) if the specified column is already the
  116        * primary sorted column; otherwise, makes the specified column
  117        * the primary sorted column, with an ascending sort order.  If
  118        * the specified column is not sortable, this method has no
  119        * effect.
  120        * <p>
  121        * If this results in changing the sort order and sorting, the
  122        * appropriate <code>RowSorterListener</code> notification will be
  123        * sent.
  124        *
  125        * @param column the column to toggle the sort ordering of, in
  126        *        terms of the underlying model
  127        * @throws IndexOutOfBoundsException if column is outside the range of
  128        *         the underlying model
  129        */
  130       public abstract void toggleSortOrder(int column);
  131   
  132       /**
  133        * Returns the location of <code>index</code> in terms of the
  134        * underlying model.  That is, for the row <code>index</code> in
  135        * the coordinates of the view this returns the row index in terms
  136        * of the underlying model.
  137        *
  138        * @param index the row index in terms of the underlying view
  139        * @return row index in terms of the view
  140        * @throws IndexOutOfBoundsException if <code>index</code> is outside the
  141        *         range of the view
  142        */
  143       public abstract int convertRowIndexToModel(int index);
  144   
  145       /**
  146        * Returns the location of <code>index</code> in terms of the
  147        * view.  That is, for the row <code>index</code> in the
  148        * coordinates of the underlying model this returns the row index
  149        * in terms of the view.
  150        *
  151        * @param index the row index in terms of the underlying model
  152        * @return row index in terms of the view, or -1 if index has been
  153        *         filtered out of the view
  154        * @throws IndexOutOfBoundsException if <code>index</code> is outside
  155        *         the range of the model
  156        */
  157       public abstract int convertRowIndexToView(int index);
  158   
  159       /**
  160        * Sets the current sort keys.
  161        *
  162        * @param keys the new <code>SortKeys</code>; <code>null</code>
  163        *        is a shorthand for specifying an empty list,
  164        *        indicating that the view should be unsorted
  165        */
  166       public abstract void setSortKeys(List<? extends SortKey> keys);
  167   
  168       /**
  169        * Returns the current sort keys.  This must return a {@code
  170        * non-null List} and may return an unmodifiable {@code List}. If
  171        * you need to change the sort keys, make a copy of the returned
  172        * {@code List}, mutate the copy and invoke {@code setSortKeys}
  173        * with the new list.
  174        *
  175        * @return the current sort order
  176        */
  177       public abstract List<? extends SortKey> getSortKeys();
  178   
  179       /**
  180        * Returns the number of rows in the view.  If the contents have
  181        * been filtered this might differ from the row count of the
  182        * underlying model.
  183        *
  184        * @return number of rows in the view
  185        * @see #getModelRowCount
  186        */
  187       public abstract int getViewRowCount();
  188   
  189       /**
  190        * Returns the number of rows in the underlying model.
  191        *
  192        * @return number of rows in the underlying model
  193        * @see #getViewRowCount
  194        */
  195       public abstract int getModelRowCount();
  196   
  197       /**
  198        * Invoked when the underlying model structure has completely
  199        * changed.  For example, if the number of columns in a
  200        * <code>TableModel</code> changed, this method would be invoked.
  201        * <p>
  202        * You normally do not call this method.  This method is public
  203        * to allow view classes to call it.
  204        */
  205       public abstract void modelStructureChanged();
  206   
  207       /**
  208        * Invoked when the contents of the underlying model have
  209        * completely changed. The structure of the table is the same,
  210        * only the contents have changed. This is typically sent when it
  211        * is too expensive to characterize the change in terms of the
  212        * other methods.
  213        * <p>
  214        * You normally do not call this method.  This method is public
  215        * to allow view classes to call it.
  216        */
  217       public abstract void allRowsChanged();
  218   
  219       /**
  220        * Invoked when rows have been inserted into the underlying model
  221        * in the specified range (inclusive).
  222        * <p>
  223        * The arguments give the indices of the effected range.
  224        * The first argument is in terms of the model before the change, and
  225        * must be less than or equal to the size of the model before the change.
  226        * The second argument is in terms of the model after the change and must
  227        * be less than the size of the model after the change. For example,
  228        * if you have a 5-row model and add 3 items to the end of the model
  229        * the indices are 5, 7.
  230        * <p>
  231        * You normally do not call this method.  This method is public
  232        * to allow view classes to call it.
  233        *
  234        * @param firstRow the first row
  235        * @param endRow the last row
  236        * @throws IndexOutOfBoundsException if either argument is invalid, or
  237        *         <code>firstRow</code> &gt; <code>endRow</code>
  238        */
  239       public abstract void rowsInserted(int firstRow, int endRow);
  240   
  241       /**
  242        * Invoked when rows have been deleted from the underlying model
  243        * in the specified range (inclusive).
  244        * <p>
  245        * The arguments give the indices of the effected range and
  246        * are in terms of the model <b>before</b> the change.
  247        * For example, if you have a 5-row model and delete 3 items from the end
  248        * of the model the indices are 2, 4.
  249        * <p>
  250        * You normally do not call this method.  This method is public
  251        * to allow view classes to call it.
  252        *
  253        * @param firstRow the first row
  254        * @param endRow the last row
  255        * @throws IndexOutOfBoundsException if either argument is outside
  256        *         the range of the model before the change, or
  257        *         <code>firstRow</code> &gt; <code>endRow</code>
  258        */
  259       public abstract void rowsDeleted(int firstRow, int endRow);
  260   
  261       /**
  262        * Invoked when rows have been changed in the underlying model
  263        * between the specified range (inclusive).
  264        * <p>
  265        * You normally do not call this method.  This method is public
  266        * to allow view classes to call it.
  267        *
  268        * @param firstRow the first row, in terms of the underlying model
  269        * @param endRow the last row, in terms of the underlying model
  270        * @throws IndexOutOfBoundsException if either argument is outside
  271        *         the range of the underlying model, or
  272        *         <code>firstRow</code> &gt; <code>endRow</code>
  273        */
  274       public abstract void rowsUpdated(int firstRow, int endRow);
  275   
  276       /**
  277        * Invoked when the column in the rows have been updated in
  278        * the underlying model between the specified range.
  279        * <p>
  280        * You normally do not call this method.  This method is public
  281        * to allow view classes to call it.
  282        *
  283        * @param firstRow the first row, in terms of the underlying model
  284        * @param endRow the last row, in terms of the underlying model
  285        * @param column the column that has changed, in terms of the underlying
  286        *        model
  287        * @throws IndexOutOfBoundsException if either argument is outside
  288        *         the range of the underlying model after the change,
  289        *         <code>firstRow</code> &gt; <code>endRow</code>, or
  290        *         <code>column</code> is outside the range of the underlying
  291        *          model
  292        */
  293       public abstract void rowsUpdated(int firstRow, int endRow, int column);
  294   
  295       /**
  296        * Adds a <code>RowSorterListener</code> to receive notification
  297        * about this <code>RowSorter</code>.  If the same
  298        * listener is added more than once it will receive multiple
  299        * notifications.  If <code>l</code> is <code>null</code> nothing
  300        * is done.
  301        *
  302        * @param l the <code>RowSorterListener</code>
  303        */
  304       public void addRowSorterListener(RowSorterListener l) {
  305           listenerList.add(RowSorterListener.class, l);
  306       }
  307   
  308       /**
  309        * Removes a <code>RowSorterListener</code>.  If
  310        * <code>l</code> is <code>null</code> nothing is done.
  311        *
  312        * @param l the <code>RowSorterListener</code>
  313        */
  314       public void removeRowSorterListener(RowSorterListener l) {
  315           listenerList.remove(RowSorterListener.class, l);
  316       }
  317   
  318       /**
  319        * Notifies listener that the sort order has changed.
  320        */
  321       protected void fireSortOrderChanged() {
  322           fireRowSorterChanged(new RowSorterEvent(this));
  323       }
  324   
  325       /**
  326        * Notifies listener that the mapping has changed.
  327        *
  328        * @param lastRowIndexToModel the mapping from model indices to
  329        *        view indices prior to the sort, may be <code>null</code>
  330        */
  331       protected void fireRowSorterChanged(int[] lastRowIndexToModel) {
  332           fireRowSorterChanged(new RowSorterEvent(this,
  333                   RowSorterEvent.Type.SORTED, lastRowIndexToModel));
  334       }
  335   
  336       void fireRowSorterChanged(RowSorterEvent event) {
  337           Object[] listeners = listenerList.getListenerList();
  338           for (int i = listeners.length - 2; i >= 0; i -= 2) {
  339               if (listeners[i] == RowSorterListener.class) {
  340                   ((RowSorterListener)listeners[i + 1]).
  341                           sorterChanged(event);
  342               }
  343           }
  344       }
  345   
  346       /**
  347        * SortKey describes the sort order for a particular column.  The
  348        * column index is in terms of the underlying model, which may differ
  349        * from that of the view.
  350        *
  351        * @since 1.6
  352        */
  353       public static class SortKey {
  354           private int column;
  355           private SortOrder sortOrder;
  356   
  357           /**
  358            * Creates a <code>SortKey</code> for the specified column with
  359            * the specified sort order.
  360            *
  361            * @param column index of the column, in terms of the model
  362            * @param sortOrder the sorter order
  363            * @throws IllegalArgumentException if <code>sortOrder</code> is
  364            *         <code>null</code>
  365            */
  366           public SortKey(int column, SortOrder sortOrder) {
  367               if (sortOrder == null) {
  368                   throw new IllegalArgumentException(
  369                           "sort order must be non-null");
  370               }
  371               this.column = column;
  372               this.sortOrder = sortOrder;
  373           }
  374   
  375           /**
  376            * Returns the index of the column.
  377            *
  378            * @return index of column
  379            */
  380           public final int getColumn() {
  381               return column;
  382           }
  383   
  384           /**
  385            * Returns the sort order of the column.
  386            *
  387            * @return the sort order of the column
  388            */
  389           public final SortOrder getSortOrder() {
  390               return sortOrder;
  391           }
  392   
  393           /**
  394            * Returns the hash code for this <code>SortKey</code>.
  395            *
  396            * @return hash code
  397            */
  398           public int hashCode() {
  399               int result = 17;
  400               result = 37 * result + column;
  401               result = 37 * result + sortOrder.hashCode();
  402               return result;
  403           }
  404   
  405           /**
  406            * Returns true if this object equals the specified object.
  407            * If the specified object is a <code>SortKey</code> and
  408            * references the same column and sort order, the two objects
  409            * are equal.
  410            *
  411            * @param o the object to compare to
  412            * @return true if <code>o</code> is equal to this <code>SortKey</code>
  413            */
  414           public boolean equals(Object o) {
  415               if (o == this) {
  416                   return true;
  417               }
  418               if (o instanceof SortKey) {
  419                   return (((SortKey)o).column == column &&
  420                           ((SortKey)o).sortOrder == sortOrder);
  421               }
  422               return false;
  423           }
  424       }
  425   }

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