Source Code Cross Referenced for JTable.java in  » 6.0-JDK-Core » swing » javax » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package javax.swing;
0027
0028        import java.util.*;
0029
0030        import java.applet.Applet;
0031        import java.awt.*;
0032        import java.awt.event.*;
0033        import java.awt.print.*;
0034
0035        import java.beans.*;
0036
0037        import java.io.Serializable;
0038        import java.io.ObjectOutputStream;
0039        import java.io.ObjectInputStream;
0040        import java.io.IOException;
0041
0042        import javax.accessibility.*;
0043
0044        import javax.swing.event.*;
0045        import javax.swing.plaf.*;
0046        import javax.swing.table.*;
0047        import javax.swing.border.*;
0048
0049        import java.text.NumberFormat;
0050        import java.text.DateFormat;
0051        import java.text.MessageFormat;
0052
0053        import javax.print.attribute.*;
0054        import javax.print.PrintService;
0055
0056        import sun.swing.SwingUtilities2;
0057        import sun.swing.SwingUtilities2.Section;
0058        import static sun.swing.SwingUtilities2.Section.*;
0059        import sun.swing.PrintingStatus;
0060
0061        /**
0062         * The <code>JTable</code> is used to display and edit regular two-dimensional tables
0063         * of cells.
0064         * See <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/table.html">How to Use Tables</a>
0065         * in <em>The Java Tutorial</em>
0066         * for task-oriented documentation and examples of using <code>JTable</code>.
0067         *
0068         * <p>
0069         * The <code>JTable</code> has many
0070         * facilities that make it possible to customize its rendering and editing
0071         * but provides defaults for these features so that simple tables can be
0072         * set up easily.  For example, to set up a table with 10 rows and 10
0073         * columns of numbers:
0074         * <p>
0075         * <pre>
0076         *      TableModel dataModel = new AbstractTableModel() {
0077         *          public int getColumnCount() { return 10; }
0078         *          public int getRowCount() { return 10;}
0079         *          public Object getValueAt(int row, int col) { return new Integer(row*col); }
0080         *      };
0081         *      JTable table = new JTable(dataModel);
0082         *      JScrollPane scrollpane = new JScrollPane(table);
0083         * </pre>
0084         * <p>
0085         * {@code JTable}s are typically placed inside of a {@code JScrollPane}.  By
0086         * default, a {@code JTable} will adjust its width such that
0087         * a horizontal scrollbar is unnecessary.  To allow for a horizontal scrollbar,
0088         * invoke {@link #setAutoResizeMode} with {@code AUTO_RESIZE_OFF}.
0089         * Note that if you wish to use a <code>JTable</code> in a standalone
0090         * view (outside of a <code>JScrollPane</code>) and want the header
0091         * displayed, you can get it using {@link #getTableHeader} and
0092         * display it separately.
0093         * <p>
0094         * To enable sorting and filtering of rows, use a
0095         * {@code RowSorter}.
0096         * You can set up a row sorter in either of two ways: 
0097         * <ul>
0098         *   <li>Directly set the {@code RowSorter}. For example:
0099         *        {@code table.setRowSorter(new TableRowSorter(model))}.
0100         *   <li>Set the {@code autoCreateRowSorter}
0101         *       property to {@code true}, so that the {@code JTable}
0102         *       creates a {@code RowSorter} for
0103         *       you. For example: {@code setAutoCreateRowSorter(true)}.
0104         * </ul>
0105         * <p>
0106         * When designing applications that use the <code>JTable</code> it is worth paying
0107         * close attention to the data structures that will represent the table's data.
0108         * The <code>DefaultTableModel</code> is a model implementation that
0109         * uses a <code>Vector</code> of <code>Vector</code>s of <code>Object</code>s to
0110         * store the cell values. As well as copying the data from an
0111         * application into the <code>DefaultTableModel</code>,
0112         * it is also possible to wrap the data in the methods of the
0113         * <code>TableModel</code> interface so that the data can be passed to the
0114         * <code>JTable</code> directly, as in the example above. This often results
0115         * in more efficient applications because the model is free to choose the
0116         * internal representation that best suits the data.
0117         * A good rule of thumb for deciding whether to use the <code>AbstractTableModel</code>
0118         * or the <code>DefaultTableModel</code> is to use the <code>AbstractTableModel</code>
0119         * as the base class for creating subclasses and the <code>DefaultTableModel</code>
0120         * when subclassing is not required.
0121         * <p>
0122         * The "TableExample" directory in the demo area of the source distribution
0123         * gives a number of complete examples of <code>JTable</code> usage,
0124         * covering how the <code>JTable</code> can be used to provide an
0125         * editable view of data taken from a database and how to modify
0126         * the columns in the display to use specialized renderers and editors.
0127         * <p>
0128         * The <code>JTable</code> uses integers exclusively to refer to both the rows and the columns
0129         * of the model that it displays. The <code>JTable</code> simply takes a tabular range of cells
0130         * and uses <code>getValueAt(int, int)</code> to retrieve the
0131         * values from the model during painting.  It is important to remember that
0132         * the column and row indexes returned by various <code>JTable</code> methods
0133         * are in terms of the <code>JTable</code> (the view) and are not
0134         * necessarily the same indexes used by the model.
0135         * <p>
0136         * By default, columns may be rearranged in the <code>JTable</code> so that the
0137         * view's columns appear in a different order to the columns in the model.
0138         * This does not affect the implementation of the model at all: when the
0139         * columns are reordered, the <code>JTable</code> maintains the new order of the columns
0140         * internally and converts its column indices before querying the model.
0141         * <p>
0142         * So, when writing a <code>TableModel</code>, it is not necessary to listen for column
0143         * reordering events as the model will be queried in its own coordinate
0144         * system regardless of what is happening in the view.
0145         * In the examples area there is a demonstration of a sorting algorithm making
0146         * use of exactly this technique to interpose yet another coordinate system
0147         * where the order of the rows is changed, rather than the order of the columns.
0148         * <p>
0149         * Similarly when using the sorting and filtering functionality
0150         * provided by <code>RowSorter</code> the underlying
0151         * <code>TableModel</code> does not need to know how to do sorting,
0152         * rather <code>RowSorter</code> will handle it.  Coordinate
0153         * conversions will be necessary when using the row based methods of
0154         * <code>JTable</code> with the underlying <code>TableModel</code>.
0155         * All of <code>JTable</code>s row based methods are in terms of the
0156         * <code>RowSorter</code>, which is not necessarily the same as that
0157         * of the underlying <code>TableModel</code>.  For example, the
0158         * selection is always in terms of <code>JTable</code> so that when
0159         * using <code>RowSorter</code> you will need to convert using
0160         * <code>convertRowIndexToView</code> or
0161         * <code>convertRowIndexToModel</code>.  The following shows how to
0162         * convert coordinates from <code>JTable</code> to that of the
0163         * underlying model:
0164         * <pre>
0165         *   int[] selection = table.getSelectedRows();
0166         *   for (int i = 0; i &lt; selection.length; i++) {
0167         *     selection[i] = table.convertRowIndexToModel(selection[i]);
0168         *   }
0169         *   // selection is now in terms of the underlying TableModel
0170         * </pre>
0171         * <p>
0172         * By default if sorting is enabled <code>JTable</code> will persist the
0173         * selection and variable row heights in terms of the model on
0174         * sorting.  For example if row 0, in terms of the underlying model,
0175         * is currently selected, after the sort row 0, in terms of the
0176         * underlying model will be selected.  Visually the selection may
0177         * change, but in terms of the underlying model it will remain the
0178         * same.  The one exception to that is if the model index is no longer
0179         * visible or was removed.  For example, if row 0 in terms of model
0180         * was filtered out the selection will be empty after the sort.
0181         * <p>
0182         * J2SE 5 adds methods to <code>JTable</code> to provide convenient access to some
0183         * common printing needs. Simple new {@link #print()} methods allow for quick
0184         * and easy addition of printing support to your application. In addition, a new
0185         * {@link #getPrintable} method is available for more advanced printing needs.
0186         * <p>
0187         * As for all <code>JComponent</code> classes, you can use
0188         * {@link InputMap} and {@link ActionMap} to associate an
0189         * {@link Action} object with a {@link KeyStroke} and execute the
0190         * action under specified conditions.
0191         * <p>
0192         * <strong>Warning:</strong> Swing is not thread safe. For more
0193         * information see <a
0194         * href="package-summary.html#threading">Swing's Threading
0195         * Policy</a>.
0196         * <p>
0197         * <strong>Warning:</strong>
0198         * Serialized objects of this class will not be compatible with
0199         * future Swing releases. The current serialization support is
0200         * appropriate for short term storage or RMI between applications running
0201         * the same version of Swing.  As of 1.4, support for long term storage
0202         * of all JavaBeans<sup><font size="-2">TM</font></sup>
0203         * has been added to the <code>java.beans</code> package.
0204         * Please see {@link java.beans.XMLEncoder}.
0205         *
0206         *
0207         * @beaninfo
0208         *   attribute: isContainer false
0209         * description: A component which displays data in a two dimensional grid.
0210         *
0211         * @version 1.294 05/05/07
0212         * @author Philip Milne
0213         * @author Shannon Hickey (printing support)
0214         * @see javax.swing.table.DefaultTableModel
0215         * @see javax.swing.table.TableRowSorter
0216         */
0217        /* The first versions of the JTable, contained in Swing-0.1 through
0218         * Swing-0.4, were written by Alan Chung.
0219         */
0220        public class JTable extends JComponent implements  TableModelListener,
0221                Scrollable, TableColumnModelListener, ListSelectionListener,
0222                CellEditorListener, Accessible, RowSorterListener {
0223            //
0224            // Static Constants
0225            //
0226
0227            /**
0228             * @see #getUIClassID
0229             * @see #readObject
0230             */
0231            private static final String uiClassID = "TableUI";
0232
0233            /** Do not adjust column widths automatically; use a horizontal scrollbar instead. */
0234            public static final int AUTO_RESIZE_OFF = 0;
0235
0236            /** When a column is adjusted in the UI, adjust the next column the opposite way. */
0237            public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
0238
0239            /** During UI adjustment, change subsequent columns to preserve the total width;
0240             * this is the default behavior. */
0241            public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
0242
0243            /** During all resize operations, apply adjustments to the last column only. */
0244            public static final int AUTO_RESIZE_LAST_COLUMN = 3;
0245
0246            /** During all resize operations, proportionately resize all columns. */
0247            public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
0248
0249            /**
0250             * Printing modes, used in printing <code>JTable</code>s.
0251             *
0252             * @see #print(JTable.PrintMode, MessageFormat, MessageFormat,
0253             *             boolean, PrintRequestAttributeSet, boolean)
0254             * @see #getPrintable
0255             * @since 1.5
0256             */
0257            public enum PrintMode {
0258
0259                /**
0260                 * Printing mode that prints the table at its current size,
0261                 * spreading both columns and rows across multiple pages if necessary.
0262                 */
0263                NORMAL,
0264
0265                /**
0266                 * Printing mode that scales the output smaller, if necessary,
0267                 * to fit the table's entire width (and thereby all columns) on each page;
0268                 * Rows are spread across multiple pages as necessary.
0269                 */
0270                FIT_WIDTH
0271            }
0272
0273            //
0274            // Instance Variables
0275            //
0276
0277            /** The <code>TableModel</code> of the table. */
0278            protected TableModel dataModel;
0279
0280            /** The <code>TableColumnModel</code> of the table. */
0281            protected TableColumnModel columnModel;
0282
0283            /** The <code>ListSelectionModel</code> of the table, used to keep track of row selections. */
0284            protected ListSelectionModel selectionModel;
0285
0286            /** The <code>TableHeader</code> working with the table. */
0287            protected JTableHeader tableHeader;
0288
0289            /** The height in pixels of each row in the table. */
0290            protected int rowHeight;
0291
0292            /** The height in pixels of the margin between the cells in each row. */
0293            protected int rowMargin;
0294
0295            /** The color of the grid. */
0296            protected Color gridColor;
0297
0298            /** The table draws horizontal lines between cells if <code>showHorizontalLines</code> is true. */
0299            protected boolean showHorizontalLines;
0300
0301            /** The table draws vertical lines between cells if <code>showVerticalLines</code> is true. */
0302            protected boolean showVerticalLines;
0303
0304            /**
0305             *  Determines if the table automatically resizes the
0306             *  width of the table's columns to take up the entire width of the
0307             *  table, and how it does the resizing.
0308             */
0309            protected int autoResizeMode;
0310
0311            /**
0312             *  The table will query the <code>TableModel</code> to build the default
0313             *  set of columns if this is true.
0314             */
0315            protected boolean autoCreateColumnsFromModel;
0316
0317            /** Used by the <code>Scrollable</code> interface to determine the initial visible area. */
0318            protected Dimension preferredViewportSize;
0319
0320            /** True if row selection is allowed in this table. */
0321            protected boolean rowSelectionAllowed;
0322
0323            /**
0324             * Obsolete as of Java 2 platform v1.3.  Please use the
0325             * <code>rowSelectionAllowed</code> property and the
0326             * <code>columnSelectionAllowed</code> property of the
0327             * <code>columnModel</code> instead. Or use the
0328             * method <code>getCellSelectionEnabled</code>.
0329             */
0330            /*
0331             * If true, both a row selection and a column selection
0332             * can be non-empty at the same time, the selected cells are the
0333             * the cells whose row and column are both selected.
0334             */
0335            protected boolean cellSelectionEnabled;
0336
0337            /** If editing, the <code>Component</code> that is handling the editing. */
0338            transient protected Component editorComp;
0339
0340            /**
0341             * The active cell editor object, that overwrites the screen real estate
0342             * occupied by the current cell and allows the user to change its contents.
0343             * {@code null} if the table isn't currently editing.
0344             */
0345            transient protected TableCellEditor cellEditor;
0346
0347            /** Identifies the column of the cell being edited. */
0348            transient protected int editingColumn;
0349
0350            /** Identifies the row of the cell being edited. */
0351            transient protected int editingRow;
0352
0353            /**
0354             * A table of objects that display the contents of a cell,
0355             * indexed by class as declared in <code>getColumnClass</code>
0356             * in the <code>TableModel</code> interface.
0357             */
0358            transient protected Hashtable defaultRenderersByColumnClass;
0359
0360            /**
0361             * A table of objects that display and edit the contents of a cell,
0362             * indexed by class as declared in <code>getColumnClass</code>
0363             * in the <code>TableModel</code> interface.
0364             */
0365            transient protected Hashtable defaultEditorsByColumnClass;
0366
0367            /** The foreground color of selected cells. */
0368            protected Color selectionForeground;
0369
0370            /** The background color of selected cells. */
0371            protected Color selectionBackground;
0372
0373            //
0374            // Private state
0375            //
0376
0377            // WARNING: If you directly access this field you should also change the
0378            // SortManager.modelRowSizes field as well.
0379            private SizeSequence rowModel;
0380            private boolean dragEnabled;
0381            private boolean surrendersFocusOnKeystroke;
0382            private PropertyChangeListener editorRemover = null;
0383            /**
0384             * The last value of getValueIsAdjusting from the column selection models
0385             * columnSelectionChanged notification. Used to test if a repaint is
0386             * needed.
0387             */
0388            private boolean columnSelectionAdjusting;
0389            /**
0390             * The last value of getValueIsAdjusting from the row selection models
0391             * valueChanged notification. Used to test if a repaint is needed.
0392             */
0393            private boolean rowSelectionAdjusting;
0394
0395            /**
0396             * To communicate errors between threads during printing.
0397             */
0398            private Throwable printError;
0399
0400            /**
0401             * True when setRowHeight(int) has been invoked.
0402             */
0403            private boolean isRowHeightSet;
0404
0405            /**
0406             * If true, on a sort the selection is reset.
0407             */
0408            private boolean updateSelectionOnSort;
0409
0410            /**
0411             * Information used in sorting.
0412             */
0413            private transient SortManager sortManager;
0414
0415            /**
0416             * If true, when sorterChanged is invoked it's value is ignored.
0417             */
0418            private boolean ignoreSortChange;
0419
0420            /**
0421             * Whether or not sorterChanged has been invoked.
0422             */
0423            private boolean sorterChanged;
0424
0425            /**
0426             * If true, any time the model changes a new RowSorter is set.
0427             */
0428            private boolean autoCreateRowSorter;
0429
0430            /**
0431             * Whether or not the table always fills the viewport height.
0432             * @see #setFillsViewportHeight
0433             * @see #getScrollableTracksViewportHeight
0434             */
0435            private boolean fillsViewportHeight;
0436
0437            /**
0438             * The drop mode for this component.
0439             */
0440            private DropMode dropMode = DropMode.USE_SELECTION;
0441
0442            /**
0443             * The drop location.
0444             */
0445            private transient DropLocation dropLocation;
0446
0447            /**
0448             * A subclass of <code>TransferHandler.DropLocation</code> representing
0449             * a drop location for a <code>JTable</code>.
0450             *
0451             * @see #getDropLocation
0452             * @since 1.6
0453             */
0454            public static final class DropLocation extends
0455                    TransferHandler.DropLocation {
0456                private final int row;
0457                private final int col;
0458                private final boolean isInsertRow;
0459                private final boolean isInsertCol;
0460
0461                private DropLocation(Point p, int row, int col,
0462                        boolean isInsertRow, boolean isInsertCol) {
0463
0464                    super (p);
0465                    this .row = row;
0466                    this .col = col;
0467                    this .isInsertRow = isInsertRow;
0468                    this .isInsertCol = isInsertCol;
0469                }
0470
0471                /**
0472                 * Returns the row index where a dropped item should be placed in the
0473                 * table. Interpretation of the value depends on the return of
0474                 * <code>isInsertRow()</code>. If that method returns
0475                 * <code>true</code> this value indicates the index where a new
0476                 * row should be inserted. Otherwise, it represents the value
0477                 * of an existing row on which the data was dropped. This index is
0478                 * in terms of the view.
0479                 * <p>
0480                 * <code>-1</code> indicates that the drop occurred over empty space,
0481                 * and no row could be calculated.
0482                 *
0483                 * @return the drop row
0484                 */
0485                public int getRow() {
0486                    return row;
0487                }
0488
0489                /**
0490                 * Returns the column index where a dropped item should be placed in the
0491                 * table. Interpretation of the value depends on the return of
0492                 * <code>isInsertColumn()</code>. If that method returns
0493                 * <code>true</code> this value indicates the index where a new
0494                 * column should be inserted. Otherwise, it represents the value
0495                 * of an existing column on which the data was dropped. This index is
0496                 * in terms of the view.
0497                 * <p>
0498                 * <code>-1</code> indicates that the drop occurred over empty space,
0499                 * and no column could be calculated.
0500                 *
0501                 * @return the drop row
0502                 */
0503                public int getColumn() {
0504                    return col;
0505                }
0506
0507                /**
0508                 * Returns whether or not this location represents an insert
0509                 * of a row.
0510                 *
0511                 * @return whether or not this is an insert row
0512                 */
0513                public boolean isInsertRow() {
0514                    return isInsertRow;
0515                }
0516
0517                /**
0518                 * Returns whether or not this location represents an insert
0519                 * of a column.
0520                 *
0521                 * @return whether or not this is an insert column
0522                 */
0523                public boolean isInsertColumn() {
0524                    return isInsertCol;
0525                }
0526
0527                /**
0528                 * Returns a string representation of this drop location.
0529                 * This method is intended to be used for debugging purposes,
0530                 * and the content and format of the returned string may vary
0531                 * between implementations.
0532                 *
0533                 * @return a string representation of this drop location
0534                 */
0535                public String toString() {
0536                    return getClass().getName() + "[dropPoint="
0537                            + getDropPoint() + "," + "row=" + row + ","
0538                            + "column=" + col + "," + "insertRow="
0539                            + isInsertRow + "," + "insertColumn=" + isInsertCol
0540                            + "]";
0541                }
0542            }
0543
0544            //
0545            // Constructors
0546            //
0547
0548            /**
0549             * Constructs a default <code>JTable</code> that is initialized with a default
0550             * data model, a default column model, and a default selection
0551             * model.
0552             *
0553             * @see #createDefaultDataModel
0554             * @see #createDefaultColumnModel
0555             * @see #createDefaultSelectionModel
0556             */
0557            public JTable() {
0558                this (null, null, null);
0559            }
0560
0561            /**
0562             * Constructs a <code>JTable</code> that is initialized with
0563             * <code>dm</code> as the data model, a default column model,
0564             * and a default selection model.
0565             *
0566             * @param dm        the data model for the table
0567             * @see #createDefaultColumnModel
0568             * @see #createDefaultSelectionModel
0569             */
0570            public JTable(TableModel dm) {
0571                this (dm, null, null);
0572            }
0573
0574            /**
0575             * Constructs a <code>JTable</code> that is initialized with
0576             * <code>dm</code> as the data model, <code>cm</code>
0577             * as the column model, and a default selection model.
0578             *
0579             * @param dm        the data model for the table
0580             * @param cm        the column model for the table
0581             * @see #createDefaultSelectionModel
0582             */
0583            public JTable(TableModel dm, TableColumnModel cm) {
0584                this (dm, cm, null);
0585            }
0586
0587            /**
0588             * Constructs a <code>JTable</code> that is initialized with
0589             * <code>dm</code> as the data model, <code>cm</code> as the
0590             * column model, and <code>sm</code> as the selection model.
0591             * If any of the parameters are <code>null</code> this method
0592             * will initialize the table with the corresponding default model.
0593             * The <code>autoCreateColumnsFromModel</code> flag is set to false
0594             * if <code>cm</code> is non-null, otherwise it is set to true
0595             * and the column model is populated with suitable
0596             * <code>TableColumns</code> for the columns in <code>dm</code>.
0597             *
0598             * @param dm        the data model for the table
0599             * @param cm        the column model for the table
0600             * @param sm        the row selection model for the table
0601             * @see #createDefaultDataModel
0602             * @see #createDefaultColumnModel
0603             * @see #createDefaultSelectionModel
0604             */
0605            public JTable(TableModel dm, TableColumnModel cm,
0606                    ListSelectionModel sm) {
0607                super ();
0608                setLayout(null);
0609
0610                setFocusTraversalKeys(
0611                        KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, JComponent
0612                                .getManagingFocusForwardTraversalKeys());
0613                setFocusTraversalKeys(
0614                        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
0615                        JComponent.getManagingFocusBackwardTraversalKeys());
0616                if (cm == null) {
0617                    cm = createDefaultColumnModel();
0618                    autoCreateColumnsFromModel = true;
0619                }
0620                setColumnModel(cm);
0621
0622                if (sm == null) {
0623                    sm = createDefaultSelectionModel();
0624                }
0625                setSelectionModel(sm);
0626
0627                // Set the model last, that way if the autoCreatColumnsFromModel has
0628                // been set above, we will automatically populate an empty columnModel
0629                // with suitable columns for the new model.
0630                if (dm == null) {
0631                    dm = createDefaultDataModel();
0632                }
0633                setModel(dm);
0634
0635                initializeLocalVars();
0636                updateUI();
0637            }
0638
0639            /**
0640             * Constructs a <code>JTable</code> with <code>numRows</code>
0641             * and <code>numColumns</code> of empty cells using
0642             * <code>DefaultTableModel</code>.  The columns will have
0643             * names of the form "A", "B", "C", etc.
0644             *
0645             * @param numRows           the number of rows the table holds
0646             * @param numColumns        the number of columns the table holds
0647             * @see javax.swing.table.DefaultTableModel
0648             */
0649            public JTable(int numRows, int numColumns) {
0650                this (new DefaultTableModel(numRows, numColumns));
0651            }
0652
0653            /**
0654             * Constructs a <code>JTable</code> to display the values in the
0655             * <code>Vector</code> of <code>Vectors</code>, <code>rowData</code>,
0656             * with column names, <code>columnNames</code>.  The
0657             * <code>Vectors</code> contained in <code>rowData</code>
0658             * should contain the values for that row. In other words,
0659             * the value of the cell at row 1, column 5 can be obtained
0660             * with the following code:
0661             * <p>
0662             * <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
0663             * <p>
0664             * @param rowData           the data for the new table
0665             * @param columnNames       names of each column
0666             */
0667            public JTable(Vector rowData, Vector columnNames) {
0668                this (new DefaultTableModel(rowData, columnNames));
0669            }
0670
0671            /**
0672             * Constructs a <code>JTable</code> to display the values in the two dimensional array,
0673             * <code>rowData</code>, with column names, <code>columnNames</code>.
0674             * <code>rowData</code> is an array of rows, so the value of the cell at row 1,
0675             * column 5 can be obtained with the following code:
0676             * <p>
0677             * <pre> rowData[1][5]; </pre>
0678             * <p>
0679             * All rows must be of the same length as <code>columnNames</code>.
0680             * <p>
0681             * @param rowData           the data for the new table
0682             * @param columnNames       names of each column
0683             */
0684            public JTable(final Object[][] rowData, final Object[] columnNames) {
0685                this (new AbstractTableModel() {
0686                    public String getColumnName(int column) {
0687                        return columnNames[column].toString();
0688                    }
0689
0690                    public int getRowCount() {
0691                        return rowData.length;
0692                    }
0693
0694                    public int getColumnCount() {
0695                        return columnNames.length;
0696                    }
0697
0698                    public Object getValueAt(int row, int col) {
0699                        return rowData[row][col];
0700                    }
0701
0702                    public boolean isCellEditable(int row, int column) {
0703                        return true;
0704                    }
0705
0706                    public void setValueAt(Object value, int row, int col) {
0707                        rowData[row][col] = value;
0708                        fireTableCellUpdated(row, col);
0709                    }
0710                });
0711            }
0712
0713            /**
0714             * Calls the <code>configureEnclosingScrollPane</code> method.
0715             *
0716             * @see #configureEnclosingScrollPane
0717             */
0718            public void addNotify() {
0719                super .addNotify();
0720                configureEnclosingScrollPane();
0721            }
0722
0723            /**
0724             * If this <code>JTable</code> is the <code>viewportView</code> of an enclosing <code>JScrollPane</code>
0725             * (the usual situation), configure this <code>ScrollPane</code> by, amongst other things,
0726             * installing the table's <code>tableHeader</code> as the <code>columnHeaderView</code> of the scroll pane.
0727             * When a <code>JTable</code> is added to a <code>JScrollPane</code> in the usual way,
0728             * using <code>new JScrollPane(myTable)</code>, <code>addNotify</code> is
0729             * called in the <code>JTable</code> (when the table is added to the viewport).
0730             * <code>JTable</code>'s <code>addNotify</code> method in turn calls this method,
0731             * which is protected so that this default installation procedure can
0732             * be overridden by a subclass.
0733             *
0734             * @see #addNotify
0735             */
0736            protected void configureEnclosingScrollPane() {
0737                Container p = getParent();
0738                if (p instanceof  JViewport) {
0739                    Container gp = p.getParent();
0740                    if (gp instanceof  JScrollPane) {
0741                        JScrollPane scrollPane = (JScrollPane) gp;
0742                        // Make certain we are the viewPort's view and not, for
0743                        // example, the rowHeaderView of the scrollPane -
0744                        // an implementor of fixed columns might do this.
0745                        JViewport viewport = scrollPane.getViewport();
0746                        if (viewport == null || viewport.getView() != this ) {
0747                            return;
0748                        }
0749                        scrollPane.setColumnHeaderView(getTableHeader());
0750                        //  scrollPane.getViewport().setBackingStoreEnabled(true);
0751                        Border border = scrollPane.getBorder();
0752                        if (border == null || border instanceof  UIResource) {
0753                            Border scrollPaneBorder = UIManager
0754                                    .getBorder("Table.scrollPaneBorder");
0755                            if (scrollPaneBorder != null) {
0756                                scrollPane.setBorder(scrollPaneBorder);
0757                            }
0758                        }
0759                    }
0760                }
0761            }
0762
0763            /**
0764             * Calls the <code>unconfigureEnclosingScrollPane</code> method.
0765             *
0766             * @see #unconfigureEnclosingScrollPane
0767             */
0768            public void removeNotify() {
0769                KeyboardFocusManager.getCurrentKeyboardFocusManager()
0770                        .removePropertyChangeListener("permanentFocusOwner",
0771                                editorRemover);
0772                editorRemover = null;
0773                unconfigureEnclosingScrollPane();
0774                super .removeNotify();
0775            }
0776
0777            /**
0778             * Reverses the effect of <code>configureEnclosingScrollPane</code>
0779             * by replacing the <code>columnHeaderView</code> of the enclosing
0780             * scroll pane with <code>null</code>. <code>JTable</code>'s
0781             * <code>removeNotify</code> method calls
0782             * this method, which is protected so that this default uninstallation
0783             * procedure can be overridden by a subclass.
0784             *
0785             * @see #removeNotify
0786             * @see #configureEnclosingScrollPane
0787             * @since 1.3
0788             */
0789            protected void unconfigureEnclosingScrollPane() {
0790                Container p = getParent();
0791                if (p instanceof  JViewport) {
0792                    Container gp = p.getParent();
0793                    if (gp instanceof  JScrollPane) {
0794                        JScrollPane scrollPane = (JScrollPane) gp;
0795                        // Make certain we are the viewPort's view and not, for
0796                        // example, the rowHeaderView of the scrollPane -
0797                        // an implementor of fixed columns might do this.
0798                        JViewport viewport = scrollPane.getViewport();
0799                        if (viewport == null || viewport.getView() != this ) {
0800                            return;
0801                        }
0802                        scrollPane.setColumnHeaderView(null);
0803                    }
0804                }
0805            }
0806
0807            void setUIProperty(String propertyName, Object value) {
0808                if (propertyName == "rowHeight") {
0809                    if (!isRowHeightSet) {
0810                        setRowHeight(((Number) value).intValue());
0811                        isRowHeightSet = false;
0812                    }
0813                    return;
0814                }
0815                super .setUIProperty(propertyName, value);
0816            }
0817
0818            //
0819            // Static Methods
0820            //
0821
0822            /**
0823             * Equivalent to <code>new JScrollPane(aTable)</code>.
0824             *
0825             * @deprecated As of Swing version 1.0.2,
0826             * replaced by <code>new JScrollPane(aTable)</code>.
0827             */
0828            @Deprecated
0829            static public JScrollPane createScrollPaneForTable(JTable aTable) {
0830                return new JScrollPane(aTable);
0831            }
0832
0833            //
0834            // Table Attributes
0835            //
0836
0837            /**
0838             * Sets the <code>tableHeader</code> working with this <code>JTable</code> to <code>newHeader</code>.
0839             * It is legal to have a <code>null</code> <code>tableHeader</code>.
0840             *
0841             * @param   tableHeader                       new tableHeader
0842             * @see     #getTableHeader
0843             * @beaninfo
0844             *  bound: true
0845             *  description: The JTableHeader instance which renders the column headers.
0846             */
0847            public void setTableHeader(JTableHeader tableHeader) {
0848                if (this .tableHeader != tableHeader) {
0849                    JTableHeader old = this .tableHeader;
0850                    // Release the old header
0851                    if (old != null) {
0852                        old.setTable(null);
0853                    }
0854                    this .tableHeader = tableHeader;
0855                    if (tableHeader != null) {
0856                        tableHeader.setTable(this );
0857                    }
0858                    firePropertyChange("tableHeader", old, tableHeader);
0859                }
0860            }
0861
0862            /**
0863             * Returns the <code>tableHeader</code> used by this <code>JTable</code>.
0864             *
0865             * @return  the <code>tableHeader</code> used by this table
0866             * @see     #setTableHeader
0867             */
0868            public JTableHeader getTableHeader() {
0869                return tableHeader;
0870            }
0871
0872            /**
0873             * Sets the height, in pixels, of all cells to <code>rowHeight</code>,
0874             * revalidates, and repaints.
0875             * The height of the cells will be equal to the row height minus
0876             * the row margin.
0877             *
0878             * @param   rowHeight                       new row height
0879             * @exception IllegalArgumentException      if <code>rowHeight</code> is
0880             *                                          less than 1
0881             * @see     #getRowHeight
0882             * @beaninfo
0883             *  bound: true
0884             *  description: The height of the specified row.
0885             */
0886            public void setRowHeight(int rowHeight) {
0887                if (rowHeight <= 0) {
0888                    throw new IllegalArgumentException(
0889                            "New row height less than 1");
0890                }
0891                int old = this .rowHeight;
0892                this .rowHeight = rowHeight;
0893                rowModel = null;
0894                if (sortManager != null) {
0895                    sortManager.modelRowSizes = null;
0896                }
0897                isRowHeightSet = true;
0898                resizeAndRepaint();
0899                firePropertyChange("rowHeight", old, rowHeight);
0900            }
0901
0902            /**
0903             * Returns the height of a table row, in pixels.
0904             * The default row height is 16.0.
0905             *
0906             * @return  the height in pixels of a table row
0907             * @see     #setRowHeight
0908             */
0909            public int getRowHeight() {
0910                return rowHeight;
0911            }
0912
0913            private SizeSequence getRowModel() {
0914                if (rowModel == null) {
0915                    rowModel = new SizeSequence(getRowCount(), getRowHeight());
0916                }
0917                return rowModel;
0918            }
0919
0920            /**
0921             * Sets the height for <code>row</code> to <code>rowHeight</code>,
0922             * revalidates, and repaints. The height of the cells in this row
0923             * will be equal to the row height minus the row margin.
0924             *
0925             * @param   row                             the row whose height is being
0926            					changed
0927             * @param   rowHeight                       new row height, in pixels
0928             * @exception IllegalArgumentException      if <code>rowHeight</code> is
0929             *                                          less than 1
0930             * @beaninfo
0931             *  bound: true
0932             *  description: The height in pixels of the cells in <code>row</code>
0933             * @since 1.3
0934             */
0935            public void setRowHeight(int row, int rowHeight) {
0936                if (rowHeight <= 0) {
0937                    throw new IllegalArgumentException(
0938                            "New row height less than 1");
0939                }
0940                getRowModel().setSize(row, rowHeight);
0941                if (sortManager != null) {
0942                    sortManager.setViewRowHeight(row, rowHeight);
0943                }
0944                resizeAndRepaint();
0945            }
0946
0947            /**
0948             * Returns the height, in pixels, of the cells in <code>row</code>.
0949             * @param   row              the row whose height is to be returned
0950             * @return the height, in pixels, of the cells in the row
0951             * @since 1.3
0952             */
0953            public int getRowHeight(int row) {
0954                return (rowModel == null) ? getRowHeight() : rowModel
0955                        .getSize(row);
0956            }
0957
0958            /**
0959             * Sets the amount of empty space between cells in adjacent rows.
0960             *
0961             * @param  rowMargin  the number of pixels between cells in a row
0962             * @see     #getRowMargin
0963             * @beaninfo
0964             *  bound: true
0965             *  description: The amount of space between cells.
0966             */
0967            public void setRowMargin(int rowMargin) {
0968                int old = this .rowMargin;
0969                this .rowMargin = rowMargin;
0970                resizeAndRepaint();
0971                firePropertyChange("rowMargin", old, rowMargin);
0972            }
0973
0974            /**
0975             * Gets the amount of empty space, in pixels, between cells. Equivalent to:
0976             * <code>getIntercellSpacing().height</code>.
0977             * @return the number of pixels between cells in a row
0978             *
0979             * @see     #setRowMargin
0980             */
0981            public int getRowMargin() {
0982                return rowMargin;
0983            }
0984
0985            /**
0986             * Sets the <code>rowMargin</code> and the <code>columnMargin</code> --
0987             * the height and width of the space between cells -- to
0988             * <code>intercellSpacing</code>.
0989             *
0990             * @param   intercellSpacing        a <code>Dimension</code>
0991             *					specifying the new width
0992             *					and height between cells
0993             * @see     #getIntercellSpacing
0994             * @beaninfo
0995             *  description: The spacing between the cells,
0996             *               drawn in the background color of the JTable.
0997             */
0998            public void setIntercellSpacing(Dimension intercellSpacing) {
0999                // Set the rowMargin here and columnMargin in the TableColumnModel
1000                setRowMargin(intercellSpacing.height);
1001                getColumnModel().setColumnMargin(intercellSpacing.width);
1002
1003                resizeAndRepaint();
1004            }
1005
1006            /**
1007             * Returns the horizontal and vertical space between cells.
1008             * The default spacing is (1, 1), which provides room to draw the grid.
1009             *
1010             * @return  the horizontal and vertical spacing between cells
1011             * @see     #setIntercellSpacing
1012             */
1013            public Dimension getIntercellSpacing() {
1014                return new Dimension(getColumnModel().getColumnMargin(),
1015                        rowMargin);
1016            }
1017
1018            /**
1019             * Sets the color used to draw grid lines to <code>gridColor</code> and redisplays.
1020             * The default color is look and feel dependent.
1021             *
1022             * @param   gridColor                       the new color of the grid lines
1023             * @exception IllegalArgumentException      if <code>gridColor</code> is <code>null</code>
1024             * @see     #getGridColor
1025             * @beaninfo
1026             *  bound: true
1027             *  description: The grid color.
1028             */
1029            public void setGridColor(Color gridColor) {
1030                if (gridColor == null) {
1031                    throw new IllegalArgumentException("New color is null");
1032                }
1033                Color old = this .gridColor;
1034                this .gridColor = gridColor;
1035                firePropertyChange("gridColor", old, gridColor);
1036                // Redraw
1037                repaint();
1038            }
1039
1040            /**
1041             * Returns the color used to draw grid lines.
1042             * The default color is look and feel dependent.
1043             *
1044             * @return  the color used to draw grid lines
1045             * @see     #setGridColor
1046             */
1047            public Color getGridColor() {
1048                return gridColor;
1049            }
1050
1051            /**
1052             *  Sets whether the table draws grid lines around cells.
1053             *  If <code>showGrid</code> is true it does; if it is false it doesn't.
1054             *  There is no <code>getShowGrid</code> method as this state is held
1055             *  in two variables -- <code>showHorizontalLines</code> and <code>showVerticalLines</code> --
1056             *  each of which can be queried independently.
1057             *
1058             * @param   showGrid                 true if table view should draw grid lines
1059             *
1060             * @see     #setShowVerticalLines
1061             * @see     #setShowHorizontalLines
1062             * @beaninfo
1063             *  description: The color used to draw the grid lines.
1064             */
1065            public void setShowGrid(boolean showGrid) {
1066                setShowHorizontalLines(showGrid);
1067                setShowVerticalLines(showGrid);
1068
1069                // Redraw
1070                repaint();
1071            }
1072
1073            /**
1074             *  Sets whether the table draws horizontal lines between cells.
1075             *  If <code>showHorizontalLines</code> is true it does; if it is false it doesn't.
1076             *
1077             * @param   showHorizontalLines      true if table view should draw horizontal lines
1078             * @see     #getShowHorizontalLines
1079             * @see     #setShowGrid
1080             * @see     #setShowVerticalLines
1081             * @beaninfo
1082             *  bound: true
1083             *  description: Whether horizontal lines should be drawn in between the cells.
1084             */
1085            public void setShowHorizontalLines(boolean showHorizontalLines) {
1086                boolean old = this .showHorizontalLines;
1087                this .showHorizontalLines = showHorizontalLines;
1088                firePropertyChange("showHorizontalLines", old,
1089                        showHorizontalLines);
1090
1091                // Redraw
1092                repaint();
1093            }
1094
1095            /**
1096             *  Sets whether the table draws vertical lines between cells.
1097             *  If <code>showVerticalLines</code> is true it does; if it is false it doesn't.
1098             *
1099             * @param   showVerticalLines              true if table view should draw vertical lines
1100             * @see     #getShowVerticalLines
1101             * @see     #setShowGrid
1102             * @see     #setShowHorizontalLines
1103             * @beaninfo
1104             *  bound: true
1105             *  description: Whether vertical lines should be drawn in between the cells.
1106             */
1107            public void setShowVerticalLines(boolean showVerticalLines) {
1108                boolean old = this .showVerticalLines;
1109                this .showVerticalLines = showVerticalLines;
1110                firePropertyChange("showVerticalLines", old, showVerticalLines);
1111                // Redraw
1112                repaint();
1113            }
1114
1115            /**
1116             * Returns true if the table draws horizontal lines between cells, false if it
1117             * doesn't. The default is true.
1118             *
1119             * @return  true if the table draws horizontal lines between cells, false if it
1120             *          doesn't
1121             * @see     #setShowHorizontalLines
1122             */
1123            public boolean getShowHorizontalLines() {
1124                return showHorizontalLines;
1125            }
1126
1127            /**
1128             * Returns true if the table draws vertical lines between cells, false if it
1129             * doesn't. The default is true.
1130             *
1131             * @return  true if the table draws vertical lines between cells, false if it
1132             *          doesn't
1133             * @see     #setShowVerticalLines
1134             */
1135            public boolean getShowVerticalLines() {
1136                return showVerticalLines;
1137            }
1138
1139            /**
1140             * Sets the table's auto resize mode when the table is resized.  For further
1141             * information on how the different resize modes work, see
1142             * {@link #doLayout}.
1143             *
1144             * @param   mode One of 5 legal values:
1145             *                   AUTO_RESIZE_OFF,
1146             *                   AUTO_RESIZE_NEXT_COLUMN,
1147             *                   AUTO_RESIZE_SUBSEQUENT_COLUMNS,
1148             *                   AUTO_RESIZE_LAST_COLUMN,
1149             *                   AUTO_RESIZE_ALL_COLUMNS
1150             *
1151             * @see     #getAutoResizeMode
1152             * @see     #doLayout
1153             * @beaninfo
1154             *  bound: true
1155             *  description: Whether the columns should adjust themselves automatically.
1156             *        enum: AUTO_RESIZE_OFF                JTable.AUTO_RESIZE_OFF
1157             *              AUTO_RESIZE_NEXT_COLUMN        JTable.AUTO_RESIZE_NEXT_COLUMN
1158             *              AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS
1159             *              AUTO_RESIZE_LAST_COLUMN        JTable.AUTO_RESIZE_LAST_COLUMN
1160             *              AUTO_RESIZE_ALL_COLUMNS        JTable.AUTO_RESIZE_ALL_COLUMNS
1161             */
1162            public void setAutoResizeMode(int mode) {
1163                if ((mode == AUTO_RESIZE_OFF)
1164                        || (mode == AUTO_RESIZE_NEXT_COLUMN)
1165                        || (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS)
1166                        || (mode == AUTO_RESIZE_LAST_COLUMN)
1167                        || (mode == AUTO_RESIZE_ALL_COLUMNS)) {
1168                    int old = autoResizeMode;
1169                    autoResizeMode = mode;
1170                    resizeAndRepaint();
1171                    if (tableHeader != null) {
1172                        tableHeader.resizeAndRepaint();
1173                    }
1174                    firePropertyChange("autoResizeMode", old, autoResizeMode);
1175                }
1176            }
1177
1178            /**
1179             * Returns the auto resize mode of the table.  The default mode
1180             * is AUTO_RESIZE_SUBSEQUENT_COLUMNS.
1181             *
1182             * @return  the autoResizeMode of the table
1183             *
1184             * @see     #setAutoResizeMode
1185             * @see     #doLayout
1186             */
1187            public int getAutoResizeMode() {
1188                return autoResizeMode;
1189            }
1190
1191            /**
1192             * Sets this table's <code>autoCreateColumnsFromModel</code> flag.
1193             * This method calls <code>createDefaultColumnsFromModel</code> if
1194             * <code>autoCreateColumnsFromModel</code> changes from false to true.
1195             *
1196             * @param   autoCreateColumnsFromModel   true if <code>JTable</code> should automatically create columns
1197             * @see     #getAutoCreateColumnsFromModel
1198             * @see     #createDefaultColumnsFromModel
1199             * @beaninfo
1200             *  bound: true
1201             *  description: Automatically populates the columnModel when a new TableModel is submitted.
1202             */
1203            public void setAutoCreateColumnsFromModel(
1204                    boolean autoCreateColumnsFromModel) {
1205                if (this .autoCreateColumnsFromModel != autoCreateColumnsFromModel) {
1206                    boolean old = this .autoCreateColumnsFromModel;
1207                    this .autoCreateColumnsFromModel = autoCreateColumnsFromModel;
1208                    if (autoCreateColumnsFromModel) {
1209                        createDefaultColumnsFromModel();
1210                    }
1211                    firePropertyChange("autoCreateColumnsFromModel", old,
1212                            autoCreateColumnsFromModel);
1213                }
1214            }
1215
1216            /**
1217             * Determines whether the table will create default columns from the model.
1218             * If true, <code>setModel</code> will clear any existing columns and
1219             * create new columns from the new model.  Also, if the event in
1220             * the <code>tableChanged</code> notification specifies that the
1221             * entire table changed, then the columns will be rebuilt.
1222             * The default is true.
1223             *
1224             * @return  the autoCreateColumnsFromModel of the table
1225             * @see     #setAutoCreateColumnsFromModel
1226             * @see     #createDefaultColumnsFromModel
1227             */
1228            public boolean getAutoCreateColumnsFromModel() {
1229                return autoCreateColumnsFromModel;
1230            }
1231
1232            /**
1233             * Creates default columns for the table from
1234             * the data model using the <code>getColumnCount</code> method
1235             * defined in the <code>TableModel</code> interface.
1236             * <p>
1237             * Clears any existing columns before creating the
1238             * new columns based on information from the model.
1239             *
1240             * @see     #getAutoCreateColumnsFromModel
1241             */
1242            public void createDefaultColumnsFromModel() {
1243                TableModel m = getModel();
1244                if (m != null) {
1245                    // Remove any current columns
1246                    TableColumnModel cm = getColumnModel();
1247                    while (cm.getColumnCount() > 0) {
1248                        cm.removeColumn(cm.getColumn(0));
1249                    }
1250
1251                    // Create new columns from the data model info
1252                    for (int i = 0; i < m.getColumnCount(); i++) {
1253                        TableColumn newColumn = new TableColumn(i);
1254                        addColumn(newColumn);
1255                    }
1256                }
1257            }
1258
1259            /**
1260             * Sets a default cell renderer to be used if no renderer has been set in
1261             * a <code>TableColumn</code>. If renderer is <code>null</code>,
1262             * removes the default renderer for this column class.
1263             *
1264             * @param  columnClass     set the default cell renderer for this columnClass
1265             * @param  renderer        default cell renderer to be used for this
1266             *			       columnClass
1267             * @see     #getDefaultRenderer
1268             * @see     #setDefaultEditor
1269             */
1270            public void setDefaultRenderer(Class<?> columnClass,
1271                    TableCellRenderer renderer) {
1272                if (renderer != null) {
1273                    defaultRenderersByColumnClass.put(columnClass, renderer);
1274                } else {
1275                    defaultRenderersByColumnClass.remove(columnClass);
1276                }
1277            }
1278
1279            /**
1280             * Returns the cell renderer to be used when no renderer has been set in
1281             * a <code>TableColumn</code>. During the rendering of cells the renderer is fetched from
1282             * a <code>Hashtable</code> of entries according to the class of the cells in the column. If
1283             * there is no entry for this <code>columnClass</code> the method returns
1284             * the entry for the most specific superclass. The <code>JTable</code> installs entries
1285             * for <code>Object</code>, <code>Number</code>, and <code>Boolean</code>, all of which can be modified
1286             * or replaced.
1287             *
1288             * @param   columnClass   return the default cell renderer
1289             *			      for this columnClass
1290             * @return  the renderer for this columnClass
1291             * @see     #setDefaultRenderer
1292             * @see     #getColumnClass
1293             */
1294            public TableCellRenderer getDefaultRenderer(Class<?> columnClass) {
1295                if (columnClass == null) {
1296                    return null;
1297                } else {
1298                    Object renderer = defaultRenderersByColumnClass
1299                            .get(columnClass);
1300                    if (renderer != null) {
1301                        return (TableCellRenderer) renderer;
1302                    } else {
1303                        return getDefaultRenderer(columnClass.getSuperclass());
1304                    }
1305                }
1306            }
1307
1308            /**
1309             * Sets a default cell editor to be used if no editor has been set in
1310             * a <code>TableColumn</code>. If no editing is required in a table, or a
1311             * particular column in a table, uses the <code>isCellEditable</code>
1312             * method in the <code>TableModel</code> interface to ensure that this
1313             * <code>JTable</code> will not start an editor in these columns.
1314             * If editor is <code>null</code>, removes the default editor for this
1315             * column class.
1316             *
1317             * @param  columnClass  set the default cell editor for this columnClass
1318             * @param  editor   default cell editor to be used for this columnClass
1319             * @see     TableModel#isCellEditable
1320             * @see     #getDefaultEditor
1321             * @see     #setDefaultRenderer
1322             */
1323            public void setDefaultEditor(Class<?> columnClass,
1324                    TableCellEditor editor) {
1325                if (editor != null) {
1326                    defaultEditorsByColumnClass.put(columnClass, editor);
1327                } else {
1328                    defaultEditorsByColumnClass.remove(columnClass);
1329                }
1330            }
1331
1332            /**
1333             * Returns the editor to be used when no editor has been set in
1334             * a <code>TableColumn</code>. During the editing of cells the editor is fetched from
1335             * a <code>Hashtable</code> of entries according to the class of the cells in the column. If
1336             * there is no entry for this <code>columnClass</code> the method returns
1337             * the entry for the most specific superclass. The <code>JTable</code> installs entries
1338             * for <code>Object</code>, <code>Number</code>, and <code>Boolean</code>, all of which can be modified
1339             * or replaced.
1340             *
1341             * @param   columnClass  return the default cell editor for this columnClass
1342             * @return the default cell editor to be used for this columnClass
1343             * @see     #setDefaultEditor
1344             * @see     #getColumnClass
1345             */
1346            public TableCellEditor getDefaultEditor(Class<?> columnClass) {
1347                if (columnClass == null) {
1348                    return null;
1349                } else {
1350                    Object editor = defaultEditorsByColumnClass
1351                            .get(columnClass);
1352                    if (editor != null) {
1353                        return (TableCellEditor) editor;
1354                    } else {
1355                        return getDefaultEditor(columnClass.getSuperclass());
1356                    }
1357                }
1358            }
1359
1360            /**
1361             * Turns on or off automatic drag handling. In order to enable automatic
1362             * drag handling, this property should be set to {@code true}, and the
1363             * table's {@code TransferHandler} needs to be {@code non-null}.
1364             * The default value of the {@code dragEnabled} property is {@code false}.
1365             * <p>
1366             * The job of honoring this property, and recognizing a user drag gesture,
1367             * lies with the look and feel implementation, and in particular, the table's
1368             * {@code TableUI}. When automatic drag handling is enabled, most look and
1369             * feels (including those that subclass {@code BasicLookAndFeel}) begin a
1370             * drag and drop operation whenever the user presses the mouse button over
1371             * an item (in single selection mode) or a selection (in other selection
1372             * modes) and then moves the mouse a few pixels. Setting this property to
1373             * {@code true} can therefore have a subtle effect on how selections behave.
1374             * <p>
1375             * If a look and feel is used that ignores this property, you can still
1376             * begin a drag and drop operation by calling {@code exportAsDrag} on the
1377             * table's {@code TransferHandler}.
1378             *
1379             * @param b whether or not to enable automatic drag handling
1380             * @exception HeadlessException if
1381             *            <code>b</code> is <code>true</code> and
1382             *            <code>GraphicsEnvironment.isHeadless()</code>
1383             *            returns <code>true</code>
1384             * @see java.awt.GraphicsEnvironment#isHeadless
1385             * @see #getDragEnabled
1386             * @see #setTransferHandler
1387             * @see TransferHandler
1388             * @since 1.4
1389             *
1390             * @beaninfo
1391             *  description: determines whether automatic drag handling is enabled
1392             *        bound: false
1393             */
1394            public void setDragEnabled(boolean b) {
1395                if (b && GraphicsEnvironment.isHeadless()) {
1396                    throw new HeadlessException();
1397                }
1398                dragEnabled = b;
1399            }
1400
1401            /**
1402             * Returns whether or not automatic drag handling is enabled.
1403             *
1404             * @return the value of the {@code dragEnabled} property
1405             * @see #setDragEnabled
1406             * @since 1.4
1407             */
1408            public boolean getDragEnabled() {
1409                return dragEnabled;
1410            }
1411
1412            /**
1413             * Sets the drop mode for this component. For backward compatibility,
1414             * the default for this property is <code>DropMode.USE_SELECTION</code>.
1415             * Usage of one of the other modes is recommended, however, for an
1416             * improved user experience. <code>DropMode.ON</code>, for instance,
1417             * offers similar behavior of showing items as selected, but does so without
1418             * affecting the actual selection in the table.
1419             * <p>
1420             * <code>JTable</code> supports the following drop modes:
1421             * <ul>
1422             *    <li><code>DropMode.USE_SELECTION</code></li>
1423             *    <li><code>DropMode.ON</code></li>
1424             *    <li><code>DropMode.INSERT</code></li>
1425             *    <li><code>DropMode.INSERT_ROWS</code></li>
1426             *    <li><code>DropMode.INSERT_COLS</code></li>
1427             *    <li><code>DropMode.ON_OR_INSERT</code></li>
1428             *    <li><code>DropMode.ON_OR_INSERT_ROWS</code></li>
1429             *    <li><code>DropMode.ON_OR_INSERT_COLS</code></li>
1430             * </ul>
1431             * <p>
1432             * The drop mode is only meaningful if this component has a
1433             * <code>TransferHandler</code> that accepts drops.
1434             *
1435             * @param dropMode the drop mode to use
1436             * @throws IllegalArgumentException if the drop mode is unsupported
1437             *         or <code>null</code>
1438             * @see #getDropMode
1439             * @see #getDropLocation
1440             * @see #setTransferHandler
1441             * @see TransferHandler
1442             * @since 1.6
1443             */
1444            public final void setDropMode(DropMode dropMode) {
1445                if (dropMode != null) {
1446                    switch (dropMode) {
1447                    case USE_SELECTION:
1448                    case ON:
1449                    case INSERT:
1450                    case INSERT_ROWS:
1451                    case INSERT_COLS:
1452                    case ON_OR_INSERT:
1453                    case ON_OR_INSERT_ROWS:
1454                    case ON_OR_INSERT_COLS:
1455                        this .dropMode = dropMode;
1456                        return;
1457                    }
1458                }
1459
1460                throw new IllegalArgumentException(dropMode
1461                        + ": Unsupported drop mode for table");
1462            }
1463
1464            /**
1465             * Returns the drop mode for this component.
1466             *
1467             * @return the drop mode for this component
1468             * @see #setDropMode
1469             * @since 1.6
1470             */
1471            public final DropMode getDropMode() {
1472                return dropMode;
1473            }
1474
1475            /**
1476             * Calculates a drop location in this component, representing where a
1477             * drop at the given point should insert data.
1478             *
1479             * @param p the point to calculate a drop location for
1480             * @return the drop location, or <code>null</code>
1481             */
1482            DropLocation dropLocationForPoint(Point p) {
1483                DropLocation location = null;
1484
1485                int row = rowAtPoint(p);
1486                int col = columnAtPoint(p);
1487                boolean outside = Boolean.TRUE == getClientProperty("Table.isFileList")
1488                        && SwingUtilities2.pointOutsidePrefSize(this , row, col,
1489                                p);
1490
1491                Rectangle rect = getCellRect(row, col, true);
1492                Section xSection, ySection;
1493                boolean between = false;
1494                boolean ltr = getComponentOrientation().isLeftToRight();
1495
1496                switch (dropMode) {
1497                case USE_SELECTION:
1498                case ON:
1499                    if (row == -1 || col == -1 || outside) {
1500                        location = new DropLocation(p, -1, -1, false, false);
1501                    } else {
1502                        location = new DropLocation(p, row, col, false, false);
1503                    }
1504                    break;
1505                case INSERT:
1506                    if (row == -1 && col == -1) {
1507                        location = new DropLocation(p, 0, 0, true, true);
1508                        break;
1509                    }
1510
1511                    xSection = SwingUtilities2.liesInHorizontal(rect, p, ltr,
1512                            true);
1513
1514                    if (row == -1) {
1515                        if (xSection == LEADING) {
1516                            location = new DropLocation(p, getRowCount(), col,
1517                                    true, true);
1518                        } else if (xSection == TRAILING) {
1519                            location = new DropLocation(p, getRowCount(),
1520                                    col + 1, true, true);
1521                        } else {
1522                            location = new DropLocation(p, getRowCount(), col,
1523                                    true, false);
1524                        }
1525                    } else if (xSection == LEADING || xSection == TRAILING) {
1526                        ySection = SwingUtilities2
1527                                .liesInVertical(rect, p, true);
1528                        if (ySection == LEADING) {
1529                            between = true;
1530                        } else if (ySection == TRAILING) {
1531                            row++;
1532                            between = true;
1533                        }
1534
1535                        location = new DropLocation(p, row,
1536                                xSection == TRAILING ? col + 1 : col, between,
1537                                true);
1538                    } else {
1539                        if (SwingUtilities2.liesInVertical(rect, p, false) == TRAILING) {
1540                            row++;
1541                        }
1542
1543                        location = new DropLocation(p, row, col, true, false);
1544                    }
1545
1546                    break;
1547                case INSERT_ROWS:
1548                    if (row == -1 && col == -1) {
1549                        location = new DropLocation(p, -1, -1, false, false);
1550                        break;
1551                    }
1552
1553                    if (row == -1) {
1554                        location = new DropLocation(p, getRowCount(), col,
1555                                true, false);
1556                        break;
1557                    }
1558
1559                    if (SwingUtilities2.liesInVertical(rect, p, false) == TRAILING) {
1560                        row++;
1561                    }
1562
1563                    location = new DropLocation(p, row, col, true, false);
1564                    break;
1565                case ON_OR_INSERT_ROWS:
1566                    if (row == -1 && col == -1) {
1567                        location = new DropLocation(p, -1, -1, false, false);
1568                        break;
1569                    }
1570
1571                    if (row == -1) {
1572                        location = new DropLocation(p, getRowCount(), col,
1573                                true, false);
1574                        break;
1575                    }
1576
1577                    ySection = SwingUtilities2.liesInVertical(rect, p, true);
1578                    if (ySection == LEADING) {
1579                        between = true;
1580                    } else if (ySection == TRAILING) {
1581                        row++;
1582                        between = true;
1583                    }
1584
1585                    location = new DropLocation(p, row, col, between, false);
1586                    break;
1587                case INSERT_COLS:
1588                    if (row == -1) {
1589                        location = new DropLocation(p, -1, -1, false, false);
1590                        break;
1591                    }
1592
1593                    if (col == -1) {
1594                        location = new DropLocation(p, getColumnCount(), col,
1595                                false, true);
1596                        break;
1597                    }
1598
1599                    if (SwingUtilities2.liesInHorizontal(rect, p, ltr, false) == TRAILING) {
1600                        col++;
1601                    }
1602
1603                    location = new DropLocation(p, row, col, false, true);
1604                    break;
1605                case ON_OR_INSERT_COLS:
1606                    if (row == -1) {
1607                        location = new DropLocation(p, -1, -1, false, false);
1608                        break;
1609                    }
1610
1611                    if (col == -1) {
1612                        location = new DropLocation(p, row, getColumnCount(),
1613                                false, true);
1614                        break;
1615                    }
1616
1617                    xSection = SwingUtilities2.liesInHorizontal(rect, p, ltr,
1618                            true);
1619                    if (xSection == LEADING) {
1620                        between = true;
1621                    } else if (xSection == TRAILING) {
1622                        col++;
1623                        between = true;
1624                    }
1625
1626                    location = new DropLocation(p, row, col, false, between);
1627                    break;
1628                case ON_OR_INSERT:
1629                    if (row == -1 && col == -1) {
1630                        location = new DropLocation(p, 0, 0, true, true);
1631                        break;
1632                    }
1633
1634                    xSection = SwingUtilities2.liesInHorizontal(rect, p, ltr,
1635                            true);
1636
1637                    if (row == -1) {
1638                        if (xSection == LEADING) {
1639                            location = new DropLocation(p, getRowCount(), col,
1640                                    true, true);
1641                        } else if (xSection == TRAILING) {
1642                            location = new DropLocation(p, getRowCount(),
1643                                    col + 1, true, true);
1644                        } else {
1645                            location = new DropLocation(p, getRowCount(), col,
1646                                    true, false);
1647                        }
1648
1649                        break;
1650                    }
1651
1652                    ySection = SwingUtilities2.liesInVertical(rect, p, true);
1653                    if (ySection == LEADING) {
1654                        between = true;
1655                    } else if (ySection == TRAILING) {
1656                        row++;
1657                        between = true;
1658                    }
1659
1660                    location = new DropLocation(p, row,
1661                            xSection == TRAILING ? col + 1 : col, between,
1662                            xSection != MIDDLE);
1663
1664                    break;
1665                default:
1666                    assert false : "Unexpected drop mode";
1667                }
1668
1669                return location;
1670            }
1671
1672            /**
1673             * Called to set or clear the drop location during a DnD operation.
1674             * In some cases, the component may need to use it's internal selection
1675             * temporarily to indicate the drop location. To help facilitate this,
1676             * this method returns and accepts as a parameter a state object.
1677             * This state object can be used to store, and later restore, the selection
1678             * state. Whatever this method returns will be passed back to it in
1679             * future calls, as the state parameter. If it wants the DnD system to
1680             * continue storing the same state, it must pass it back every time.
1681             * Here's how this is used:
1682             * <p>
1683             * Let's say that on the first call to this method the component decides
1684             * to save some state (because it is about to use the selection to show
1685             * a drop index). It can return a state object to the caller encapsulating
1686             * any saved selection state. On a second call, let's say the drop location
1687             * is being changed to something else. The component doesn't need to
1688             * restore anything yet, so it simply passes back the same state object
1689             * to have the DnD system continue storing it. Finally, let's say this
1690             * method is messaged with <code>null</code>. This means DnD
1691             * is finished with this component for now, meaning it should restore
1692             * state. At this point, it can use the state parameter to restore
1693             * said state, and of course return <code>null</code> since there's
1694             * no longer anything to store.
1695             *
1696             * @param location the drop location (as calculated by
1697             *        <code>dropLocationForPoint</code>) or <code>null</code>
1698             *        if there's no longer a valid drop location
1699             * @param state the state object saved earlier for this component,
1700             *        or <code>null</code>
1701             * @param forDrop whether or not the method is being called because an
1702             *        actual drop occurred
1703             * @return any saved state for this component, or <code>null</code> if none
1704             */
1705            Object setDropLocation(TransferHandler.DropLocation location,
1706                    Object state, boolean forDrop) {
1707
1708                Object retVal = null;
1709                DropLocation tableLocation = (DropLocation) location;
1710
1711                if (dropMode == DropMode.USE_SELECTION) {
1712                    if (tableLocation == null) {
1713                        if (!forDrop && state != null) {
1714                            clearSelection();
1715
1716                            int[] rows = (int[]) ((int[][]) state)[0];
1717                            int[] cols = (int[]) ((int[][]) state)[1];
1718                            int[] anchleads = (int[]) ((int[][]) state)[2];
1719
1720                            for (int i = 0; i < rows.length; i++) {
1721                                addRowSelectionInterval(rows[i], rows[i]);
1722                            }
1723
1724                            for (int i = 0; i < cols.length; i++) {
1725                                addColumnSelectionInterval(cols[i], cols[i]);
1726                            }
1727
1728                            SwingUtilities2.setLeadAnchorWithoutSelection(
1729                                    getSelectionModel(), anchleads[1],
1730                                    anchleads[0]);
1731
1732                            SwingUtilities2.setLeadAnchorWithoutSelection(
1733                                    getColumnModel().getSelectionModel(),
1734                                    anchleads[3], anchleads[2]);
1735                        }
1736                    } else {
1737                        if (dropLocation == null) {
1738                            retVal = new int[][] {
1739                                    getSelectedRows(),
1740                                    getSelectedColumns(),
1741                                    {
1742                                            getAdjustedIndex(
1743                                                    getSelectionModel()
1744                                                            .getAnchorSelectionIndex(),
1745                                                    true),
1746                                            getAdjustedIndex(
1747                                                    getSelectionModel()
1748                                                            .getLeadSelectionIndex(),
1749                                                    true),
1750                                            getAdjustedIndex(getColumnModel()
1751                                                    .getSelectionModel()
1752                                                    .getAnchorSelectionIndex(),
1753                                                    false),
1754                                            getAdjustedIndex(getColumnModel()
1755                                                    .getSelectionModel()
1756                                                    .getLeadSelectionIndex(),
1757                                                    false) } };
1758                        } else {
1759                            retVal = state;
1760                        }
1761
1762                        if (tableLocation.getRow() == -1) {
1763                            clearSelectionAndLeadAnchor();
1764                        } else {
1765                            setRowSelectionInterval(tableLocation.getRow(),
1766                                    tableLocation.getRow());
1767                            setColumnSelectionInterval(tableLocation
1768                                    .getColumn(), tableLocation.getColumn());
1769                        }
1770                    }
1771                }
1772
1773                DropLocation old = dropLocation;
1774                dropLocation = tableLocation;
1775                firePropertyChange("dropLocation", old, dropLocation);
1776
1777                return retVal;
1778            }
1779
1780            /**
1781             * Returns the location that this component should visually indicate
1782             * as the drop location during a DnD operation over the component,
1783             * or {@code null} if no location is to currently be shown.
1784             * <p>
1785             * This method is not meant for querying the drop location
1786             * from a {@code TransferHandler}, as the drop location is only
1787             * set after the {@code TransferHandler}'s <code>canImport</code>
1788             * has returned and has allowed for the location to be shown.
1789             * <p>
1790             * When this property changes, a property change event with
1791             * name "dropLocation" is fired by the component.
1792             *
1793             * @return the drop location
1794             * @see #setDropMode
1795             * @see TransferHandler#canImport(TransferHandler.TransferSupport)
1796             * @since 1.6
1797             */
1798            public final DropLocation getDropLocation() {
1799                return dropLocation;
1800            }
1801
1802            /**
1803             * Specifies whether a {@code RowSorter} should be created for the
1804             * table whenever its model changes.
1805             * <p>
1806             * When {@code setAutoCreateRowSorter(true)} is invoked, a {@code
1807             * TableRowSorter} is immediately created and installed on the
1808             * table.  While the {@code autoCreateRowSorter} property remains
1809             * {@code true}, every time the model is changed, a new {@code
1810             * TableRowSorter} is created and set as the table's row sorter.
1811             *
1812             * @param autoCreateRowSorter whether or not a {@code RowSorter}
1813             *        should be automatically created
1814             * @see javax.swing.table.TableRowSorter
1815             * @beaninfo
1816             *        bound: true
1817             *    preferred: true
1818             *  description: Whether or not to turn on sorting by default.
1819             * @since 1.6
1820             */
1821            public void setAutoCreateRowSorter(boolean autoCreateRowSorter) {
1822                boolean oldValue = this .autoCreateRowSorter;
1823                this .autoCreateRowSorter = autoCreateRowSorter;
1824                if (autoCreateRowSorter) {
1825                    setRowSorter(new TableRowSorter(getModel()));
1826                }
1827                firePropertyChange("autoCreateRowSorter", oldValue,
1828                        autoCreateRowSorter);
1829            }
1830
1831            /**
1832             * Returns {@code true} if whenever the model changes, a new
1833             * {@code RowSorter} should be created and installed
1834             * as the table's sorter; otherwise, returns {@code false}. 
1835             *
1836             * @return true if a {@code RowSorter} should be created when
1837             *         the model changes
1838             * @since 1.6
1839             */
1840            public boolean getAutoCreateRowSorter() {
1841                return autoCreateRowSorter;
1842            }
1843
1844            /**
1845             * Specifies whether the selection should be updated after sorting.
1846             * If true, on sorting the selection is reset such that
1847             * the same rows, in terms of the model, remain selected.  The default
1848             * is true.
1849             *
1850             * @param update whether or not to update the selection on sorting
1851             * @beaninfo
1852             *        bound: true
1853             *       expert: true
1854             *  description: Whether or not to update the selection on sorting
1855             * @since 1.6
1856             */
1857            public void setUpdateSelectionOnSort(boolean update) {
1858                if (updateSelectionOnSort != update) {
1859                    updateSelectionOnSort = update;
1860                    firePropertyChange("updateSelectionOnSort", !update, update);
1861                }
1862            }
1863
1864            /**
1865             * Returns true if the selection should be updated after sorting.
1866             *
1867             * @return whether to update the selection on a sort
1868             * @since 1.6
1869             */
1870            public boolean getUpdateSelectionOnSort() {
1871                return updateSelectionOnSort;
1872            }
1873
1874            /**
1875             * Sets the <code>RowSorter</code>.  <code>RowSorter</code> is used
1876             * to provide sorting and filtering to a <code>JTable</code>.
1877             * <p>
1878             * This method clears the selection and resets any variable row heights.
1879             * <p>
1880             * If the underlying model of the <code>RowSorter</code> differs from
1881             * that of this <code>JTable</code> undefined behavior will result.
1882             *
1883             * @param sorter the <code>RowSorter</code>; <code>null</code> turns
1884             *        sorting off
1885             * @see javax.swing.table.TableRowSorter
1886             * @since 1.6
1887             */
1888            public void setRowSorter(RowSorter<? extends TableModel> sorter) {
1889                RowSorter<? extends TableModel> oldRowSorter = null;
1890                if (sortManager != null) {
1891                    oldRowSorter = sortManager.sorter;
1892                    sortManager.dispose();
1893                    sortManager = null;
1894                }
1895                rowModel = null;
1896                clearSelectionAndLeadAnchor();
1897                if (sorter != null) {
1898                    sortManager = new SortManager(sorter);
1899                }
1900                resizeAndRepaint();
1901                firePropertyChange("sorter", oldRowSorter, sorter);
1902            }
1903
1904            /**
1905             * Returns the object responsible for sorting.
1906             *
1907             * @return the object responsible for sorting
1908             * @since 1.6
1909             */
1910            public RowSorter<? extends TableModel> getRowSorter() {
1911                return (sortManager != null) ? sortManager.sorter : null;
1912            }
1913
1914            //
1915            // Selection methods
1916            //
1917            /**
1918             * Sets the table's selection mode to allow only single selections, a single
1919             * contiguous interval, or multiple intervals.
1920             * <P>
1921             * <bold>Note:</bold>
1922             * <code>JTable</code> provides all the methods for handling
1923             * column and row selection.  When setting states,
1924             * such as <code>setSelectionMode</code>, it not only
1925             * updates the mode for the row selection model but also sets similar
1926             * values in the selection model of the <code>columnModel</code>.
1927             * If you want to have the row and column selection models operating
1928             * in different modes, set them both directly.
1929             * <p>
1930             * Both the row and column selection models for <code>JTable</code>
1931             * default to using a <code>DefaultListSelectionModel</code>
1932             * so that <code>JTable</code> works the same way as the
1933             * <code>JList</code>. See the <code>setSelectionMode</code> method
1934             * in <code>JList</code> for details about the modes.
1935             *
1936             * @see JList#setSelectionMode
1937             * @beaninfo
1938             * description: The selection mode used by the row and column selection models.
1939             *        enum: SINGLE_SELECTION            ListSelectionModel.SINGLE_SELECTION
1940             *              SINGLE_INTERVAL_SELECTION   ListSelectionModel.SINGLE_INTERVAL_SELECTION
1941             *              MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
1942             */
1943            public void setSelectionMode(int selectionMode) {
1944                clearSelection();
1945                getSelectionModel().setSelectionMode(selectionMode);
1946                getColumnModel().getSelectionModel().setSelectionMode(
1947                        selectionMode);
1948            }
1949
1950            /**
1951             * Sets whether the rows in this model can be selected.
1952             *
1953             * @param rowSelectionAllowed   true if this model will allow row selection
1954             * @see #getRowSelectionAllowed
1955             * @beaninfo
1956             *  bound: true
1957             *    attribute: visualUpdate true
1958             *  description: If true, an entire row is selected for each selected cell.
1959             */
1960            public void setRowSelectionAllowed(boolean rowSelectionAllowed) {
1961                boolean old = this .rowSelectionAllowed;
1962                this .rowSelectionAllowed = rowSelectionAllowed;
1963                if (old != rowSelectionAllowed) {
1964                    repaint();
1965                }
1966                firePropertyChange("rowSelectionAllowed", old,
1967                        rowSelectionAllowed);
1968            }
1969
1970            /**
1971             * Returns true if rows can be selected.
1972             *
1973             * @return true if rows can be selected, otherwise false
1974             * @see #setRowSelectionAllowed
1975             */
1976            public boolean getRowSelectionAllowed() {
1977                return rowSelectionAllowed;
1978            }
1979
1980            /**
1981             * Sets whether the columns in this model can be selected.
1982             *
1983             * @param columnSelectionAllowed   true if this model will allow column selection
1984             * @see #getColumnSelectionAllowed
1985             * @beaninfo
1986             *  bound: true
1987             *    attribute: visualUpdate true
1988             *  description: If true, an entire column is selected for each selected cell.
1989             */
1990            public void setColumnSelectionAllowed(boolean columnSelectionAllowed) {
1991                boolean old = columnModel.getColumnSelectionAllowed();
1992                columnModel.setColumnSelectionAllowed(columnSelectionAllowed);
1993                if (old != columnSelectionAllowed) {
1994                    repaint();
1995                }
1996                firePropertyChange("columnSelectionAllowed", old,
1997                        columnSelectionAllowed);
1998            }
1999
2000            /**
2001             * Returns true if columns can be selected.
2002             *
2003             * @return true if columns can be selected, otherwise false
2004             * @see #setColumnSelectionAllowed
2005             */
2006            public boolean getColumnSelectionAllowed() {
2007                return columnModel.getColumnSelectionAllowed();
2008            }
2009
2010            /**
2011             * Sets whether this table allows both a column selection and a
2012             * row selection to exist simultaneously. When set,
2013             * the table treats the intersection of the row and column selection
2014             * models as the selected cells. Override <code>isCellSelected</code> to
2015             * change this default behavior. This method is equivalent to setting
2016             * both the <code>rowSelectionAllowed</code> property and
2017             * <code>columnSelectionAllowed</code> property of the
2018             * <code>columnModel</code> to the supplied value.
2019             *
2020             * @param  cellSelectionEnabled   	true if simultaneous row and column
2021             *					selection is allowed
2022             * @see #getCellSelectionEnabled
2023             * @see #isCellSelected
2024             * @beaninfo
2025             *  bound: true
2026             *    attribute: visualUpdate true
2027             *  description: Select a rectangular region of cells rather than
2028             *		     rows or columns.
2029             */
2030            public void setCellSelectionEnabled(boolean cellSelectionEnabled) {
2031                setRowSelectionAllowed(cellSelectionEnabled);
2032                setColumnSelectionAllowed(cellSelectionEnabled);
2033                boolean old = this .cellSelectionEnabled;
2034                this .cellSelectionEnabled = cellSelectionEnabled;
2035                firePropertyChange("cellSelectionEnabled", old,
2036                        cellSelectionEnabled);
2037            }
2038
2039            /**
2040             * Returns true if both row and column selection models are enabled.
2041             * Equivalent to <code>getRowSelectionAllowed() &&
2042             * getColumnSelectionAllowed()</code>.
2043             *
2044             * @return true if both row and column selection models are enabled
2045             *
2046             * @see #setCellSelectionEnabled
2047             */
2048            public boolean getCellSelectionEnabled() {
2049                return getRowSelectionAllowed() && getColumnSelectionAllowed();
2050            }
2051
2052            /**
2053             *  Selects all rows, columns, and cells in the table.
2054             */
2055            public void selectAll() {
2056                // If I'm currently editing, then I should stop editing
2057                if (isEditing()) {
2058                    removeEditor();
2059                }
2060                if (getRowCount() > 0 && getColumnCount() > 0) {
2061                    int oldLead;
2062                    int oldAnchor;
2063                    ListSelectionModel selModel;
2064
2065                    selModel = selectionModel;
2066                    selModel.setValueIsAdjusting(true);
2067                    oldLead = getAdjustedIndex(
2068                            selModel.getLeadSelectionIndex(), true);
2069                    oldAnchor = getAdjustedIndex(selModel
2070                            .getAnchorSelectionIndex(), true);
2071
2072                    setRowSelectionInterval(0, getRowCount() - 1);
2073
2074                    // this is done to restore the anchor and lead
2075                    SwingUtilities2.setLeadAnchorWithoutSelection(selModel,
2076                            oldLead, oldAnchor);
2077
2078                    selModel.setValueIsAdjusting(false);
2079
2080                    selModel = columnModel.getSelectionModel();
2081                    selModel.setValueIsAdjusting(true);
2082                    oldLead = getAdjustedIndex(
2083                            selModel.getLeadSelectionIndex(), false);
2084                    oldAnchor = getAdjustedIndex(selModel
2085                            .getAnchorSelectionIndex(), false);
2086
2087                    setColumnSelectionInterval(0, getColumnCount() - 1);
2088
2089                    // this is done to restore the anchor and lead
2090                    SwingUtilities2.setLeadAnchorWithoutSelection(selModel,
2091                            oldLead, oldAnchor);
2092
2093                    selModel.setValueIsAdjusting(false);
2094                }
2095            }
2096
2097            /**
2098             * Deselects all selected columns and rows.
2099             */
2100            public void clearSelection() {
2101                selectionModel.clearSelection();
2102                columnModel.getSelectionModel().clearSelection();
2103            }
2104
2105            private void clearSelectionAndLeadAnchor() {
2106                selectionModel.setValueIsAdjusting(true);
2107                columnModel.getSelectionModel().setValueIsAdjusting(true);
2108
2109                clearSelection();
2110
2111                selectionModel.setAnchorSelectionIndex(-1);
2112                selectionModel.setLeadSelectionIndex(-1);
2113                columnModel.getSelectionModel().setAnchorSelectionIndex(-1);
2114                columnModel.getSelectionModel().setLeadSelectionIndex(-1);
2115
2116                selectionModel.setValueIsAdjusting(false);
2117                columnModel.getSelectionModel().setValueIsAdjusting(false);
2118            }
2119
2120            private int getAdjustedIndex(int index, boolean row) {
2121                int compare = row ? getRowCount() : getColumnCount();
2122                return index < compare ? index : -1;
2123            }
2124
2125            private int boundRow(int row) throws IllegalArgumentException {
2126                if (row < 0 || row >= getRowCount()) {
2127                    throw new IllegalArgumentException("Row index out of range");
2128                }
2129                return row;
2130            }
2131
2132            private int boundColumn(int col) {
2133                if (col < 0 || col >= getColumnCount()) {
2134                    throw new IllegalArgumentException(
2135                            "Column index out of range");
2136                }
2137                return col;
2138            }
2139
2140            /**
2141             * Selects the rows from <code>index0</code> to <code>index1</code>,
2142             * inclusive.
2143             *
2144             * @exception IllegalArgumentException      if <code>index0</code> or
2145             *						<code>index1</code> lie outside
2146             *                                          [0, <code>getRowCount()</code>-1]
2147             * @param   index0 one end of the interval
2148             * @param   index1 the other end of the interval
2149             */
2150            public void setRowSelectionInterval(int index0, int index1) {
2151                selectionModel.setSelectionInterval(boundRow(index0),
2152                        boundRow(index1));
2153            }
2154
2155            /**
2156             * Selects the columns from <code>index0</code> to <code>index1</code>,
2157             * inclusive.
2158             *
2159             * @exception IllegalArgumentException      if <code>index0</code> or
2160             *						<code>index1</code> lie outside
2161             *                                          [0, <code>getColumnCount()</code>-1]
2162             * @param   index0 one end of the interval
2163             * @param   index1 the other end of the interval
2164             */
2165            public void setColumnSelectionInterval(int index0, int index1) {
2166                columnModel.getSelectionModel().setSelectionInterval(
2167                        boundColumn(index0), boundColumn(index1));
2168            }
2169
2170            /**
2171             * Adds the rows from <code>index0</code> to <code>index1</code>, inclusive, to
2172             * the current selection.
2173             *
2174             * @exception IllegalArgumentException      if <code>index0</code> or <code>index1</code>
2175             *                                          lie outside [0, <code>getRowCount()</code>-1]
2176             * @param   index0 one end of the interval
2177             * @param   index1 the other end of the interval
2178             */
2179            public void addRowSelectionInterval(int index0, int index1) {
2180                selectionModel.addSelectionInterval(boundRow(index0),
2181                        boundRow(index1));
2182            }
2183
2184            /**
2185             * Adds the columns from <code>index0</code> to <code>index1</code>,
2186             * inclusive, to the current selection.
2187             *
2188             * @exception IllegalArgumentException      if <code>index0</code> or
2189             *						<code>index1</code> lie outside
2190             *                                          [0, <code>getColumnCount()</code>-1]
2191             * @param   index0 one end of the interval
2192             * @param   index1 the other end of the interval
2193             */
2194            public void addColumnSelectionInterval(int index0, int index1) {
2195                columnModel.getSelectionModel().addSelectionInterval(
2196                        boundColumn(index0), boundColumn(index1));
2197            }
2198
2199            /**
2200             * Deselects the rows from <code>index0</code> to <code>index1</code>, inclusive.
2201             *
2202             * @exception IllegalArgumentException      if <code>index0</code> or
2203             *						<code>index1</code> lie outside
2204             *                                          [0, <code>getRowCount()</code>-1]
2205             * @param   index0 one end of the interval
2206             * @param   index1 the other end of the interval
2207             */
2208            public void removeRowSelectionInterval(int index0, int index1) {
2209                selectionModel.removeSelectionInterval(boundRow(index0),
2210                        boundRow(index1));
2211            }
2212
2213            /**
2214             * Deselects the columns from <code>index0</code> to <code>index1</code>, inclusive.
2215             *
2216             * @exception IllegalArgumentException      if <code>index0</code> or
2217             *						<code>index1</code> lie outside
2218             *                                          [0, <code>getColumnCount()</code>-1]
2219             * @param   index0 one end of the interval
2220             * @param   index1 the other end of the interval
2221             */
2222            public void removeColumnSelectionInterval(int index0, int index1) {
2223                columnModel.getSelectionModel().removeSelectionInterval(
2224                        boundColumn(index0), boundColumn(index1));
2225            }
2226
2227            /**
2228             * Returns the index of the first selected row, -1 if no row is selected.
2229             * @return the index of the first selected row
2230             */
2231            public int getSelectedRow() {
2232                return selectionModel.getMinSelectionIndex();
2233            }
2234
2235            /**
2236             * Returns the index of the first selected column,
2237             * -1 if no column is selected.
2238             * @return the index of the first selected column
2239             */
2240            public int getSelectedColumn() {
2241                return columnModel.getSelectionModel().getMinSelectionIndex();
2242            }
2243
2244            /**
2245             * Returns the indices of all selected rows.
2246             *
2247             * @return an array of integers containing the indices of all selected rows,
2248             *         or an empty array if no row is selected
2249             * @see #getSelectedRow
2250             */
2251            public int[] getSelectedRows() {
2252                int iMin = selectionModel.getMinSelectionIndex();
2253                int iMax = selectionModel.getMaxSelectionIndex();
2254
2255                if ((iMin == -1) || (iMax == -1)) {
2256                    return new int[0];
2257                }
2258
2259                int[] rvTmp = new int[1 + (iMax - iMin)];
2260                int n = 0;
2261                for (int i = iMin; i <= iMax; i++) {
2262                    if (selectionModel.isSelectedIndex(i)) {
2263                        rvTmp[n++] = i;
2264                    }
2265                }
2266                int[] rv = new int[n];
2267                System.arraycopy(rvTmp, 0, rv, 0, n);
2268                return rv;
2269            }
2270
2271            /**
2272             * Returns the indices of all selected columns.
2273             *
2274             * @return an array of integers containing the indices of all selected columns,
2275             *         or an empty array if no column is selected
2276             * @see #getSelectedColumn
2277             */
2278            public int[] getSelectedColumns() {
2279                return columnModel.getSelectedColumns();
2280            }
2281
2282            /**
2283             * Returns the number of selected rows.
2284             *
2285             * @return the number of selected rows, 0 if no rows are selected
2286             */
2287            public int getSelectedRowCount() {
2288                int iMin = selectionModel.getMinSelectionIndex();
2289                int iMax = selectionModel.getMaxSelectionIndex();
2290                int count = 0;
2291
2292                for (int i = iMin; i <= iMax; i++) {
2293                    if (selectionModel.isSelectedIndex(i)) {
2294                        count++;
2295                    }
2296                }
2297                return count;
2298            }
2299
2300            /**
2301             * Returns the number of selected columns.
2302             *
2303             * @return the number of selected columns, 0 if no columns are selected
2304             */
2305            public int getSelectedColumnCount() {
2306                return columnModel.getSelectedColumnCount();
2307            }
2308
2309            /**
2310             * Returns true if the specified index is in the valid range of rows,
2311             * and the row at that index is selected.
2312             *
2313             * @return true if <code>row</code> is a valid index and the row at
2314             *              that index is selected (where 0 is the first row)
2315             */
2316            public boolean isRowSelected(int row) {
2317                return selectionModel.isSelectedIndex(row);
2318            }
2319
2320            /**
2321             * Returns true if the specified index is in the valid range of columns,
2322             * and the column at that index is selected.
2323             *
2324             * @param   column   the column in the column model
2325             * @return true if <code>column</code> is a valid index and the column at
2326             *              that index is selected (where 0 is the first column)
2327             */
2328            public boolean isColumnSelected(int column) {
2329                return columnModel.getSelectionModel().isSelectedIndex(column);
2330            }
2331
2332            /**
2333             * Returns true if the specified indices are in the valid range of rows
2334             * and columns and the cell at the specified position is selected.
2335             * @param row   the row being queried
2336             * @param column  the column being queried
2337             *
2338             * @return true if <code>row</code> and <code>column</code> are valid indices
2339             *              and the cell at index <code>(row, column)</code> is selected,
2340             *              where the first row and first column are at index 0
2341             */
2342            public boolean isCellSelected(int row, int column) {
2343                if (!getRowSelectionAllowed() && !getColumnSelectionAllowed()) {
2344                    return false;
2345                }
2346                return (!getRowSelectionAllowed() || isRowSelected(row))
2347                        && (!getColumnSelectionAllowed() || isColumnSelected(column));
2348            }
2349
2350            private void changeSelectionModel(ListSelectionModel sm, int index,
2351                    boolean toggle, boolean extend, boolean selected,
2352                    int anchor, boolean anchorSelected) {
2353                if (extend) {
2354                    if (toggle) {
2355                        if (anchorSelected) {
2356                            sm.addSelectionInterval(anchor, index);
2357                        } else {
2358                            sm.removeSelectionInterval(anchor, index);
2359                            // this is a Windows-only behavior that we want for file lists
2360                            if (Boolean.TRUE == getClientProperty("Table.isFileList")) {
2361                                sm.addSelectionInterval(index, index);
2362                                sm.setAnchorSelectionIndex(anchor);
2363                            }
2364                        }
2365                    } else {
2366                        sm.setSelectionInterval(anchor, index);
2367                    }
2368                } else {
2369                    if (toggle) {
2370                        if (selected) {
2371                            sm.removeSelectionInterval(index, index);
2372                        } else {
2373                            sm.addSelectionInterval(index, index);
2374                        }
2375                    } else {
2376                        sm.setSelectionInterval(index, index);
2377                    }
2378                }
2379            }
2380
2381            /**
2382             * Updates the selection models of the table, depending on the state of the
2383             * two flags: <code>toggle</code> and <code>extend</code>. Most changes
2384             * to the selection that are the result of keyboard or mouse events received
2385             * by the UI are channeled through this method so that the behavior may be
2386             * overridden by a subclass. Some UIs may need more functionality than
2387             * this method provides, such as when manipulating the lead for discontiguous
2388             * selection, and may not call into this method for some selection changes.
2389             * <p>
2390             * This implementation uses the following conventions:
2391             * <ul>
2392             * <li> <code>toggle</code>: <em>false</em>, <code>extend</code>: <em>false</em>.
2393             *      Clear the previous selection and ensure the new cell is selected.
2394             * <li> <code>toggle</code>: <em>false</em>, <code>extend</code>: <em>true</em>.
2395             *      Extend the previous selection from the anchor to the specified cell,
2396             *      clearing all other selections.
2397             * <li> <code>toggle</code>: <em>true</em>, <code>extend</code>: <em>false</em>.
2398             *      If the specified cell is selected, deselect it. If it is not selected, select it.
2399             * <li> <code>toggle</code>: <em>true</em>, <code>extend</code>: <em>true</em>.
2400             *      Apply the selection state of the anchor to all cells between it and the
2401             *      specified cell.
2402             * </ul>
2403             * @param  rowIndex   affects the selection at <code>row</code>
2404             * @param  columnIndex  affects the selection at <code>column</code>
2405             * @param  toggle  see description above
2406             * @param  extend  if true, extend the current selection
2407             *
2408             * @since 1.3
2409             */
2410            public void changeSelection(int rowIndex, int columnIndex,
2411                    boolean toggle, boolean extend) {
2412                ListSelectionModel rsm = getSelectionModel();
2413                ListSelectionModel csm = getColumnModel().getSelectionModel();
2414
2415                int anchorRow = getAdjustedIndex(rsm.getAnchorSelectionIndex(),
2416                        true);
2417                int anchorCol = getAdjustedIndex(csm.getAnchorSelectionIndex(),
2418                        false);
2419
2420                boolean anchorSelected = true;
2421
2422                if (anchorRow == -1) {
2423                    if (getRowCount() > 0) {
2424                        anchorRow = 0;
2425                    }
2426                    anchorSelected = false;
2427                }
2428
2429                if (anchorCol == -1) {
2430                    if (getColumnCount() > 0) {
2431                        anchorCol = 0;
2432                    }
2433                    anchorSelected = false;
2434                }
2435
2436                // Check the selection here rather than in each selection model.
2437                // This is significant in cell selection mode if we are supposed
2438                // to be toggling the selection. In this case it is better to
2439                // ensure that the cell's selection state will indeed be changed.
2440                // If this were done in the code for the selection model it
2441                // might leave a cell in selection state if the row was
2442                // selected but the column was not - as it would toggle them both.
2443                boolean selected = isCellSelected(rowIndex, columnIndex);
2444                anchorSelected = anchorSelected
2445                        && isCellSelected(anchorRow, anchorCol);
2446
2447                changeSelectionModel(csm, columnIndex, toggle, extend,
2448                        selected, anchorCol, anchorSelected);
2449                changeSelectionModel(rsm, rowIndex, toggle, extend, selected,
2450                        anchorRow, anchorSelected);
2451
2452                // Scroll after changing the selection as blit scrolling is immediate,
2453                // so that if we cause the repaint after the scroll we end up painting
2454                // everything!
2455                if (getAutoscrolls()) {
2456                    Rectangle cellRect = getCellRect(rowIndex, columnIndex,
2457                            false);
2458                    if (cellRect != null) {
2459                        scrollRectToVisible(cellRect);
2460                    }
2461                }
2462            }
2463
2464            /**
2465             * Returns the foreground color for selected cells.
2466             *
2467             * @return the <code>Color</code> object for the foreground property
2468             * @see #setSelectionForeground
2469             * @see #setSelectionBackground
2470             */
2471            public Color getSelectionForeground() {
2472                return selectionForeground;
2473            }
2474
2475            /**
2476             * Sets the foreground color for selected cells.  Cell renderers
2477             * can use this color to render text and graphics for selected
2478             * cells.
2479             * <p>
2480             * The default value of this property is defined by the look
2481             * and feel implementation.
2482             * <p>
2483             * This is a <a href="http://java.sun.com/docs/books/tutorial/javabeans/whatis/beanDefinition.html">JavaBeans</a> bound property.
2484             *
2485             * @param selectionForeground  the <code>Color</code> to use in the foreground
2486             *                             for selected list items
2487             * @see #getSelectionForeground
2488             * @see #setSelectionBackground
2489             * @see #setForeground
2490             * @see #setBackground
2491             * @see #setFont
2492             * @beaninfo
2493             *       bound: true
2494             * description: A default foreground color for selected cells.
2495             */
2496            public void setSelectionForeground(Color selectionForeground) {
2497                Color old = this .selectionForeground;
2498                this .selectionForeground = selectionForeground;
2499                firePropertyChange("selectionForeground", old,
2500                        selectionForeground);
2501                if (!selectionForeground.equals(old)) {
2502                    repaint();
2503                }
2504            }
2505
2506            /**
2507             * Returns the background color for selected cells.
2508             *
2509             * @return the <code>Color</code> used for the background of selected list items
2510             * @see #setSelectionBackground
2511             * @see #setSelectionForeground
2512             */
2513            public Color getSelectionBackground() {
2514                return selectionBackground;
2515            }
2516
2517            /**
2518             * Sets the background color for selected cells.  Cell renderers
2519             * can use this color to the fill selected cells.
2520             * <p>
2521             * The default value of this property is defined by the look
2522             * and feel implementation.
2523             * <p>
2524             * This is a <a href="http://java.sun.com/docs/books/tutorial/javabeans/whatis/beanDefinition.html">JavaBeans</a> bound property.
2525             *
2526             * @param selectionBackground  the <code>Color</code> to use for the background
2527             *                             of selected cells
2528             * @see #getSelectionBackground
2529             * @see #setSelectionForeground
2530             * @see #setForeground
2531             * @see #setBackground
2532             * @see #setFont
2533             * @beaninfo
2534             *       bound: true
2535             * description: A default background color for selected cells.
2536             */
2537            public void setSelectionBackground(Color selectionBackground) {
2538                Color old = this .selectionBackground;
2539                this .selectionBackground = selectionBackground;
2540                firePropertyChange("selectionBackground", old,
2541                        selectionBackground);
2542                if (!selectionBackground.equals(old)) {
2543                    repaint();
2544                }
2545            }
2546
2547            /**
2548             * Returns the <code>TableColumn</code> object for the column in the table
2549             * whose identifier is equal to <code>identifier</code>, when compared using
2550             * <code>equals</code>.
2551             *
2552             * @return  the <code>TableColumn</code> object that matches the identifier
2553             * @exception IllegalArgumentException      if <code>identifier</code> is <code>null</code> or no <code>TableColumn</code> has this identifier
2554             *
2555             * @param   identifier                      the identifier object
2556             */
2557            public TableColumn getColumn(Object identifier) {
2558                TableColumnModel cm = getColumnModel();
2559                int columnIndex = cm.getColumnIndex(identifier);
2560                return cm.getColumn(columnIndex);
2561            }
2562
2563            //
2564            // Informally implement the TableModel interface.
2565            //
2566
2567            /**
2568             * Maps the index of the column in the view at
2569             * <code>viewColumnIndex</code> to the index of the column
2570             * in the table model.  Returns the index of the corresponding
2571             * column in the model.  If <code>viewColumnIndex</code>
2572             * is less than zero, returns <code>viewColumnIndex</code>.
2573             *
2574             * @param   viewColumnIndex     the index of the column in the view
2575             * @return  the index of the corresponding column in the model
2576             *
2577             * @see #convertColumnIndexToView
2578             */
2579            public int convertColumnIndexToModel(int viewColumnIndex) {
2580                if (viewColumnIndex < 0) {
2581                    return viewColumnIndex;
2582                }
2583                return getColumnModel().getColumn(viewColumnIndex)
2584                        .getModelIndex();
2585            }
2586
2587            /**
2588             * Maps the index of the column in the table model at
2589             * <code>modelColumnIndex</code> to the index of the column
2590             * in the view.  Returns the index of the
2591             * corresponding column in the view; returns -1 if this column is not
2592             * being displayed.  If <code>modelColumnIndex</code> is less than zero,
2593             * returns <code>modelColumnIndex</code>.
2594             *
2595             * @param   modelColumnIndex     the index of the column in the model
2596             * @return   the index of the corresponding column in the view
2597             *
2598             * @see #convertColumnIndexToModel
2599             */
2600            public int convertColumnIndexToView(int modelColumnIndex) {
2601                if (modelColumnIndex < 0) {
2602                    return modelColumnIndex;
2603                }
2604                TableColumnModel cm = getColumnModel();
2605                for (int column = 0; column < getColumnCount(); column++) {
2606                    if (cm.getColumn(column).getModelIndex() == modelColumnIndex) {
2607                        return column;
2608                    }
2609                }
2610                return -1;
2611            }
2612
2613            /**
2614             * Maps the index of the row in terms of the
2615             * <code>TableModel</code> to the view.  If the contents of the
2616             * model are not sorted the model and view indices are the same.
2617             *
2618             * @param modelRowIndex the index of the row in terms of the model
2619             * @return the index of the corresponding row in the view, or -1 if
2620             *         the row isn't visible
2621             * @throws IndexOutOfBoundsException if sorting is enabled and passed an
2622             *         index outside the number of rows of the <code>TableModel</code>
2623             * @see javax.swing.table.TableRowSorter
2624             * @since 1.6
2625             */
2626            public int convertRowIndexToView(int modelRowIndex) {
2627                RowSorter sorter = getRowSorter();
2628                if (sorter != null) {
2629                    return sorter.convertRowIndexToView(modelRowIndex);
2630                }
2631                return modelRowIndex;
2632            }
2633
2634            /**
2635             * Maps the index of the row in terms of the view to the
2636             * underlying <code>TableModel</code>.  If the contents of the
2637             * model are not sorted the model and view indices are the same.
2638             *
2639             * @param viewRowIndex the index of the row in the view
2640             * @return the index of the corresponding row in the model
2641             * @throws IndexOutOfBoundsException if sorting is enabled and passed an
2642             *         index outside the range of the <code>JTable</code> as
2643             *         determined by the method <code>getRowCount</code> 
2644             * @see javax.swing.table.TableRowSorter
2645             * @see #getRowCount
2646             * @since 1.6
2647             */
2648            public int convertRowIndexToModel(int viewRowIndex) {
2649                RowSorter sorter = getRowSorter();
2650                if (sorter != null) {
2651                    return sorter.convertRowIndexToModel(viewRowIndex);
2652                }
2653                return viewRowIndex;
2654            }
2655
2656            /**
2657             * Returns the number of rows that can be shown in the
2658             * <code>JTable</code>, given unlimited space.  If a
2659             * <code>RowSorter</code> with a filter has been specified, the
2660             * number of rows returned may differ from that of the underlying
2661             * <code>TableModel</code>.
2662             *
2663             * @return the number of rows shown in the <code>JTable</code>
2664             * @see #getColumnCount
2665             */
2666            public int getRowCount() {
2667                RowSorter sorter = getRowSorter();
2668                if (sorter != null) {
2669                    return sorter.getViewRowCount();
2670                }
2671                return getModel().getRowCount();
2672            }
2673
2674            /**
2675             * Returns the number of columns in the column model. Note that this may
2676             * be different from the number of columns in the table model.
2677             *
2678             * @return  the number of columns in the table
2679             * @see #getRowCount
2680             * @see #removeColumn
2681             */
2682            public int getColumnCount() {
2683                return getColumnModel().getColumnCount();
2684            }
2685
2686            /**
2687             * Returns the name of the column appearing in the view at
2688             * column position <code>column</code>.
2689             *
2690             * @param  column    the column in the view being queried
2691             * @return the name of the column at position <code>column</code>
2692            		in the view where the first column is column 0
2693             */
2694            public String getColumnName(int column) {
2695                return getModel().getColumnName(
2696                        convertColumnIndexToModel(column));
2697            }
2698
2699            /**
2700             * Returns the type of the column appearing in the view at
2701             * column position <code>column</code>.
2702             *
2703             * @param   column   the column in the view being queried
2704             * @return the type of the column at position <code>column</code>
2705             * 		in the view where the first column is column 0
2706             */
2707            public Class<?> getColumnClass(int column) {
2708                return getModel().getColumnClass(
2709                        convertColumnIndexToModel(column));
2710            }
2711
2712            /**
2713             * Returns the cell value at <code>row</code> and <code>column</code>.
2714             * <p>
2715             * <b>Note</b>: The column is specified in the table view's display
2716             *              order, and not in the <code>TableModel</code>'s column
2717             *		    order.  This is an important distinction because as the
2718             *		    user rearranges the columns in the table,
2719             *		    the column at a given index in the view will change.
2720             *              Meanwhile the user's actions never affect the model's
2721             *              column ordering.
2722             *
2723             * @param   row             the row whose value is to be queried
2724             * @param   column          the column whose value is to be queried
2725             * @return  the Object at the specified cell
2726             */
2727            public Object getValueAt(int row, int column) {
2728                return getModel().getValueAt(convertRowIndexToModel(row),
2729                        convertColumnIndexToModel(column));
2730            }
2731
2732            /**
2733             * Sets the value for the cell in the table model at <code>row</code>
2734             * and <code>column</code>.
2735             * <p>
2736             * <b>Note</b>: The column is specified in the table view's display
2737             *              order, and not in the <code>TableModel</code>'s column
2738             *		    order.  This is an important distinction because as the
2739             *		    user rearranges the columns in the table,
2740             *		    the column at a given index in the view will change.
2741             *              Meanwhile the user's actions never affect the model's
2742             *              column ordering.
2743             *
2744             * <code>aValue</code> is the new value.
2745             *
2746             * @param   aValue          the new value
2747             * @param   row             the row of the cell to be changed
2748             * @param   column          the column of the cell to be changed
2749             * @see #getValueAt
2750             */
2751            public void setValueAt(Object aValue, int row, int column) {
2752                getModel().setValueAt(aValue, convertRowIndexToModel(row),
2753                        convertColumnIndexToModel(column));
2754            }
2755
2756            /**
2757             * Returns true if the cell at <code>row</code> and <code>column</code>
2758             * is editable.  Otherwise, invoking <code>setValueAt</code> on the cell
2759             * will have no effect.
2760             * <p>
2761             * <b>Note</b>: The column is specified in the table view's display
2762             *              order, and not in the <code>TableModel</code>'s column
2763             *		    order.  This is an important distinction because as the
2764             *		    user rearranges the columns in the table,
2765             *		    the column at a given index in the view will change.
2766             *              Meanwhile the user's actions never affect the model's
2767             *              column ordering.
2768             *
2769             *
2770             * @param   row      the row whose value is to be queried
2771             * @param   column   the column whose value is to be queried
2772             * @return  true if the cell is editable
2773             * @see #setValueAt
2774             */
2775            public boolean isCellEditable(int row, int column) {
2776                return getModel().isCellEditable(convertRowIndexToModel(row),
2777                        convertColumnIndexToModel(column));
2778            }
2779
2780            //
2781            // Adding and removing columns in the view
2782            //
2783
2784            /**
2785             *  Appends <code>aColumn</code> to the end of the array of columns held by
2786             *  this <code>JTable</code>'s column model.
2787             *  If the column name of <code>aColumn</code> is <code>null</code>,
2788             *  sets the column name of <code>aColumn</code> to the name
2789             *  returned by <code>getModel().getColumnName()</code>.
2790             *  <p>
2791             *  To add a column to this <code>JTable</code> to display the
2792             *  <code>modelColumn</code>'th column of data in the model with a
2793             *  given <code>width</code>, <code>cellRenderer</code>,
2794             *  and <code>cellEditor</code> you can use:
2795             *  <pre>
2796             *
2797             *      addColumn(new TableColumn(modelColumn, width, cellRenderer, cellEditor));
2798             *
2799             *  </pre>
2800             *  [Any of the <code>TableColumn</code> constructors can be used
2801             *  instead of this one.]
2802             *  The model column number is stored inside the <code>TableColumn</code>
2803             *  and is used during rendering and editing to locate the appropriates
2804             *  data values in the model. The model column number does not change
2805             *  when columns are reordered in the view.
2806             *
2807             *  @param  aColumn         the <code>TableColumn</code> to be added
2808             *  @see    #removeColumn
2809             */
2810            public void addColumn(TableColumn aColumn) {
2811                if (aColumn.getHeaderValue() == null) {
2812                    int modelColumn = aColumn.getModelIndex();
2813                    String columnName = getModel().getColumnName(modelColumn);
2814                    aColumn.setHeaderValue(columnName);
2815                }
2816                getColumnModel().addColumn(aColumn);
2817            }
2818
2819            /**
2820             *  Removes <code>aColumn</code> from this <code>JTable</code>'s
2821             *  array of columns.  Note: this method does not remove the column
2822             *  of data from the model; it just removes the <code>TableColumn</code>
2823             *  that was responsible for displaying it.
2824             *
2825             *  @param  aColumn         the <code>TableColumn</code> to be removed
2826             *  @see    #addColumn
2827             */
2828            public void removeColumn(TableColumn aColumn) {
2829                getColumnModel().removeColumn(aColumn);
2830            }
2831
2832            /**
2833             * Moves the column <code>column</code> to the position currently
2834             * occupied by the column <code>targetColumn</code> in the view.
2835             * The old column at <code>targetColumn</code> is
2836             * shifted left or right to make room.
2837             *
2838             * @param   column                  the index of column to be moved
2839             * @param   targetColumn            the new index of the column
2840             */
2841            public void moveColumn(int column, int targetColumn) {
2842                getColumnModel().moveColumn(column, targetColumn);
2843            }
2844
2845            //
2846            // Cover methods for various models and helper methods
2847            //
2848
2849            /**
2850             * Returns the index of the column that <code>point</code> lies in,
2851             * or -1 if the result is not in the range
2852             * [0, <code>getColumnCount()</code>-1].
2853             *
2854             * @param   point   the location of interest
2855             * @return  the index of the column that <code>point</code> lies in,
2856             *		or -1 if the result is not in the range
2857             *		[0, <code>getColumnCount()</code>-1]
2858             * @see     #rowAtPoint
2859             */
2860            public int columnAtPoint(Point point) {
2861                int x = point.x;
2862                if (!getComponentOrientation().isLeftToRight()) {
2863                    x = getWidth() - x - 1;
2864                }
2865                return getColumnModel().getColumnIndexAtX(x);
2866            }
2867
2868            /**
2869             * Returns the index of the row that <code>point</code> lies in,
2870             * or -1 if the result is not in the range
2871             * [0, <code>getRowCount()</code>-1].
2872             *
2873             * @param   point   the location of interest
2874             * @return  the index of the row that <code>point</code> lies in,
2875             *          or -1 if the result is not in the range
2876             *          [0, <code>getRowCount()</code>-1]
2877             * @see     #columnAtPoint
2878             */
2879            public int rowAtPoint(Point point) {
2880                int y = point.y;
2881                int result = (rowModel == null) ? y / getRowHeight() : rowModel
2882                        .getIndex(y);
2883                if (result < 0) {
2884                    return -1;
2885                } else if (result >= getRowCount()) {
2886                    return -1;
2887                } else {
2888                    return result;
2889                }
2890            }
2891
2892            /**
2893             * Returns a rectangle for the cell that lies at the intersection of
2894             * <code>row</code> and <code>column</code>.
2895             * If <code>includeSpacing</code> is true then the value returned
2896             * has the full height and width of the row and column
2897             * specified. If it is false, the returned rectangle is inset by the
2898             * intercell spacing to return the true bounds of the rendering or
2899             * editing component as it will be set during rendering.
2900             * <p>
2901             * If the column index is valid but the row index is less
2902             * than zero the method returns a rectangle with the
2903             * <code>y</code> and <code>height</code> values set appropriately
2904             * and the <code>x</code> and <code>width</code> values both set
2905             * to zero. In general, when either the row or column indices indicate a
2906             * cell outside the appropriate range, the method returns a rectangle
2907             * depicting the closest edge of the closest cell that is within
2908             * the table's range. When both row and column indices are out
2909             * of range the returned rectangle covers the closest
2910             * point of the closest cell.
2911             * <p>
2912             * In all cases, calculations that use this method to calculate
2913             * results along one axis will not fail because of anomalies in
2914             * calculations along the other axis. When the cell is not valid
2915             * the <code>includeSpacing</code> parameter is ignored.
2916             *
2917             * @param   row                   the row index where the desired cell
2918             *                                is located
2919             * @param   column                the column index where the desired cell
2920             *                                is located in the display; this is not
2921             *                                necessarily the same as the column index
2922             *                                in the data model for the table; the
2923             *                                {@link #convertColumnIndexToView(int)}
2924             *                                method may be used to convert a data
2925             *                                model column index to a display
2926             *                                column index
2927             * @param   includeSpacing        if false, return the true cell bounds -
2928             *                                computed by subtracting the intercell
2929             *				      spacing from the height and widths of
2930             *				      the column and row models
2931             *
2932             * @return  the rectangle containing the cell at location
2933             *          <code>row</code>,<code>column</code>
2934             * @see #getIntercellSpacing
2935             */
2936            public Rectangle getCellRect(int row, int column,
2937                    boolean includeSpacing) {
2938                Rectangle r = new Rectangle();
2939                boolean valid = true;
2940                if (row < 0) {
2941                    // y = height = 0;
2942                    valid = false;
2943                } else if (row >= getRowCount()) {
2944                    r.y = getHeight();
2945                    valid = false;
2946                } else {
2947                    r.height = getRowHeight(row);
2948                    r.y = (rowModel == null) ? row * r.height : rowModel
2949                            .getPosition(row);
2950                }
2951
2952                if (column < 0) {
2953                    if (!getComponentOrientation().isLeftToRight()) {
2954                        r.x = getWidth();
2955                    }
2956                    // otherwise, x = width = 0;
2957                    valid = false;
2958                } else if (column >= getColumnCount()) {
2959                    if (getComponentOrientation().isLeftToRight()) {
2960                        r.x = getWidth();
2961                    }
2962                    // otherwise, x = width = 0;
2963                    valid = false;
2964                } else {
2965                    TableColumnModel cm = getColumnModel();
2966                    if (getComponentOrientation().isLeftToRight()) {
2967                        for (int i = 0; i < column; i++) {
2968                            r.x += cm.getColumn(i).getWidth();
2969                        }
2970                    } else {
2971                        for (int i = cm.getColumnCount() - 1; i > column; i--) {
2972                            r.x += cm.getColumn(i).getWidth();
2973                        }
2974                    }
2975                    r.width = cm.getColumn(column).getWidth();
2976                }
2977
2978                if (valid && !includeSpacing) {
2979                    // Bound the margins by their associated dimensions to prevent
2980                    // returning bounds with negative dimensions.
2981                    int rm = Math.min(getRowMargin(), r.height);
2982                    int cm = Math.min(getColumnModel().getColumnMargin(),
2983                            r.width);
2984                    // This is not the same as grow(), it rounds differently.
2985                    r.setBounds(r.x + cm / 2, r.y + rm / 2, r.width - cm,
2986                            r.height - rm);
2987                }
2988                return r;
2989            }
2990
2991            private int viewIndexForColumn(TableColumn aColumn) {
2992                TableColumnModel cm = getColumnModel();
2993                for (int column = 0; column < cm.getColumnCount(); column++) {
2994                    if (cm.getColumn(column) == aColumn) {
2995                        return column;
2996                    }
2997                }
2998                return -1;
2999            }
3000
3001            /**
3002             * Causes this table to lay out its rows and columns.  Overridden so
3003             * that columns can be resized to accomodate a change in the size of
3004             * a containing parent.
3005             * Resizes one or more of the columns in the table
3006             * so that the total width of all of this <code>JTable</code>'s
3007             * columns is equal to the width of the table.
3008             * <p>
3009             * Before the layout begins the method gets the
3010             * <code>resizingColumn</code> of the <code>tableHeader</code>.
3011             * When the method is called as a result of the resizing of an enclosing window,
3012             * the <code>resizingColumn</code> is <code>null</code>. This means that resizing
3013             * has taken place "outside" the <code>JTable</code> and the change -
3014             * or "delta" - should be distributed to all of the columns regardless
3015             * of this <code>JTable</code>'s automatic resize mode.
3016             * <p>
3017             * If the <code>resizingColumn</code> is not <code>null</code>, it is one of
3018             * the columns in the table that has changed size rather than
3019             * the table itself. In this case the auto-resize modes govern
3020             * the way the extra (or deficit) space is distributed
3021             * amongst the available columns.
3022             * <p>
3023             * The modes are:
3024             * <ul>
3025             * <li>  AUTO_RESIZE_OFF: Don't automatically adjust the column's
3026             * widths at all. Use a horizontal scrollbar to accomodate the
3027             * columns when their sum exceeds the width of the
3028             * <code>Viewport</code>.  If the <code>JTable</code> is not
3029             * enclosed in a <code>JScrollPane</code> this may
3030             * leave parts of the table invisible.
3031             * <li>  AUTO_RESIZE_NEXT_COLUMN: Use just the column after the
3032             * resizing column. This results in the "boundary" or divider
3033             * between adjacent cells being independently adjustable.
3034             * <li>  AUTO_RESIZE_SUBSEQUENT_COLUMNS: Use all columns after the
3035             * one being adjusted to absorb the changes.  This is the
3036             * default behavior.
3037             * <li>  AUTO_RESIZE_LAST_COLUMN: Automatically adjust the
3038             * size of the last column only. If the bounds of the last column
3039             * prevent the desired size from being allocated, set the
3040             * width of the last column to the appropriate limit and make
3041             * no further adjustments.
3042             * <li>  AUTO_RESIZE_ALL_COLUMNS: Spread the delta amongst all the columns
3043             * in the <code>JTable</code>, including the one that is being
3044             * adjusted.
3045             * </ul>
3046             * <p>
3047             * <bold>Note:</bold> When a <code>JTable</code> makes adjustments
3048             *   to the widths of the columns it respects their minimum and
3049             *   maximum values absolutely.  It is therefore possible that,
3050             *   even after this method is called, the total width of the columns
3051             *   is still not equal to the width of the table. When this happens
3052             *   the <code>JTable</code> does not put itself
3053             *   in AUTO_RESIZE_OFF mode to bring up a scroll bar, or break other
3054             *   commitments of its current auto-resize mode -- instead it
3055             *   allows its bounds to be set larger (or smaller) than the total of the
3056             *   column minimum or maximum, meaning, either that there
3057             *   will not be enough room to display all of the columns, or that the
3058             *   columns will not fill the <code>JTable</code>'s bounds.
3059             *   These respectively, result in the clipping of some columns
3060             *   or an area being painted in the <code>JTable</code>'s
3061             *   background color during painting.
3062             * <p>
3063             *   The mechanism for distributing the delta amongst the available
3064             *   columns is provided in a private method in the <code>JTable</code>
3065             *   class:
3066             * <pre>
3067             *   adjustSizes(long targetSize, final Resizable3 r, boolean inverse)
3068             * </pre>
3069             *   an explanation of which is provided in the following section.
3070             *   <code>Resizable3</code> is a private
3071             *   interface that allows any data structure containing a collection
3072             *   of elements with a size, preferred size, maximum size and minimum size
3073             *   to have its elements manipulated by the algorithm.
3074             * <p>
3075             * <H3> Distributing the delta </H3>
3076             * <p>
3077             * <H4> Overview </H4>
3078             * <P>
3079             * Call "DELTA" the difference between the target size and the
3080             * sum of the preferred sizes of the elements in r. The individual
3081             * sizes are calculated by taking the original preferred
3082             * sizes and adding a share of the DELTA - that share being based on
3083             * how far each preferred size is from its limiting bound (minimum or
3084             * maximum).
3085             * <p>
3086             * <H4>Definition</H4>
3087             * <P>
3088             * Call the individual constraints min[i], max[i], and pref[i].
3089             * <p>
3090             * Call their respective sums: MIN, MAX, and PREF.
3091             * <p>
3092             * Each new size will be calculated using:
3093             * <p>
3094             * <pre>
3095             *          size[i] = pref[i] + delta[i]
3096             * </pre>
3097             * where each individual delta[i] is calculated according to:
3098             * <p>
3099             * If (DELTA < 0) we are in shrink mode where:
3100             * <p>
3101             * <PRE>
3102             *                        DELTA
3103             *          delta[i] = ------------ * (pref[i] - min[i])
3104             *                     (PREF - MIN)
3105             * </PRE>
3106             * If (DELTA > 0) we are in expand mode where:
3107             * <p>
3108             * <PRE>
3109             *                        DELTA
3110             *          delta[i] = ------------ * (max[i] - pref[i])
3111             *                      (MAX - PREF)
3112             * </PRE>
3113             * <P>
3114             * The overall effect is that the total size moves that same percentage,
3115             * k, towards the total minimum or maximum and that percentage guarantees
3116             * accomodation of the required space, DELTA.
3117             *
3118             * <H4>Details</H4>
3119             * <P>
3120             * Naive evaluation of the formulae presented here would be subject to
3121             * the aggregated rounding errors caused by doing this operation in finite
3122             * precision (using ints). To deal with this, the multiplying factor above,
3123             * is constantly recalculated and this takes account of the rounding
3124             * errors in the previous iterations. The result is an algorithm that
3125             * produces a set of integers whose values exactly sum to the supplied
3126             * <code>targetSize</code>, and does so by spreading the rounding
3127             * errors evenly over the given elements.
3128             *
3129             * <H4>When the MAX and MIN bounds are hit</H4>
3130             * <P>
3131             * When <code>targetSize</code> is outside the [MIN, MAX] range,
3132             * the algorithm sets all sizes to their appropriate limiting value
3133             * (maximum or minimum).
3134             *
3135             */
3136            public void doLayout() {
3137                TableColumn resizingColumn = getResizingColumn();
3138                if (resizingColumn == null) {
3139                    setWidthsFromPreferredWidths(false);
3140                } else {
3141                    // JTable behaves like a layout manger - but one in which the
3142                    // user can come along and dictate how big one of the children
3143                    // (columns) is supposed to be.
3144
3145                    // A column has been resized and JTable may need to distribute
3146                    // any overall delta to other columns, according to the resize mode.
3147                    int columnIndex = viewIndexForColumn(resizingColumn);
3148                    int delta = getWidth()
3149                            - getColumnModel().getTotalColumnWidth();
3150                    accommodateDelta(columnIndex, delta);
3151                    delta = getWidth() - getColumnModel().getTotalColumnWidth();
3152
3153                    // If the delta cannot be completely accomodated, then the
3154                    // resizing column will have to take any remainder. This means
3155                    // that the column is not being allowed to take the requested
3156                    // width. This happens under many circumstances: For example,
3157                    // AUTO_RESIZE_NEXT_COLUMN specifies that any delta be distributed
3158                    // to the column after the resizing column. If one were to attempt
3159                    // to resize the last column of the table, there would be no
3160                    // columns after it, and hence nowhere to distribute the delta.
3161                    // It would then be given entirely back to the resizing column,
3162                    // preventing it from changing size.
3163                    if (delta != 0) {
3164                        resizingColumn.setWidth(resizingColumn.getWidth()
3165                                + delta);
3166                    }
3167
3168                    // At this point the JTable has to work out what preferred sizes
3169                    // would have resulted in the layout the user has chosen.
3170                    // Thereafter, during window resizing etc. it has to work off
3171                    // the preferred sizes as usual - the idea being that, whatever
3172                    // the user does, everything stays in synch and things don't jump
3173                    // around.
3174                    setWidthsFromPreferredWidths(true);
3175                }
3176
3177                super .doLayout();
3178            }
3179
3180            private TableColumn getResizingColumn() {
3181                return (tableHeader == null) ? null : tableHeader
3182                        .getResizingColumn();
3183            }
3184
3185            /**
3186             * Sizes the table columns to fit the available space.
3187             * @deprecated As of Swing version 1.0.3,
3188             * replaced by <code>doLayout()</code>.
3189             * @see #doLayout
3190             */
3191            @Deprecated
3192            public void sizeColumnsToFit(boolean lastColumnOnly) {
3193                int oldAutoResizeMode = autoResizeMode;
3194                setAutoResizeMode(lastColumnOnly ? AUTO_RESIZE_LAST_COLUMN
3195                        : AUTO_RESIZE_ALL_COLUMNS);
3196                sizeColumnsToFit(-1);
3197                setAutoResizeMode(oldAutoResizeMode);
3198            }
3199
3200            /**
3201             * Obsolete as of Java 2 platform v1.4.  Please use the
3202             * <code>doLayout()</code> method instead.
3203             * @param resizingColumn    the column whose resizing made this adjustment
3204             *                          necessary or -1 if there is no such column
3205             * @see  #doLayout
3206             */
3207            public void sizeColumnsToFit(int resizingColumn) {
3208                if (resizingColumn == -1) {
3209                    setWidthsFromPreferredWidths(false);
3210                } else {
3211                    if (autoResizeMode == AUTO_RESIZE_OFF) {
3212                        TableColumn aColumn = getColumnModel().getColumn(
3213                                resizingColumn);
3214                        aColumn.setPreferredWidth(aColumn.getWidth());
3215                    } else {
3216                        int delta = getWidth()
3217                                - getColumnModel().getTotalColumnWidth();
3218                        accommodateDelta(resizingColumn, delta);
3219                        setWidthsFromPreferredWidths(true);
3220                    }
3221                }
3222            }
3223
3224            private void setWidthsFromPreferredWidths(final boolean inverse) {
3225                int totalWidth = getWidth();
3226                int totalPreferred = getPreferredSize().width;
3227                int target = !inverse ? totalWidth : totalPreferred;
3228
3229                final TableColumnModel cm = columnModel;
3230                Resizable3 r = new Resizable3() {
3231                    public int getElementCount() {
3232                        return cm.getColumnCount();
3233                    }
3234
3235                    public int getLowerBoundAt(int i) {
3236                        return cm.getColumn(i).getMinWidth();
3237                    }
3238
3239                    public int getUpperBoundAt(int i) {
3240                        return cm.getColumn(i).getMaxWidth();
3241                    }
3242
3243                    public int getMidPointAt(int i) {
3244                        if (!inverse) {
3245                            return cm.getColumn(i).getPreferredWidth();
3246                        } else {
3247                            return cm.getColumn(i).getWidth();
3248                        }
3249                    }
3250
3251                    public void setSizeAt(int s, int i) {
3252                        if (!inverse) {
3253                            cm.getColumn(i).setWidth(s);
3254                        } else {
3255                            cm.getColumn(i).setPreferredWidth(s);
3256                        }
3257                    }
3258                };
3259
3260                adjustSizes(target, r, inverse);
3261            }
3262
3263            // Distribute delta over columns, as indicated by the autoresize mode.
3264            private void accommodateDelta(int resizingColumnIndex, int delta) {
3265                int columnCount = getColumnCount();
3266                int from = resizingColumnIndex;
3267                int to = columnCount;
3268
3269                // Use the mode to determine how to absorb the changes.
3270                switch (autoResizeMode) {
3271                case AUTO_RESIZE_NEXT_COLUMN:
3272                    from = from + 1;
3273                    to = Math.min(from + 1, columnCount);
3274                    break;
3275                case AUTO_RESIZE_SUBSEQUENT_COLUMNS:
3276                    from = from + 1;
3277                    to = columnCount;
3278                    break;
3279                case AUTO_RESIZE_LAST_COLUMN:
3280                    from = columnCount - 1;
3281                    to = from + 1;
3282                    break;
3283                case AUTO_RESIZE_ALL_COLUMNS:
3284                    from = 0;
3285                    to = columnCount;
3286                    break;
3287                default:
3288                    return;
3289                }
3290
3291                final int start = from;
3292                final int end = to;
3293                final TableColumnModel cm = columnModel;
3294                Resizable3 r = new Resizable3() {
3295                    public int getElementCount() {
3296                        return end - start;
3297                    }
3298
3299                    public int getLowerBoundAt(int i) {
3300                        return cm.getColumn(i + start).getMinWidth();
3301                    }
3302
3303                    public int getUpperBoundAt(int i) {
3304                        return cm.getColumn(i + start).getMaxWidth();
3305                    }
3306
3307                    public int getMidPointAt(int i) {
3308                        return cm.getColumn(i + start).getWidth();
3309                    }
3310
3311                    public void setSizeAt(int s, int i) {
3312                        cm.getColumn(i + start).setWidth(s);
3313                    }
3314                };
3315
3316                int totalWidth = 0;
3317                for (int i = from; i < to; i++) {
3318                    TableColumn aColumn = columnModel.getColumn(i);
3319                    int input = aColumn.getWidth();
3320                    totalWidth = totalWidth + input;
3321                }
3322
3323                adjustSizes(totalWidth + delta, r, false);
3324
3325                return;
3326            }
3327
3328            private interface Resizable2 {
3329                public int getElementCount();
3330
3331                public int getLowerBoundAt(int i);
3332
3333                public int getUpperBoundAt(int i);
3334
3335                public void setSizeAt(int newSize, int i);
3336            }
3337
3338            private interface Resizable3 extends Resizable2 {
3339                public int getMidPointAt(int i);
3340            }
3341
3342            private void adjustSizes(long target, final Resizable3 r,
3343                    boolean inverse) {
3344                int N = r.getElementCount();
3345                long totalPreferred = 0;
3346                for (int i = 0; i < N; i++) {
3347                    totalPreferred += r.getMidPointAt(i);
3348                }
3349                Resizable2 s;
3350                if ((target < totalPreferred) == !inverse) {
3351                    s = new Resizable2() {
3352                        public int getElementCount() {
3353                            return r.getElementCount();
3354                        }
3355
3356                        public int getLowerBoundAt(int i) {
3357                            return r.getLowerBoundAt(i);
3358                        }
3359
3360                        public int getUpperBoundAt(int i) {
3361                            return r.getMidPointAt(i);
3362                        }
3363
3364                        public void setSizeAt(int newSize, int i) {
3365                            r.setSizeAt(newSize, i);
3366                        }
3367
3368                    };
3369                } else {
3370                    s = new Resizable2() {
3371                        public int getElementCount() {
3372                            return r.getElementCount();
3373                        }
3374
3375                        public int getLowerBoundAt(int i) {
3376                            return r.getMidPointAt(i);
3377                        }
3378
3379                        public int getUpperBoundAt(int i) {
3380                            return r.getUpperBoundAt(i);
3381                        }
3382
3383                        public void setSizeAt(int newSize, int i) {
3384                            r.setSizeAt(newSize, i);
3385                        }
3386
3387                    };
3388                }
3389                adjustSizes(target, s, !inverse);
3390            }
3391
3392            private void adjustSizes(long target, Resizable2 r,
3393                    boolean limitToRange) {
3394                long totalLowerBound = 0;
3395                long totalUpperBound = 0;
3396                for (int i = 0; i < r.getElementCount(); i++) {
3397                    totalLowerBound += r.getLowerBoundAt(i);
3398                    totalUpperBound += r.getUpperBoundAt(i);
3399                }
3400
3401                if (limitToRange) {
3402                    target = Math.min(Math.max(totalLowerBound, target),
3403                            totalUpperBound);
3404                }
3405
3406                for (int i = 0; i < r.getElementCount(); i++) {
3407                    int lowerBound = r.getLowerBoundAt(i);
3408                    int upperBound = r.getUpperBoundAt(i);
3409                    // Check for zero. This happens when the distribution of the delta
3410                    // finishes early due to a series of "fixed" entries at the end.
3411                    // In this case, lowerBound == upperBound, for all subsequent terms.
3412                    int newSize;
3413                    if (totalLowerBound == totalUpperBound) {
3414                        newSize = lowerBound;
3415                    } else {
3416                        double f = (double) (target - totalLowerBound)
3417                                / (totalUpperBound - totalLowerBound);
3418                        newSize = (int) Math.round(lowerBound + f
3419                                * (upperBound - lowerBound));
3420                        // We'd need to round manually in an all integer version.
3421                        // size[i] = (int)(((totalUpperBound - target) * lowerBound +
3422                        //     (target - totalLowerBound) * upperBound)/(totalUpperBound-totalLowerBound));
3423                    }
3424                    r.setSizeAt(newSize, i);
3425                    target -= newSize;
3426                    totalLowerBound -= lowerBound;
3427                    totalUpperBound -= upperBound;
3428                }
3429            }
3430
3431            /**
3432             * Overrides <code>JComponent</code>'s <code>getToolTipText</code>
3433             * method in order to allow the renderer's tips to be used
3434             * if it has text set.
3435             * <p>
3436             * <bold>Note:</bold> For <code>JTable</code> to properly display
3437             * tooltips of its renderers
3438             * <code>JTable</code> must be a registered component with the
3439             * <code>ToolTipManager</code>.
3440             * This is done automatically in <code>initializeLocalVars</code>,
3441             * but if at a later point <code>JTable</code> is told
3442             * <code>setToolTipText(null)</code> it will unregister the table
3443             * component, and no tips from renderers will display anymore.
3444             *
3445             * @see JComponent#getToolTipText
3446             */
3447            public String getToolTipText(MouseEvent event) {
3448                String tip = null;
3449                Point p = event.getPoint();
3450
3451                // Locate the renderer under the event location
3452                int hitColumnIndex = columnAtPoint(p);
3453                int hitRowIndex = rowAtPoint(p);
3454
3455                if ((hitColumnIndex != -1) && (hitRowIndex != -1)) {
3456                    TableCellRenderer renderer = getCellRenderer(hitRowIndex,
3457                            hitColumnIndex);
3458                    Component component = prepareRenderer(renderer,
3459                            hitRowIndex, hitColumnIndex);
3460
3461                    // Now have to see if the component is a JComponent before
3462                    // getting the tip
3463                    if (component instanceof  JComponent) {
3464                        // Convert the event to the renderer's coordinate system
3465                        Rectangle cellRect = getCellRect(hitRowIndex,
3466                                hitColumnIndex, false);
3467                        p.translate(-cellRect.x, -cellRect.y);
3468                        MouseEvent newEvent = new MouseEvent(component, event
3469                                .getID(), event.getWhen(),
3470                                event.getModifiers(), p.x, p.y, event
3471                                        .getXOnScreen(), event.getYOnScreen(),
3472                                event.getClickCount(), event.isPopupTrigger(),
3473                                MouseEvent.NOBUTTON);
3474
3475                        tip = ((JComponent) component).getToolTipText(newEvent);
3476                    }
3477                }
3478
3479                // No tip from the renderer get our own tip
3480                if (tip == null)
3481                    tip = getToolTipText();
3482
3483                return tip;
3484            }
3485
3486            //
3487            // Editing Support
3488            //
3489
3490            /**
3491             * Sets whether editors in this JTable get the keyboard focus
3492             * when an editor is activated as a result of the JTable
3493             * forwarding keyboard events for a cell.
3494             * By default, this property is false, and the JTable
3495             * retains the focus unless the cell is clicked.
3496             *
3497             * @param surrendersFocusOnKeystroke true if the editor should get the focus
3498             *          when keystrokes cause the editor to be
3499             *          activated
3500             *
3501             *
3502             * @see #getSurrendersFocusOnKeystroke
3503             * @since 1.4
3504             */
3505            public void setSurrendersFocusOnKeystroke(
3506                    boolean surrendersFocusOnKeystroke) {
3507                this .surrendersFocusOnKeystroke = surrendersFocusOnKeystroke;
3508            }
3509
3510            /**
3511             * Returns true if the editor should get the focus
3512             * when keystrokes cause the editor to be activated
3513             *
3514             * @return  true if the editor should get the focus
3515             *          when keystrokes cause the editor to be
3516             *          activated
3517             *
3518             * @see #setSurrendersFocusOnKeystroke
3519             * @since 1.4
3520             */
3521            public boolean getSurrendersFocusOnKeystroke() {
3522                return surrendersFocusOnKeystroke;
3523            }
3524
3525            /**
3526             * Programmatically starts editing the cell at <code>row</code> and
3527             * <code>column</code>, if those indices are in the valid range, and
3528             * the cell at those indices is editable.
3529             * Note that this is a convenience method for
3530             * <code>editCellAt(int, int, null)</code>.
3531             *
3532             * @param   row                             the row to be edited
3533             * @param   column                          the column to be edited
3534             * @return  false if for any reason the cell cannot be edited,
3535             *                or if the indices are invalid
3536             */
3537            public boolean editCellAt(int row, int column) {
3538                return editCellAt(row, column, null);
3539            }
3540
3541            /**
3542             * Programmatically starts editing the cell at <code>row</code> and
3543             * <code>column</code>, if those indices are in the valid range, and
3544             * the cell at those indices is editable.
3545             * To prevent the <code>JTable</code> from
3546             * editing a particular table, column or cell value, return false from
3547             * the <code>isCellEditable</code> method in the <code>TableModel</code>
3548             * interface.
3549             *
3550             * @param   row     the row to be edited
3551             * @param   column  the column to be edited
3552             * @param   e       event to pass into <code>shouldSelectCell</code>;
3553             *                  note that as of Java 2 platform v1.2, the call to
3554             *                  <code>shouldSelectCell</code> is no longer made
3555             * @return  false if for any reason the cell cannot be edited,
3556             *                or if the indices are invalid
3557             */
3558            public boolean editCellAt(int row, int column, EventObject e) {
3559                if (cellEditor != null && !cellEditor.stopCellEditing()) {
3560                    return false;
3561                }
3562
3563                if (row < 0 || row >= getRowCount() || column < 0
3564                        || column >= getColumnCount()) {
3565                    return false;
3566                }
3567
3568                if (!isCellEditable(row, column))
3569                    return false;
3570
3571                if (editorRemover == null) {
3572                    KeyboardFocusManager fm = KeyboardFocusManager
3573                            .getCurrentKeyboardFocusManager();
3574                    editorRemover = new CellEditorRemover(fm);
3575                    fm.addPropertyChangeListener("permanentFocusOwner",
3576                            editorRemover);
3577                }
3578
3579                TableCellEditor editor = getCellEditor(row, column);
3580                if (editor != null && editor.isCellEditable(e)) {
3581                    editorComp = prepareEditor(editor, row, column);
3582                    if (editorComp == null) {
3583                        removeEditor();
3584                        return false;
3585                    }
3586                    editorComp.setBounds(getCellRect(row, column, false));
3587                    add(editorComp);
3588                    editorComp.validate();
3589                    editorComp.repaint();
3590
3591                    setCellEditor(editor);
3592                    setEditingRow(row);
3593                    setEditingColumn(column);
3594                    editor.addCellEditorListener(this );
3595
3596                    return true;
3597                }
3598                return false;
3599            }
3600
3601            /**
3602             * Returns true if a cell is being edited.
3603             *
3604             * @return  true if the table is editing a cell
3605             * @see     #editingColumn
3606             * @see     #editingRow
3607             */
3608            public boolean isEditing() {
3609                return (cellEditor == null) ? false : true;
3610            }
3611
3612            /**
3613             * Returns the component that is handling the editing session.
3614             * If nothing is being edited, returns null.
3615             *
3616             * @return  Component handling editing session
3617             */
3618            public Component getEditorComponent() {
3619                return editorComp;
3620            }
3621
3622            /**
3623             * Returns the index of the column that contains the cell currently
3624             * being edited.  If nothing is being edited, returns -1.
3625             *
3626             * @return  the index of the column that contains the cell currently
3627             *		being edited; returns -1 if nothing being edited
3628             * @see #editingRow
3629             */
3630            public int getEditingColumn() {
3631                return editingColumn;
3632            }
3633
3634            /**
3635             * Returns the index of the row that contains the cell currently
3636             * being edited.  If nothing is being edited, returns -1.
3637             *
3638             * @return  the index of the row that contains the cell currently
3639             *		being edited; returns -1 if nothing being edited
3640             * @see #editingColumn
3641             */
3642            public int getEditingRow() {
3643                return editingRow;
3644            }
3645
3646            //
3647            // Managing TableUI
3648            //
3649
3650            /**
3651             * Returns the L&F object that renders this component.
3652             *
3653             * @return the <code>TableUI</code> object that renders this component
3654             */
3655            public TableUI getUI() {
3656                return (TableUI) ui;
3657            }
3658
3659            /**
3660             * Sets the L&F object that renders this component and repaints.
3661             *
3662             * @param ui  the TableUI L&F object
3663             * @see UIDefaults#getUI
3664             * @beaninfo
3665             *        bound: true
3666             *       hidden: true
3667             *    attribute: visualUpdate true
3668             *  description: The UI object that implements the Component's LookAndFeel.
3669             */
3670            public void setUI(TableUI ui) {
3671                if (this .ui != ui) {
3672                    super .setUI(ui);
3673                    repaint();
3674                }
3675            }
3676
3677            /**
3678             * Notification from the <code>UIManager</code> that the L&F has changed.
3679             * Replaces the current UI object with the latest version from the
3680             * <code>UIManager</code>.
3681             *
3682             * @see JComponent#updateUI
3683             */
3684            public void updateUI() {
3685                // Update the UIs of the cell renderers, cell editors and header renderers.
3686                TableColumnModel cm = getColumnModel();
3687                for (int column = 0; column < cm.getColumnCount(); column++) {
3688                    TableColumn aColumn = cm.getColumn(column);
3689                    SwingUtilities.updateRendererOrEditorUI(aColumn
3690                            .getCellRenderer());
3691                    SwingUtilities.updateRendererOrEditorUI(aColumn
3692                            .getCellEditor());
3693                    SwingUtilities.updateRendererOrEditorUI(aColumn
3694                            .getHeaderRenderer());
3695                }
3696
3697                // Update the UIs of all the default renderers.
3698                Enumeration defaultRenderers = defaultRenderersByColumnClass
3699                        .elements();
3700                while (defaultRenderers.hasMoreElements()) {
3701                    SwingUtilities.updateRendererOrEditorUI(defaultRenderers
3702                            .nextElement());
3703                }
3704
3705                // Update the UIs of all the default editors.
3706                Enumeration defaultEditors = defaultEditorsByColumnClass
3707                        .elements();
3708                while (defaultEditors.hasMoreElements()) {
3709                    SwingUtilities.updateRendererOrEditorUI(defaultEditors
3710                            .nextElement());
3711                }
3712
3713                // Update the UI of the table header
3714                if (tableHeader != null && tableHeader.getParent() == null) {
3715                    tableHeader.updateUI();
3716                }
3717
3718                setUI((TableUI) UIManager.getUI(this ));
3719            }
3720
3721            /**
3722             * Returns the suffix used to construct the name of the L&F class used to
3723             * render this component.
3724             *
3725             * @return the string "TableUI"
3726             * @see JComponent#getUIClassID
3727             * @see UIDefaults#getUI
3728             */
3729            public String getUIClassID() {
3730                return uiClassID;
3731            }
3732
3733            //
3734            // Managing models
3735            //
3736
3737            /**
3738             * Sets the data model for this table to <code>newModel</code> and registers
3739             * with it for listener notifications from the new data model.
3740             *
3741             * @param   dataModel        the new data source for this table
3742             * @exception IllegalArgumentException      if <code>newModel</code> is <code>null</code>
3743             * @see     #getModel
3744             * @beaninfo
3745             *  bound: true
3746             *  description: The model that is the source of the data for this view.
3747             */
3748            public void setModel(TableModel dataModel) {
3749                if (dataModel == null) {
3750                    throw new IllegalArgumentException(
3751                            "Cannot set a null TableModel");
3752                }
3753                if (this .dataModel != dataModel) {
3754                    TableModel old = this .dataModel;
3755                    if (old != null) {
3756                        old.removeTableModelListener(this );
3757                    }
3758                    this .dataModel = dataModel;
3759                    dataModel.addTableModelListener(this );
3760
3761                    tableChanged(new TableModelEvent(dataModel,
3762                            TableModelEvent.HEADER_ROW));
3763
3764                    firePropertyChange("model", old, dataModel);
3765
3766                    if (getAutoCreateRowSorter()) {
3767                        setRowSorter(new TableRowSorter(dataModel));
3768                    }
3769                }
3770            }
3771
3772            /**
3773             * Returns the <code>TableModel</code> that provides the data displayed by this
3774             * <code>JTable</code>.
3775             *
3776             * @return  the <code>TableModel</code> that provides the data displayed by this <code>JTable</code>
3777             * @see     #setModel
3778             */
3779            public TableModel getModel() {
3780                return dataModel;
3781            }
3782
3783            /**
3784             * Sets the column model for this table to <code>newModel</code> and registers
3785             * for listener notifications from the new column model. Also sets
3786             * the column model of the <code>JTableHeader</code> to <code>columnModel</code>.
3787             *
3788             * @param   columnModel        the new data source for this table
3789             * @exception IllegalArgumentException      if <code>columnModel</code> is <code>null</code>
3790             * @see     #getColumnModel
3791             * @beaninfo
3792             *  bound: true
3793             *  description: The object governing the way columns appear in the view.
3794             */
3795            public void setColumnModel(TableColumnModel columnModel) {
3796                if (columnModel == null) {
3797                    throw new IllegalArgumentException(
3798                            "Cannot set a null ColumnModel");
3799                }
3800                TableColumnModel old = this .columnModel;
3801                if (columnModel != old) {
3802                    if (old != null) {
3803                        old.removeColumnModelListener(this );
3804                    }
3805                    this .columnModel = columnModel;
3806                    columnModel.addColumnModelListener(this );
3807
3808                    // Set the column model of the header as well.
3809                    if (tableHeader != null) {
3810                        tableHeader.setColumnModel(columnModel);
3811                    }
3812
3813                    firePropertyChange("columnModel", old, columnModel);
3814                    resizeAndRepaint();
3815                }
3816            }
3817
3818            /**
3819             * Returns the <code>TableColumnModel</code> that contains all column information
3820             * of this table.
3821             *
3822             * @return  the object that provides the column state of the table
3823             * @see     #setColumnModel
3824             */
3825            public TableColumnModel getColumnModel() {
3826                return columnModel;
3827            }
3828
3829            /**
3830             * Sets the row selection model for this table to <code>newModel</code>
3831             * and registers for listener notifications from the new selection model.
3832             *
3833             * @param   newModel        the new selection model
3834             * @exception IllegalArgumentException      if <code>newModel</code> is <code>null</code>
3835             * @see     #getSelectionModel
3836             * @beaninfo
3837             *      bound: true
3838             *      description: The selection model for rows.
3839             */
3840            public void setSelectionModel(ListSelectionModel newModel) {
3841                if (newModel == null) {
3842                    throw new IllegalArgumentException(
3843                            "Cannot set a null SelectionModel");
3844                }
3845
3846                ListSelectionModel oldModel = selectionModel;
3847
3848                if (newModel != oldModel) {
3849                    if (oldModel != null) {
3850                        oldModel.removeListSelectionListener(this );
3851                    }
3852
3853                    selectionModel = newModel;
3854                    newModel.addListSelectionListener(this );
3855
3856                    firePropertyChange("selectionModel", oldModel, newModel);
3857                    repaint();
3858                }
3859            }
3860
3861            /**
3862             * Returns the <code>ListSelectionModel</code> that is used to maintain row
3863             * selection state.
3864             *
3865             * @return  the object that provides row selection state, <code>null</code>
3866             *          if row selection is not allowed
3867             * @see     #setSelectionModel
3868             */
3869            public ListSelectionModel getSelectionModel() {
3870                return selectionModel;
3871            }
3872
3873            //
3874            // RowSorterListener
3875            //
3876
3877            /**
3878             * <code>RowSorterListener</code> notification that the
3879             * <code>RowSorter</code> has changed in some way.
3880             *
3881             * @param e the <code>RowSorterEvent</code> describing the change
3882             * @throws NullPointerException if <code>e</code> is <code>null</code>
3883             * @since 1.6
3884             */
3885            public void sorterChanged(RowSorterEvent e) {
3886                if (e.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) {
3887                    JTableHeader header = getTableHeader();
3888                    if (header != null) {
3889                        header.repaint();
3890                    }
3891                } else if (e.getType() == RowSorterEvent.Type.SORTED) {
3892                    sorterChanged = true;
3893                    if (!ignoreSortChange) {
3894                        sortedTableChanged(e, null);
3895                    }
3896                }
3897            }
3898
3899            /**
3900             * SortManager provides support for managing the selection and variable
3901             * row heights when sorting is enabled. This information is encapsulated
3902             * into a class to avoid bulking up JTable.
3903             */
3904            private final class SortManager {
3905                RowSorter<? extends TableModel> sorter;
3906
3907                // Selection, in terms of the model. This is lazily created
3908                // as needed.
3909                private ListSelectionModel modelSelection;
3910                private int modelLeadIndex;
3911                // Set to true while in the process of changing the selection.
3912                // If this is true the selection change is ignored.
3913                private boolean syncingSelection;
3914                // Temporary cache of selection, in terms of model. This is only used
3915                // if we don't need the full weight of modelSelection.
3916                private int[] lastModelSelection;
3917
3918                // Heights of the rows in terms of the model.
3919                private SizeSequence modelRowSizes;
3920
3921                SortManager(RowSorter<? extends TableModel> sorter) {
3922                    this .sorter = sorter;
3923                    sorter.addRowSorterListener(JTable.this );
3924                }
3925
3926                /**
3927                 * Disposes any resources used by this SortManager.
3928                 */
3929                public void dispose() {
3930                    if (sorter != null) {
3931                        sorter.removeRowSorterListener(JTable.this );
3932                    }
3933                }
3934
3935                /**
3936                 * Sets the height for a row at a specified index.
3937                 */
3938                public void setViewRowHeight(int viewIndex, int rowHeight) {
3939                    if (modelRowSizes == null) {
3940                        modelRowSizes = new SizeSequence(getModel()
3941                                .getRowCount(), getRowHeight());
3942                    }
3943                    modelRowSizes.setSize(convertRowIndexToModel(viewIndex),
3944                            rowHeight);
3945                }
3946
3947                /**
3948                 * Invoked when the underlying model has completely changed.
3949                 */
3950                public void allChanged() {
3951                    modelLeadIndex = -1;
3952                    modelSelection = null;
3953                    modelRowSizes = null;
3954                }
3955
3956                /**
3957                 * Invoked when the selection, on the view, has changed.
3958                 */
3959                public void viewSelectionChanged(ListSelectionEvent e) {
3960                    if (!syncingSelection && modelSelection != null) {
3961                        modelSelection = null;
3962                    }
3963                }
3964
3965                /**
3966                 * Invoked when either the table model has changed, or the RowSorter
3967                 * has changed. This is invoked prior to notifying the sorter of the
3968                 * change.
3969                 */
3970                public void prepareForChange(RowSorterEvent sortEvent,
3971                        ModelChange change) {
3972                    if (getUpdateSelectionOnSort()) {
3973                        cacheSelection(sortEvent, change);
3974                    }
3975                }
3976
3977                /**
3978                 * Updates the internal cache of the selection based on the change.
3979                 */
3980                private void cacheSelection(RowSorterEvent sortEvent,
3981                        ModelChange change) {
3982                    if (sortEvent != null) {
3983                        // sort order changed. If modelSelection is null and filtering
3984                        // is enabled we need to cache the selection in terms of the
3985                        // underlying model, this will allow us to correctly restore
3986                        // the selection even if rows are filtered out.
3987                        if (modelSelection == null
3988                                && sorter.getViewRowCount() != getModel()
3989                                        .getRowCount()) {
3990                            modelSelection = new DefaultListSelectionModel();
3991                            ListSelectionModel viewSelection = getSelectionModel();
3992                            int min = viewSelection.getMinSelectionIndex();
3993                            int max = viewSelection.getMaxSelectionIndex();
3994                            int modelIndex;
3995                            for (int viewIndex = min; viewIndex <= max; viewIndex++) {
3996                                if (viewSelection.isSelectedIndex(viewIndex)) {
3997                                    modelIndex = convertRowIndexToModel(
3998                                            sortEvent, viewIndex);
3999                                    if (modelIndex != -1) {
4000                                        modelSelection.addSelectionInterval(
4001                                                modelIndex, modelIndex);
4002                                    }
4003                                }
4004                            }
4005                            modelIndex = convertRowIndexToModel(sortEvent,
4006                                    viewSelection.getLeadSelectionIndex());
4007                            SwingUtilities2.setLeadAnchorWithoutSelection(
4008                                    modelSelection, modelIndex, modelIndex);
4009                        } else if (modelSelection == null) {
4010                            // Sorting changed, haven't cached selection in terms
4011                            // of model and no filtering. Temporarily cache selection.
4012                            cacheModelSelection(sortEvent);
4013                        }
4014                    } else if (change.allRowsChanged) {
4015                        // All the rows have changed, chuck any cached selection.
4016                        modelSelection = null;
4017                    } else if (modelSelection != null) {
4018                        // Table changed, reflect changes in cached selection model.
4019                        switch (change.type) {
4020                        case TableModelEvent.DELETE:
4021                            modelSelection.removeIndexInterval(
4022                                    change.startModelIndex,
4023                                    change.endModelIndex);
4024                            break;
4025                        case TableModelEvent.INSERT:
4026                            modelSelection.insertIndexInterval(
4027                                    change.startModelIndex,
4028                                    change.endModelIndex, true);
4029                            break;
4030                        default:
4031                            break;
4032                        }
4033                    } else {
4034                        // table changed, but haven't cached rows, temporarily
4035                        // cache them.
4036                        cacheModelSelection(null);
4037                    }
4038                }
4039
4040                private void cacheModelSelection(RowSorterEvent sortEvent) {
4041                    lastModelSelection = convertSelectionToModel(sortEvent);
4042                    modelLeadIndex = convertRowIndexToModel(sortEvent,
4043                            selectionModel.getLeadSelectionIndex());
4044                }
4045
4046                /**
4047                 * Inovked when either the table has changed or the sorter has changed
4048                 * and after the sorter has been notified. If necessary this will
4049                 * reapply the selection and variable row heights.
4050                 */
4051                public void processChange(RowSorterEvent sortEvent,
4052                        ModelChange change, boolean sorterChanged) {
4053                    if (change != null) {
4054                        if (change.allRowsChanged) {
4055                            modelRowSizes = null;
4056                            rowModel = null;
4057                        } else if (modelRowSizes != null) {
4058                            if (change.type == TableModelEvent.INSERT) {
4059                                modelRowSizes.insertEntries(
4060                                        change.startModelIndex,
4061                                        change.endModelIndex
4062                                                - change.startModelIndex + 1,
4063                                        getRowHeight());
4064                            } else if (change.type == TableModelEvent.DELETE) {
4065                                modelRowSizes.removeEntries(
4066                                        change.startModelIndex,
4067                                        change.endModelIndex
4068                                                - change.startModelIndex + 1);
4069                            }
4070                        }
4071                    }
4072                    if (sorterChanged) {
4073                        setViewRowHeightsFromModel();
4074                        restoreSelection(change);
4075                    }
4076                }
4077
4078                /**
4079                 * Resets the variable row heights in terms of the view from
4080                 * that of the variable row heights in terms of the model.
4081                 */
4082                private void setViewRowHeightsFromModel() {
4083                    if (modelRowSizes != null) {
4084                        rowModel.setSizes(getRowCount(), getRowHeight());
4085                        for (int viewIndex = getRowCount() - 1; viewIndex >= 0; viewIndex--) {
4086                            int modelIndex = convertRowIndexToModel(viewIndex);
4087                            rowModel.setSize(viewIndex, modelRowSizes
4088                                    .getSize(modelIndex));
4089                        }
4090                    }
4091                }
4092
4093                /**
4094                 * Restores the selection from that in terms of the model.
4095                 */
4096                private void restoreSelection(ModelChange change) {
4097                    syncingSelection = true;
4098                    if (lastModelSelection != null) {
4099                        restoreSortingSelection(lastModelSelection,
4100                                modelLeadIndex, change);
4101                        lastModelSelection = null;
4102                    } else if (modelSelection != null) {
4103                        ListSelectionModel viewSelection = getSelectionModel();
4104                        viewSelection.setValueIsAdjusting(true);
4105                        viewSelection.clearSelection();
4106                        int min = modelSelection.getMinSelectionIndex();
4107                        int max = modelSelection.getMaxSelectionIndex();
4108                        int viewIndex;
4109                        for (int modelIndex = min; modelIndex <= max; modelIndex++) {
4110                            if (modelSelection.isSelectedIndex(modelIndex)) {
4111                                viewIndex = convertRowIndexToView(modelIndex);
4112                                if (viewIndex != -1) {
4113                                    viewSelection.addSelectionInterval(
4114                                            viewIndex, viewIndex);
4115                                }
4116                            }
4117                        }
4118                        // Restore the lead
4119                        int viewLeadIndex = modelSelection
4120                                .getLeadSelectionIndex();
4121                        if (viewLeadIndex != -1) {
4122                            viewLeadIndex = convertRowIndexToView(viewLeadIndex);
4123                        }
4124                        SwingUtilities2.setLeadAnchorWithoutSelection(
4125                                viewSelection, viewLeadIndex, viewLeadIndex);
4126                        viewSelection.setValueIsAdjusting(false);
4127                    }
4128                    syncingSelection = false;
4129                }
4130            }
4131
4132            /**
4133             * ModelChange is used when sorting to restore state, it corresponds
4134             * to data from a TableModelEvent.  The values are precalculated as
4135             * they are used extensively.
4136             */
4137            private final class ModelChange {
4138                // Starting index of the change, in terms of the model
4139                int startModelIndex;
4140
4141                // Ending index of the change, in terms of the model
4142                int endModelIndex;
4143
4144                // Type of change
4145                int type;
4146
4147                // Number of rows in the model
4148                int modelRowCount;
4149
4150                // The event that triggered this.
4151                TableModelEvent event;
4152
4153                // Length of the change (end - start + 1)
4154                int length;
4155
4156                // True if the event indicates all the contents have changed
4157                boolean allRowsChanged;
4158
4159                ModelChange(TableModelEvent e) {
4160                    startModelIndex = Math.max(0, e.getFirstRow());
4161                    endModelIndex = e.getLastRow();
4162                    modelRowCount = getModel().getRowCount();
4163                    if (endModelIndex < 0) {
4164                        endModelIndex = Math.max(0, modelRowCount - 1);
4165                    }
4166                    length = endModelIndex - startModelIndex + 1;
4167                    type = e.getType();
4168                    event = e;
4169                    allRowsChanged = (e.getLastRow() == Integer.MAX_VALUE);
4170                }
4171            }
4172
4173            /**
4174             * Invoked when <code>sorterChanged</code> is invoked, or
4175             * when <code>tableChanged</code> is invoked and sorting is enabled.
4176             */
4177            private void sortedTableChanged(RowSorterEvent sortedEvent,
4178                    TableModelEvent e) {
4179                int editingModelIndex = -1;
4180                ModelChange change = (e != null) ? new ModelChange(e) : null;
4181
4182                if ((change == null || !change.allRowsChanged)
4183                        && this .editingRow != -1) {
4184                    editingModelIndex = convertRowIndexToModel(sortedEvent,
4185                            this .editingRow);
4186                }
4187
4188                sortManager.prepareForChange(sortedEvent, change);
4189
4190                if (e != null) {
4191                    if (change.type == TableModelEvent.UPDATE) {
4192                        repaintSortedRows(change);
4193                    }
4194                    notifySorter(change);
4195                    if (change.type != TableModelEvent.UPDATE) {
4196                        // If the Sorter is unsorted we will not have received
4197                        // notification, force treating insert/delete as a change.
4198                        sorterChanged = true;
4199                    }
4200                } else {
4201                    sorterChanged = true;
4202                }
4203
4204                sortManager.processChange(sortedEvent, change, sorterChanged);
4205
4206                if (sorterChanged) {
4207                    // Update the editing row
4208                    if (this .editingRow != -1) {
4209                        int newIndex = (editingModelIndex == -1) ? -1
4210                                : convertRowIndexToView(editingModelIndex,
4211                                        change);
4212                        restoreSortingEditingRow(newIndex);
4213                    }
4214
4215                    // And handle the appropriate repainting.
4216                    if (e == null || change.type != TableModelEvent.UPDATE) {
4217                        resizeAndRepaint();
4218                    }
4219                }
4220
4221                // Check if lead/anchor need to be reset.
4222                if (change != null && change.allRowsChanged) {
4223                    clearSelectionAndLeadAnchor();
4224                    resizeAndRepaint();
4225                }
4226            }
4227
4228            /**
4229             * Repaints the sort of sorted rows in response to a TableModelEvent.
4230             */
4231            private void repaintSortedRows(ModelChange change) {
4232                if (change.startModelIndex > change.endModelIndex
4233                        || change.startModelIndex + 10 < change.endModelIndex) {
4234                    // Too much has changed, punt
4235                    repaint();
4236                    return;
4237                }
4238                int eventColumn = change.event.getColumn();
4239                int columnViewIndex = eventColumn;
4240                if (columnViewIndex == TableModelEvent.ALL_COLUMNS) {
4241                    columnViewIndex = 0;
4242                } else {
4243                    columnViewIndex = convertColumnIndexToView(columnViewIndex);
4244                    if (columnViewIndex == -1) {
4245                        return;
4246                    }
4247                }
4248                int modelIndex = change.startModelIndex;
4249                while (modelIndex <= change.endModelIndex) {
4250                    int viewIndex = convertRowIndexToView(modelIndex++);
4251                    if (viewIndex != -1) {
4252                        Rectangle dirty = getCellRect(viewIndex,
4253                                columnViewIndex, false);
4254                        int x = dirty.x;
4255                        int w = dirty.width;
4256                        if (eventColumn == TableModelEvent.ALL_COLUMNS) {
4257                            x = 0;
4258                            w = getWidth();
4259                        }
4260                        repaint(x, dirty.y, w, dirty.height);
4261                    }
4262                }
4263            }
4264
4265            /**
4266             * Restores the selection after a model event/sort order changes.
4267             * All coordinates are in terms of the model.
4268             */
4269            private void restoreSortingSelection(int[] selection, int lead,
4270                    ModelChange change) {
4271                // Convert the selection from model to view
4272                for (int i = selection.length - 1; i >= 0; i--) {
4273                    selection[i] = convertRowIndexToView(selection[i], change);
4274                }
4275                lead = convertRowIndexToView(lead, change);
4276
4277                // Check for the common case of no change in selection for 1 row
4278                if (selection.length == 0
4279                        || (selection.length == 1 && selection[0] == getSelectedRow())) {
4280                    return;
4281                }
4282
4283                // And apply the new selection
4284                selectionModel.setValueIsAdjusting(true);
4285                selectionModel.clearSelection();
4286                for (int i = selection.length - 1; i >= 0; i--) {
4287                    if (selection[i] != -1) {
4288                        selectionModel.addSelectionInterval(selection[i],
4289                                selection[i]);
4290                    }
4291                }
4292                SwingUtilities2.setLeadAnchorWithoutSelection(selectionModel,
4293                        lead, lead);
4294                selectionModel.setValueIsAdjusting(false);
4295            }
4296
4297            /**
4298             * Restores the editing row after a model event/sort order change.
4299             *
4300             * @param editingRow new index of the editingRow, in terms of the view
4301             */
4302            private void restoreSortingEditingRow(int editingRow) {
4303                if (editingRow == -1) {
4304                    // Editing row no longer being shown, cancel editing
4305                    TableCellEditor editor = getCellEditor();
4306                    if (editor != null) {
4307                        // First try and cancel
4308                        editor.cancelCellEditing();
4309                        if (getCellEditor() != null) {
4310                            // CellEditor didn't cede control, forcefully
4311                            // remove it
4312                            removeEditor();
4313                        }
4314                    }
4315                } else {
4316                    // Repositioning handled in BasicTableUI
4317                    this .editingRow = editingRow;
4318                    repaint();
4319                }
4320            }
4321
4322            /**
4323             * Notifies the sorter of a change in the underlying model.
4324             */
4325            private void notifySorter(ModelChange change) {
4326                try {
4327                    ignoreSortChange = true;
4328                    sorterChanged = false;
4329                    switch (change.type) {
4330                    case TableModelEvent.UPDATE:
4331                        if (change.event.getLastRow() == Integer.MAX_VALUE) {
4332                            sortManager.sorter.allRowsChanged();
4333                        } else if (change.event.getColumn() == TableModelEvent.ALL_COLUMNS) {
4334                            sortManager.sorter.rowsUpdated(
4335                                    change.startModelIndex,
4336                                    change.endModelIndex);
4337                        } else {
4338                            sortManager.sorter.rowsUpdated(
4339                                    change.startModelIndex,
4340                                    change.endModelIndex, change.event
4341                                            .getColumn());
4342                        }
4343                        break;
4344                    case TableModelEvent.INSERT:
4345                        sortManager.sorter.rowsInserted(change.startModelIndex,
4346                                change.endModelIndex);
4347                        break;
4348                    case TableModelEvent.DELETE:
4349                        sortManager.sorter.rowsDeleted(change.startModelIndex,
4350                                change.endModelIndex);
4351                        break;
4352                    }
4353                } finally {
4354                    ignoreSortChange = false;
4355                }
4356            }
4357
4358            /**
4359             * Converts a model index to view index.  This is called when the
4360             * sorter or model changes and sorting is enabled.
4361             *
4362             * @param change describes the TableModelEvent that initiated the change;
4363             *        will be null if called as the result of a sort
4364             */
4365            private int convertRowIndexToView(int modelIndex, ModelChange change) {
4366                if (modelIndex < 0) {
4367                    return -1;
4368                }
4369                if (change != null && modelIndex >= change.startModelIndex) {
4370                    if (change.type == TableModelEvent.INSERT) {
4371                        if (modelIndex + change.length >= change.modelRowCount) {
4372                            return -1;
4373                        }
4374                        return sortManager.sorter
4375                                .convertRowIndexToView(modelIndex
4376                                        + change.length);
4377                    } else if (change.type == TableModelEvent.DELETE) {
4378                        if (modelIndex <= change.endModelIndex) {
4379                            // deleted
4380                            return -1;
4381                        } else {
4382                            if (modelIndex - change.length >= change.modelRowCount) {
4383                                return -1;
4384                            }
4385                            return sortManager.sorter
4386                                    .convertRowIndexToView(modelIndex
4387                                            - change.length);
4388                        }
4389                    }
4390                    // else, updated
4391                }
4392                if (modelIndex >= getModel().getRowCount()) {
4393                    return -1;
4394                }
4395                return sortManager.sorter.convertRowIndexToView(modelIndex);
4396            }
4397
4398            /**
4399             * Converts the selection to model coordinates.  This is used when
4400             * the model changes or the sorter changes.
4401             */
4402            private int[] convertSelectionToModel(RowSorterEvent e) {
4403                int[] selection = getSelectedRows();
4404                for (int i = selection.length - 1; i >= 0; i--) {
4405                    selection[i] = convertRowIndexToModel(e, selection[i]);
4406                }
4407                return selection;
4408            }
4409
4410            private int convertRowIndexToModel(RowSorterEvent e, int viewIndex) {
4411                if (e != null) {
4412                    if (e.getPreviousRowCount() == 0) {
4413                        return viewIndex;
4414                    }
4415                    // range checking handled by RowSorterEvent
4416                    return e.convertPreviousRowIndexToModel(viewIndex);
4417                }
4418                // Make sure the viewIndex is valid
4419                if (viewIndex < 0 || viewIndex >= getRowCount()) {
4420                    return -1;
4421                }
4422                return convertRowIndexToModel(viewIndex);
4423            }
4424
4425            //
4426            // Implementing TableModelListener interface
4427            //
4428
4429            /**
4430             * Invoked when this table's <code>TableModel</code> generates
4431             * a <code>TableModelEvent</code>.
4432             * The <code>TableModelEvent</code> should be constructed in the
4433             * coordinate system of the model; the appropriate mapping to the
4434             * view coordinate system is performed by this <code>JTable</code>
4435             * when it receives the event.
4436             * <p>
4437             * Application code will not use these methods explicitly, they
4438             * are used internally by <code>JTable</code>.
4439             * <p>
4440             * Note that as of 1.3, this method clears the selection, if any.
4441             */
4442            public void tableChanged(TableModelEvent e) {
4443                if (e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW) {
4444                    // The whole thing changed
4445                    clearSelectionAndLeadAnchor();
4446
4447                    rowModel = null;
4448
4449                    if (sortManager != null) {
4450                        try {
4451                            ignoreSortChange = true;
4452                            sortManager.sorter.modelStructureChanged();
4453                        } finally {
4454                            ignoreSortChange = false;
4455                        }
4456                        sortManager.allChanged();
4457                    }
4458
4459                    if (getAutoCreateColumnsFromModel()) {
4460                        // This will effect invalidation of the JTable and JTableHeader.
4461                        createDefaultColumnsFromModel();
4462                        return;
4463                    }
4464
4465                    resizeAndRepaint();
4466                    return;
4467                }
4468
4469                if (sortManager != null) {
4470                    sortedTableChanged(null, e);
4471                    return;
4472                }
4473
4474                // The totalRowHeight calculated below will be incorrect if
4475                // there are variable height rows. Repaint the visible region,
4476                // but don't return as a revalidate may be necessary as well.
4477                if (rowModel != null) {
4478                    repaint();
4479                }
4480
4481                if (e.getType() == TableModelEvent.INSERT) {
4482                    tableRowsInserted(e);
4483                    return;
4484                }
4485
4486                if (e.getType() == TableModelEvent.DELETE) {
4487                    tableRowsDeleted(e);
4488                    return;
4489                }
4490
4491                int modelColumn = e.getColumn();
4492                int start = e.getFirstRow();
4493                int end = e.getLastRow();
4494
4495                Rectangle dirtyRegion;
4496                if (modelColumn == TableModelEvent.ALL_COLUMNS) {
4497                    // 1 or more rows changed
4498                    dirtyRegion = new Rectangle(0, start * getRowHeight(),
4499                            getColumnModel().getTotalColumnWidth(), 0);
4500                } else {
4501                    // A cell or column of cells has changed.
4502                    // Unlike the rest of the methods in the JTable, the TableModelEvent
4503                    // uses the coordinate system of the model instead of the view.
4504                    // This is the only place in the JTable where this "reverse mapping"
4505                    // is used.
4506                    int column = convertColumnIndexToView(modelColumn);
4507                    dirtyRegion = getCellRect(start, column, false);
4508                }
4509
4510                // Now adjust the height of the dirty region according to the value of "end".
4511                // Check for Integer.MAX_VALUE as this will cause an overflow.
4512                if (end != Integer.MAX_VALUE) {
4513                    dirtyRegion.height = (end - start + 1) * getRowHeight();
4514                    repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width,
4515                            dirtyRegion.height);
4516                }
4517                // In fact, if the end is Integer.MAX_VALUE we need to revalidate anyway
4518                // because the scrollbar may need repainting.
4519                else {
4520                    clearSelectionAndLeadAnchor();
4521                    resizeAndRepaint();
4522                    rowModel = null;
4523                }
4524            }
4525
4526            /*
4527             * Invoked when rows have been inserted into the table.
4528             * <p>
4529             * Application code will not use these methods explicitly, they
4530             * are used internally by JTable.
4531             *
4532             * @param e the TableModelEvent encapsulating the insertion
4533             */
4534            private void tableRowsInserted(TableModelEvent e) {
4535                int start = e.getFirstRow();
4536                int end = e.getLastRow();
4537                if (start < 0) {
4538                    start = 0;
4539                }
4540                if (end < 0) {
4541                    end = getRowCount() - 1;
4542                }
4543
4544                // Adjust the selection to account for the new rows.
4545                int length = end - start + 1;
4546                selectionModel.insertIndexInterval(start, length, true);
4547
4548                // If we have variable height rows, adjust the row model.
4549                if (rowModel != null) {
4550                    rowModel.insertEntries(start, length, getRowHeight());
4551                }
4552                int rh = getRowHeight();
4553                Rectangle drawRect = new Rectangle(0, start * rh,
4554                        getColumnModel().getTotalColumnWidth(),
4555                        (getRowCount() - start) * rh);
4556
4557                revalidate();
4558                // PENDING(milne) revalidate calls repaint() if parent is a ScrollPane
4559                // repaint still required in the unusual case where there is no ScrollPane
4560                repaint(drawRect);
4561            }
4562
4563            /*
4564             * Invoked when rows have been removed from the table.
4565             * <p>
4566             * Application code will not use these methods explicitly, they
4567             * are used internally by JTable.
4568             *
4569             * @param e the TableModelEvent encapsulating the deletion
4570             */
4571            private void tableRowsDeleted(TableModelEvent e) {
4572                int start = e.getFirstRow();
4573                int end = e.getLastRow();
4574                if (start < 0) {
4575                    start = 0;
4576                }
4577                if (end < 0) {
4578                    end = getRowCount() - 1;
4579                }
4580
4581                int deletedCount = end - start + 1;
4582                int previousRowCount = getRowCount() + deletedCount;
4583                // Adjust the selection to account for the new rows
4584                selectionModel.removeIndexInterval(start, end);
4585
4586                // If we have variable height rows, adjust the row model.
4587                if (rowModel != null) {
4588                    rowModel.removeEntries(start, deletedCount);
4589                }
4590
4591                int rh = getRowHeight();
4592                Rectangle drawRect = new Rectangle(0, start * rh,
4593                        getColumnModel().getTotalColumnWidth(),
4594                        (previousRowCount - start) * rh);
4595
4596                revalidate();
4597                // PENDING(milne) revalidate calls repaint() if parent is a ScrollPane
4598                // repaint still required in the unusual case where there is no ScrollPane
4599                repaint(drawRect);
4600            }
4601
4602            //
4603            // Implementing TableColumnModelListener interface
4604            //
4605
4606            /**
4607             * Invoked when a column is added to the table column model.
4608             * <p>
4609             * Application code will not use these methods explicitly, they
4610             * are used internally by JTable.
4611             *
4612             * @see TableColumnModelListener
4613             */
4614            public void columnAdded(TableColumnModelEvent e) {
4615                // If I'm currently editing, then I should stop editing
4616                if (isEditing()) {
4617                    removeEditor();
4618                }
4619                resizeAndRepaint();
4620            }
4621
4622            /**
4623             * Invoked when a column is removed from the table column model.
4624             * <p>
4625             * Application code will not use these methods explicitly, they
4626             * are used internally by JTable.
4627             *
4628             * @see TableColumnModelListener
4629             */
4630            public void columnRemoved(TableColumnModelEvent e) {
4631                // If I'm currently editing, then I should stop editing
4632                if (isEditing()) {
4633                    removeEditor();
4634                }
4635                resizeAndRepaint();
4636            }
4637
4638            /**
4639             * Invoked when a column is repositioned. If a cell is being
4640             * edited, then editing is stopped and the cell is redrawn.
4641             * <p>
4642             * Application code will not use these methods explicitly, they
4643             * are used internally by JTable.
4644             *
4645             * @param e   the event received
4646             * @see TableColumnModelListener
4647             */
4648            public void columnMoved(TableColumnModelEvent e) {
4649                // If I'm currently editing, then I should stop editing
4650                if (isEditing()) {
4651                    removeEditor();
4652                }
4653                repaint();
4654            }
4655
4656            /**
4657             * Invoked when a column is moved due to a margin change.
4658             * If a cell is being edited, then editing is stopped and the cell
4659             * is redrawn.
4660             * <p>
4661             * Application code will not use these methods explicitly, they
4662             * are used internally by JTable.
4663             *
4664             * @param  e    the event received
4665             * @see TableColumnModelListener
4666             */
4667            public void columnMarginChanged(ChangeEvent e) {
4668                if (isEditing()) {
4669                    removeEditor();
4670                }
4671                TableColumn resizingColumn = getResizingColumn();
4672                // Need to do this here, before the parent's
4673                // layout manager calls getPreferredSize().
4674                if (resizingColumn != null && autoResizeMode == AUTO_RESIZE_OFF) {
4675                    resizingColumn.setPreferredWidth(resizingColumn.getWidth());
4676                }
4677                resizeAndRepaint();
4678            }
4679
4680            private int limit(int i, int a, int b) {
4681                return Math.min(b, Math.max(i, a));
4682            }
4683
4684            /**
4685             * Invoked when the selection model of the <code>TableColumnModel</code>
4686             * is changed.
4687             * <p>
4688             * Application code will not use these methods explicitly, they
4689             * are used internally by JTable.
4690             *
4691             * @param  e  the event received
4692             * @see TableColumnModelListener
4693             */
4694            public void columnSelectionChanged(ListSelectionEvent e) {
4695                boolean isAdjusting = e.getValueIsAdjusting();
4696                if (columnSelectionAdjusting && !isAdjusting) {
4697                    // The assumption is that when the model is no longer adjusting
4698                    // we will have already gotten all the changes, and therefore
4699                    // don't need to do an additional paint.
4700                    columnSelectionAdjusting = false;
4701                    return;
4702                }
4703                columnSelectionAdjusting = isAdjusting;
4704                // The getCellRect() call will fail unless there is at least one row.
4705                if (getRowCount() <= 0 || getColumnCount() <= 0) {
4706                    return;
4707                }
4708                int firstIndex = limit(e.getFirstIndex(), 0,
4709                        getColumnCount() - 1);
4710                int lastIndex = limit(e.getLastIndex(), 0, getColumnCount() - 1);
4711                int minRow = 0;
4712                int maxRow = getRowCount() - 1;
4713                if (getRowSelectionAllowed()) {
4714                    minRow = selectionModel.getMinSelectionIndex();
4715                    maxRow = selectionModel.getMaxSelectionIndex();
4716                    int leadRow = getAdjustedIndex(selectionModel
4717                            .getLeadSelectionIndex(), true);
4718
4719                    if (minRow == -1 || maxRow == -1) {
4720                        if (leadRow == -1) {
4721                            // nothing to repaint, return
4722                            return;
4723                        }
4724
4725                        // only thing to repaint is the lead
4726                        minRow = maxRow = leadRow;
4727                    } else {
4728                        // We need to consider more than just the range between
4729                        // the min and max selected index. The lead row, which could
4730                        // be outside this range, should be considered also.
4731                        if (leadRow != -1) {
4732                            minRow = Math.min(minRow, leadRow);
4733                            maxRow = Math.max(maxRow, leadRow);
4734                        }
4735                    }
4736                }
4737                Rectangle firstColumnRect = getCellRect(minRow, firstIndex,
4738                        false);
4739                Rectangle lastColumnRect = getCellRect(maxRow, lastIndex, false);
4740                Rectangle dirtyRegion = firstColumnRect.union(lastColumnRect);
4741                repaint(dirtyRegion);
4742            }
4743
4744            //
4745            // Implementing ListSelectionListener interface
4746            //
4747
4748            /**
4749             * Invoked when the row selection changes -- repaints to show the new
4750             * selection.
4751             * <p>
4752             * Application code will not use these methods explicitly, they
4753             * are used internally by JTable.
4754             *
4755             * @param e   the event received
4756             * @see ListSelectionListener
4757             */
4758            public void valueChanged(ListSelectionEvent e) {
4759                if (sortManager != null) {
4760                    sortManager.viewSelectionChanged(e);
4761                }
4762                boolean isAdjusting = e.getValueIsAdjusting();
4763                if (rowSelectionAdjusting && !isAdjusting) {
4764                    // The assumption is that when the model is no longer adjusting
4765                    // we will have already gotten all the changes, and therefore
4766                    // don't need to do an additional paint.
4767                    rowSelectionAdjusting = false;
4768                    return;
4769                }
4770                rowSelectionAdjusting = isAdjusting;
4771                // The getCellRect() calls will fail unless there is at least one column.
4772                if (getRowCount() <= 0 || getColumnCount() <= 0) {
4773                    return;
4774                }
4775                int firstIndex = limit(e.getFirstIndex(), 0, getRowCount() - 1);
4776                int lastIndex = limit(e.getLastIndex(), 0, getRowCount() - 1);
4777                Rectangle firstRowRect = getCellRect(firstIndex, 0, false);
4778                Rectangle lastRowRect = getCellRect(lastIndex,
4779                        getColumnCount() - 1, false);
4780                Rectangle dirtyRegion = firstRowRect.union(lastRowRect);
4781                repaint(dirtyRegion);
4782            }
4783
4784            //
4785            // Implementing the CellEditorListener interface
4786            //
4787
4788            /**
4789             * Invoked when editing is finished. The changes are saved and the
4790             * editor is discarded.
4791             * <p>
4792             * Application code will not use these methods explicitly, they
4793             * are used internally by JTable.
4794             *
4795             * @param  e  the event received
4796             * @see CellEditorListener
4797             */
4798            public void editingStopped(ChangeEvent e) {
4799                // Take in the new value
4800                TableCellEditor editor = getCellEditor();
4801                if (editor != null) {
4802                    Object value = editor.getCellEditorValue();
4803                    setValueAt(value, editingRow, editingColumn);
4804                    removeEditor();
4805                }
4806            }
4807
4808            /**
4809             * Invoked when editing is canceled. The editor object is discarded
4810             * and the cell is rendered once again.
4811             * <p>
4812             * Application code will not use these methods explicitly, they
4813             * are used internally by JTable.
4814             *
4815             * @param  e  the event received
4816             * @see CellEditorListener
4817             */
4818            public void editingCanceled(ChangeEvent e) {
4819                removeEditor();
4820            }
4821
4822            //
4823            // Implementing the Scrollable interface
4824            //
4825
4826            /**
4827             * Sets the preferred size of the viewport for this table.
4828             *
4829             * @param size  a <code>Dimension</code> object specifying the <code>preferredSize</code> of a
4830             *              <code>JViewport</code> whose view is this table
4831             * @see Scrollable#getPreferredScrollableViewportSize
4832             * @beaninfo
4833             * description: The preferred size of the viewport.
4834             */
4835            public void setPreferredScrollableViewportSize(Dimension size) {
4836                preferredViewportSize = size;
4837            }
4838
4839            /**
4840             * Returns the preferred size of the viewport for this table.
4841             *
4842             * @return a <code>Dimension</code> object containing the <code>preferredSize</code> of the <code>JViewport</code>
4843             *         which displays this table
4844             * @see Scrollable#getPreferredScrollableViewportSize
4845             */
4846            public Dimension getPreferredScrollableViewportSize() {
4847                return preferredViewportSize;
4848            }
4849
4850            /**
4851             * Returns the scroll increment (in pixels) that completely exposes one new
4852             * row or column (depending on the orientation).
4853             * <p>
4854             * This method is called each time the user requests a unit scroll.
4855             *
4856             * @param visibleRect the view area visible within the viewport
4857             * @param orientation either <code>SwingConstants.VERTICAL</code>
4858             *                	or <code>SwingConstants.HORIZONTAL</code>
4859             * @param direction less than zero to scroll up/left,
4860             *                  greater than zero for down/right
4861             * @return the "unit" increment for scrolling in the specified direction
4862             * @see Scrollable#getScrollableUnitIncrement
4863             */
4864            public int getScrollableUnitIncrement(Rectangle visibleRect,
4865                    int orientation, int direction) {
4866                int leadingRow;
4867                int leadingCol;
4868                Rectangle leadingCellRect;
4869
4870                int leadingVisibleEdge;
4871                int leadingCellEdge;
4872                int leadingCellSize;
4873
4874                leadingRow = getLeadingRow(visibleRect);
4875                leadingCol = getLeadingCol(visibleRect);
4876                if (orientation == SwingConstants.VERTICAL && leadingRow < 0) {
4877                    // Couldn't find leading row - return some default value
4878                    return getRowHeight();
4879                } else if (orientation == SwingConstants.HORIZONTAL
4880                        && leadingCol < 0) {
4881                    // Couldn't find leading col - return some default value
4882                    return 100;
4883                }
4884
4885                // Note that it's possible for one of leadingCol or leadingRow to be
4886                // -1, depending on the orientation.  This is okay, as getCellRect()
4887                // still provides enough information to calculate the unit increment.
4888                leadingCellRect = getCellRect(leadingRow, leadingCol, true);
4889                leadingVisibleEdge = leadingEdge(visibleRect, orientation);
4890                leadingCellEdge = leadingEdge(leadingCellRect, orientation);
4891
4892                if (orientation == SwingConstants.VERTICAL) {
4893                    leadingCellSize = leadingCellRect.height;
4894
4895                } else {
4896                    leadingCellSize = leadingCellRect.width;
4897                }
4898
4899                // 4 cases:
4900                // #1: Leading cell fully visible, reveal next cell
4901                // #2: Leading cell fully visible, hide leading cell
4902                // #3: Leading cell partially visible, hide rest of leading cell
4903                // #4: Leading cell partially visible, reveal rest of leading cell
4904
4905                if (leadingVisibleEdge == leadingCellEdge) { // Leading cell is fully
4906                    // visible
4907                    // Case #1: Reveal previous cell
4908                    if (direction < 0) {
4909                        int retVal = 0;
4910
4911                        if (orientation == SwingConstants.VERTICAL) {
4912                            // Loop past any zero-height rows
4913                            while (--leadingRow >= 0) {
4914                                retVal = getRowHeight(leadingRow);
4915                                if (retVal != 0) {
4916                                    break;
4917                                }
4918                            }
4919                        } else { // HORIZONTAL
4920                            // Loop past any zero-width cols
4921                            while (--leadingCol >= 0) {
4922                                retVal = getCellRect(leadingRow, leadingCol,
4923                                        true).width;
4924                                if (retVal != 0) {
4925                                    break;
4926                                }
4927                            }
4928                        }
4929                        return retVal;
4930                    } else { // Case #2: hide leading cell
4931                        return leadingCellSize;
4932                    }
4933                } else { // Leading cell is partially hidden
4934                    // Compute visible, hidden portions
4935                    int hiddenAmt = Math.abs(leadingVisibleEdge
4936                            - leadingCellEdge);
4937                    int visibleAmt = leadingCellSize - hiddenAmt;
4938
4939                    if (direction > 0) {
4940                        // Case #3: hide showing portion of leading cell
4941                        return visibleAmt;
4942                    } else { // Case #4: reveal hidden portion of leading cell
4943                        return hiddenAmt;
4944                    }
4945                }
4946            }
4947
4948            /**
4949             * Returns <code>visibleRect.height</code> or
4950             * <code>visibleRect.width</code>,
4951             * depending on this table's orientation.  Note that as of Swing 1.1.1
4952             * (Java 2 v 1.2.2) the value
4953             * returned will ensure that the viewport is cleanly aligned on
4954             * a row boundary.
4955             *
4956             * @return <code>visibleRect.height</code> or
4957             * 					<code>visibleRect.width</code>
4958             * 					per the orientation
4959             * @see Scrollable#getScrollableBlockIncrement
4960             */
4961            public int getScrollableBlockIncrement(Rectangle visibleRect,
4962                    int orientation, int direction) {
4963
4964                if (getRowCount() == 0) {
4965                    // Short-circuit empty table model
4966                    if (SwingConstants.VERTICAL == orientation) {
4967                        int rh = getRowHeight();
4968                        return (rh > 0) ? Math.max(rh,
4969                                (visibleRect.height / rh) * rh)
4970                                : visibleRect.height;
4971                    } else {
4972                        return visibleRect.width;
4973                    }
4974                }
4975                // Shortcut for vertical scrolling of a table w/ uniform row height
4976                if (null == rowModel && SwingConstants.VERTICAL == orientation) {
4977                    int row = rowAtPoint(visibleRect.getLocation());
4978                    assert row != -1;
4979                    int col = columnAtPoint(visibleRect.getLocation());
4980                    Rectangle cellRect = getCellRect(row, col, true);
4981
4982                    if (cellRect.y == visibleRect.y) {
4983                        int rh = getRowHeight();
4984                        assert rh > 0;
4985                        return Math.max(rh, (visibleRect.height / rh) * rh);
4986                    }
4987                }
4988                if (direction < 0) {
4989                    return getPreviousBlockIncrement(visibleRect, orientation);
4990                } else {
4991                    return getNextBlockIncrement(visibleRect, orientation);
4992                }
4993            }
4994
4995            /**
4996             * Called to get the block increment for upward scrolling in cases of
4997             * horizontal scrolling, or for vertical scrolling of a table with
4998             * variable row heights.
4999             */
5000            private int getPreviousBlockIncrement(Rectangle visibleRect,
5001                    int orientation) {
5002                // Measure back from visible leading edge
5003                // If we hit the cell on its leading edge, it becomes the leading cell.
5004                // Else, use following cell
5005
5006                int row;
5007                int col;
5008
5009                int newEdge;
5010                Point newCellLoc;
5011
5012                int visibleLeadingEdge = leadingEdge(visibleRect, orientation);
5013                boolean leftToRight = getComponentOrientation().isLeftToRight();
5014                int newLeadingEdge;
5015
5016                // Roughly determine the new leading edge by measuring back from the
5017                // leading visible edge by the size of the visible rect, and find the
5018                // cell there.
5019                if (orientation == SwingConstants.VERTICAL) {
5020                    newEdge = visibleLeadingEdge - visibleRect.height;
5021                    int x = visibleRect.x
5022                            + (leftToRight ? 0 : visibleRect.width);
5023                    newCellLoc = new Point(x, newEdge);
5024                } else if (leftToRight) {
5025                    newEdge = visibleLeadingEdge - visibleRect.width;
5026                    newCellLoc = new Point(newEdge, visibleRect.y);
5027                } else { // Horizontal, right-to-left
5028                    newEdge = visibleLeadingEdge + visibleRect.width;
5029                    newCellLoc = new Point(newEdge - 1, visibleRect.y);
5030                }
5031                row = rowAtPoint(newCellLoc);
5032                col = columnAtPoint(newCellLoc);
5033
5034                // If we're measuring past the beginning of the table, we get an invalid
5035                // cell.  Just go to the beginning of the table in this case.
5036                if (orientation == SwingConstants.VERTICAL & row < 0) {
5037                    newLeadingEdge = 0;
5038                } else if (orientation == SwingConstants.HORIZONTAL & col < 0) {
5039                    if (leftToRight) {
5040                        newLeadingEdge = 0;
5041                    } else {
5042                        newLeadingEdge = getWidth();
5043                    }
5044                } else {
5045                    // Refine our measurement
5046                    Rectangle newCellRect = getCellRect(row, col, true);
5047                    int newCellLeadingEdge = leadingEdge(newCellRect,
5048                            orientation);
5049                    int newCellTrailingEdge = trailingEdge(newCellRect,
5050                            orientation);
5051
5052                    // Usually, we hit in the middle of newCell, and want to scroll to
5053                    // the beginning of the cell after newCell.  But there are a
5054                    // couple corner cases where we want to scroll to the beginning of
5055                    // newCell itself.  These cases are:
5056                    // 1) newCell is so large that it ends at or extends into the
5057                    //    visibleRect (newCell is the leading cell, or is adjacent to
5058                    //    the leading cell)
5059                    // 2) newEdge happens to fall right on the beginning of a cell
5060
5061                    // Case 1
5062                    if ((orientation == SwingConstants.VERTICAL || leftToRight)
5063                            && (newCellTrailingEdge >= visibleLeadingEdge)) {
5064                        newLeadingEdge = newCellLeadingEdge;
5065                    } else if (orientation == SwingConstants.HORIZONTAL
5066                            && !leftToRight
5067                            && newCellTrailingEdge <= visibleLeadingEdge) {
5068                        newLeadingEdge = newCellLeadingEdge;
5069                    }
5070                    // Case 2:
5071                    else if (newEdge == newCellLeadingEdge) {
5072                        newLeadingEdge = newCellLeadingEdge;
5073                    }
5074                    // Common case: scroll to cell after newCell
5075                    else {
5076                        newLeadingEdge = newCellTrailingEdge;
5077                    }
5078                }
5079                return Math.abs(visibleLeadingEdge - newLeadingEdge);
5080            }
5081
5082            /**  
5083             * Called to get the block increment for downward scrolling in cases of  
5084             * horizontal scrolling, or for vertical scrolling of a table with  
5085             * variable row heights.  
5086             */
5087            private int getNextBlockIncrement(Rectangle visibleRect,
5088                    int orientation) {
5089                // Find the cell at the trailing edge.  Return the distance to put
5090                // that cell at the leading edge.
5091                int trailingRow = getTrailingRow(visibleRect);
5092                int trailingCol = getTrailingCol(visibleRect);
5093
5094                Rectangle cellRect;
5095                boolean cellFillsVis;
5096
5097                int cellLeadingEdge;
5098                int cellTrailingEdge;
5099                int newLeadingEdge;
5100                int visibleLeadingEdge = leadingEdge(visibleRect, orientation);
5101
5102                // If we couldn't find trailing cell, just return the size of the
5103                // visibleRect.  Note that, for instance, we don't need the
5104                // trailingCol to proceed if we're scrolling vertically, because
5105                // cellRect will still fill in the required dimensions.  This would
5106                // happen if we're scrolling vertically, and the table is not wide
5107                // enough to fill the visibleRect.
5108                if (orientation == SwingConstants.VERTICAL && trailingRow < 0) {
5109                    return visibleRect.height;
5110                } else if (orientation == SwingConstants.HORIZONTAL
5111                        && trailingCol < 0) {
5112                    return visibleRect.width;
5113                }
5114                cellRect = getCellRect(trailingRow, trailingCol, true);
5115                cellLeadingEdge = leadingEdge(cellRect, orientation);
5116                cellTrailingEdge = trailingEdge(cellRect, orientation);
5117
5118                if (orientation == SwingConstants.VERTICAL
5119                        || getComponentOrientation().isLeftToRight()) {
5120                    cellFillsVis = cellLeadingEdge <= visibleLeadingEdge;
5121                } else { // Horizontal, right-to-left
5122                    cellFillsVis = cellLeadingEdge >= visibleLeadingEdge;
5123                }
5124
5125                if (cellFillsVis) {
5126                    // The visibleRect contains a single large cell.  Scroll to the end
5127                    // of this cell, so the following cell is the first cell.
5128                    newLeadingEdge = cellTrailingEdge;
5129                } else if (cellTrailingEdge == trailingEdge(visibleRect,
5130                        orientation)) {
5131                    // The trailing cell happens to end right at the end of the 
5132                    // visibleRect.  Again, scroll to the beginning of the next cell.
5133                    newLeadingEdge = cellTrailingEdge;
5134                } else {
5135                    // Common case: the trailing cell is partially visible, and isn't
5136                    // big enough to take up the entire visibleRect.  Scroll so it 
5137                    // becomes the leading cell.
5138                    newLeadingEdge = cellLeadingEdge;
5139                }
5140                return Math.abs(newLeadingEdge - visibleLeadingEdge);
5141            }
5142
5143            /*
5144             * Return the row at the top of the visibleRect
5145             *
5146             * May return -1
5147             */
5148            private int getLeadingRow(Rectangle visibleRect) {
5149                Point leadingPoint;
5150
5151                if (getComponentOrientation().isLeftToRight()) {
5152                    leadingPoint = new Point(visibleRect.x, visibleRect.y);
5153                } else {
5154                    leadingPoint = new Point(visibleRect.x + visibleRect.width
5155                            - 1, visibleRect.y);
5156                }
5157                return rowAtPoint(leadingPoint);
5158            }
5159
5160            /*
5161             * Return the column at the leading edge of the visibleRect.
5162             *
5163             * May return -1
5164             */
5165            private int getLeadingCol(Rectangle visibleRect) {
5166                Point leadingPoint;
5167
5168                if (getComponentOrientation().isLeftToRight()) {
5169                    leadingPoint = new Point(visibleRect.x, visibleRect.y);
5170                } else {
5171                    leadingPoint = new Point(visibleRect.x + visibleRect.width
5172                            - 1, visibleRect.y);
5173                }
5174                return columnAtPoint(leadingPoint);
5175            }
5176
5177            /*
5178             * Return the row at the bottom of the visibleRect.
5179             *
5180             * May return -1
5181             */
5182            private int getTrailingRow(Rectangle visibleRect) {
5183                Point trailingPoint;
5184
5185                if (getComponentOrientation().isLeftToRight()) {
5186                    trailingPoint = new Point(visibleRect.x, visibleRect.y
5187                            + visibleRect.height - 1);
5188                } else {
5189                    trailingPoint = new Point(visibleRect.x + visibleRect.width
5190                            - 1, visibleRect.y + visibleRect.height - 1);
5191                }
5192                return rowAtPoint(trailingPoint);
5193            }
5194
5195            /*
5196             * Return the column at the trailing edge of the visibleRect.
5197             * 
5198             * May return -1
5199             */
5200            private int getTrailingCol(Rectangle visibleRect) {
5201                Point trailingPoint;
5202
5203                if (getComponentOrientation().isLeftToRight()) {
5204                    trailingPoint = new Point(visibleRect.x + visibleRect.width
5205                            - 1, visibleRect.y);
5206                } else {
5207                    trailingPoint = new Point(visibleRect.x, visibleRect.y);
5208                }
5209                return columnAtPoint(trailingPoint);
5210            }
5211
5212            /*
5213             * Returns the leading edge ("beginning") of the given Rectangle.
5214             * For VERTICAL, this is the top, for left-to-right, the left side, and for
5215             * right-to-left, the right side.
5216             */
5217            private int leadingEdge(Rectangle rect, int orientation) {
5218                if (orientation == SwingConstants.VERTICAL) {
5219                    return rect.y;
5220                } else if (getComponentOrientation().isLeftToRight()) {
5221                    return rect.x;
5222                } else { // Horizontal, right-to-left
5223                    return rect.x + rect.width;
5224                }
5225            }
5226
5227            /*
5228             * Returns the trailing edge ("end") of the given Rectangle.
5229             * For VERTICAL, this is the bottom, for left-to-right, the right side, and
5230             * for right-to-left, the left side.
5231             */
5232            private int trailingEdge(Rectangle rect, int orientation) {
5233                if (orientation == SwingConstants.VERTICAL) {
5234                    return rect.y + rect.height;
5235                } else if (getComponentOrientation().isLeftToRight()) {
5236                    return rect.x + rect.width;
5237                } else { // Horizontal, right-to-left
5238                    return rect.x;
5239                }
5240            }
5241
5242            /**
5243             * Returns false if <code>autoResizeMode</code> is set to
5244             * <code>AUTO_RESIZE_OFF</code>, which indicates that the
5245             * width of the viewport does not determine the width
5246             * of the table.  Otherwise returns true.
5247             *
5248             * @return false if <code>autoResizeMode</code> is set
5249             *   to <code>AUTO_RESIZE_OFF</code>, otherwise returns true
5250             * @see Scrollable#getScrollableTracksViewportWidth
5251             */
5252            public boolean getScrollableTracksViewportWidth() {
5253                return !(autoResizeMode == AUTO_RESIZE_OFF);
5254            }
5255
5256            /**
5257             * Returns {@code false} to indicate that the height of the viewport does
5258             * not determine the height of the table, unless
5259             * {@code getFillsViewportHeight} is {@code true} and the preferred height
5260             * of the table is smaller than the viewport's height.
5261             *
5262             * @return {@code false} unless {@code getFillsViewportHeight} is
5263             *         {@code true} and the table needs to be stretched to fill
5264             *         the viewport
5265             * @see Scrollable#getScrollableTracksViewportHeight
5266             * @see #setFillsViewportHeight
5267             * @see #getFillsViewportHeight
5268             */
5269            public boolean getScrollableTracksViewportHeight() {
5270                return getFillsViewportHeight()
5271                        && getParent() instanceof  JViewport
5272                        && (((JViewport) getParent()).getHeight() > getPreferredSize().height);
5273            }
5274
5275            /**
5276             * Sets whether or not this table is always made large enough
5277             * to fill the height of an enclosing viewport. If the preferred
5278             * height of the table is smaller than the viewport, then the table
5279             * will be stretched to fill the viewport. In other words, this
5280             * ensures the table is never smaller than the viewport.
5281             * The default for this property is {@code false}.
5282             *
5283             * @param fillsViewportHeight whether or not this table is always
5284             *        made large enough to fill the height of an enclosing
5285             *        viewport
5286             * @see #getFillsViewportHeight
5287             * @see #getScrollableTracksViewportHeight
5288             * @since 1.6
5289             * @beaninfo
5290             *      bound: true
5291             *      description: Whether or not this table is always made large enough
5292             *                   to fill the height of an enclosing viewport
5293             */
5294            public void setFillsViewportHeight(boolean fillsViewportHeight) {
5295                boolean old = this .fillsViewportHeight;
5296                this .fillsViewportHeight = fillsViewportHeight;
5297                resizeAndRepaint();
5298                firePropertyChange("fillsViewportHeight", old,
5299                        fillsViewportHeight);
5300            }
5301
5302            /**
5303             * Returns whether or not this table is always made large enough
5304             * to fill the height of an enclosing viewport.
5305             *
5306             * @return whether or not this table is always made large enough
5307             *         to fill the height of an enclosing viewport
5308             * @see #setFillsViewportHeight
5309             * @since 1.6
5310             */
5311            public boolean getFillsViewportHeight() {
5312                return fillsViewportHeight;
5313            }
5314
5315            //
5316            // Protected Methods
5317            //
5318
5319            protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
5320                    int condition, boolean pressed) {
5321                boolean retValue = super .processKeyBinding(ks, e, condition,
5322                        pressed);
5323
5324                // Start editing when a key is typed. UI classes can disable this behavior
5325                // by setting the client property JTable.autoStartsEdit to Boolean.FALSE.
5326                if (!retValue
5327                        && condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
5328                        && isFocusOwner()
5329                        && !Boolean.FALSE
5330                                .equals((Boolean) getClientProperty("JTable.autoStartsEdit"))) {
5331                    // We do not have a binding for the event.
5332                    Component editorComponent = getEditorComponent();
5333                    if (editorComponent == null) {
5334                        // Only attempt to install the editor on a KEY_PRESSED,
5335                        if (e == null || e.getID() != KeyEvent.KEY_PRESSED) {
5336                            return false;
5337                        }
5338                        // Don't start when just a modifier is pressed
5339                        int code = e.getKeyCode();
5340                        if (code == KeyEvent.VK_SHIFT
5341                                || code == KeyEvent.VK_CONTROL
5342                                || code == KeyEvent.VK_ALT) {
5343                            return false;
5344                        }
5345                        // Try to install the editor
5346                        int leadRow = getSelectionModel()
5347                                .getLeadSelectionIndex();
5348                        int leadColumn = getColumnModel().getSelectionModel()
5349                                .getLeadSelectionIndex();
5350                        if (leadRow != -1 && leadColumn != -1 && !isEditing()) {
5351                            if (!editCellAt(leadRow, leadColumn, e)) {
5352                                return false;
5353                            }
5354                        }
5355                        editorComponent = getEditorComponent();
5356                        if (editorComponent == null) {
5357                            return false;
5358                        }
5359                    }
5360                    // If the editorComponent is a JComponent, pass the event to it.
5361                    if (editorComponent instanceof  JComponent) {
5362                        retValue = ((JComponent) editorComponent)
5363                                .processKeyBinding(ks, e, WHEN_FOCUSED, pressed);
5364                        // If we have started an editor as a result of the user
5365                        // pressing a key and the surrendersFocusOnKeystroke property
5366                        // is true, give the focus to the new editor.
5367                        if (getSurrendersFocusOnKeystroke()) {
5368                            editorComponent.requestFocus();
5369                        }
5370                    }
5371                }
5372                return retValue;
5373            }
5374
5375            private void setLazyValue(Hashtable h, Class c, String s) {
5376                h.put(c, new UIDefaults.ProxyLazyValue(s));
5377            }
5378
5379            private void setLazyRenderer(Class c, String s) {
5380                setLazyValue(defaultRenderersByColumnClass, c, s);
5381            }
5382
5383            /**
5384             * Creates default cell renderers for objects, numbers, doubles, dates,
5385             * booleans, and icons.
5386             * @see javax.swing.table.DefaultTableCellRenderer
5387             *
5388             */
5389            protected void createDefaultRenderers() {
5390                defaultRenderersByColumnClass = new UIDefaults(8, 0.75f);
5391
5392                // Objects
5393                setLazyRenderer(Object.class,
5394                        "javax.swing.table.DefaultTableCellRenderer$UIResource");
5395
5396                // Numbers
5397                setLazyRenderer(Number.class,
5398                        "javax.swing.JTable$NumberRenderer");
5399
5400                // Doubles and Floats
5401                setLazyRenderer(Float.class,
5402                        "javax.swing.JTable$DoubleRenderer");
5403                setLazyRenderer(Double.class,
5404                        "javax.swing.JTable$DoubleRenderer");
5405
5406                // Dates
5407                setLazyRenderer(Date.class, "javax.swing.JTable$DateRenderer");
5408
5409                // Icons and ImageIcons
5410                setLazyRenderer(Icon.class, "javax.swing.JTable$IconRenderer");
5411                setLazyRenderer(ImageIcon.class,
5412                        "javax.swing.JTable$IconRenderer");
5413
5414                // Booleans
5415                setLazyRenderer(Boolean.class,
5416                        "javax.swing.JTable$BooleanRenderer");
5417            }
5418
5419            /**
5420             * Default Renderers
5421             **/
5422            static class NumberRenderer extends
5423                    DefaultTableCellRenderer.UIResource {
5424                public NumberRenderer() {
5425                    super ();
5426                    setHorizontalAlignment(JLabel.RIGHT);
5427                }
5428            }
5429
5430            static class DoubleRenderer extends NumberRenderer {
5431                NumberFormat formatter;
5432
5433                public DoubleRenderer() {
5434                    super ();
5435                }
5436
5437                public void setValue(Object value) {
5438                    if (formatter == null) {
5439                        formatter = NumberFormat.getInstance();
5440                    }
5441                    setText((value == null) ? "" : formatter.format(value));
5442                }
5443            }
5444
5445            static class DateRenderer extends
5446                    DefaultTableCellRenderer.UIResource {
5447                DateFormat formatter;
5448
5449                public DateRenderer() {
5450                    super ();
5451                }
5452
5453                public void setValue(Object value) {
5454                    if (formatter == null) {
5455                        formatter = DateFormat.getDateInstance();
5456                    }
5457                    setText((value == null) ? "" : formatter.format(value));
5458                }
5459            }
5460
5461            static class IconRenderer extends
5462                    DefaultTableCellRenderer.UIResource {
5463                public IconRenderer() {
5464                    super ();
5465                    setHorizontalAlignment(JLabel.CENTER);
5466                }
5467
5468                public void setValue(Object value) {
5469                    setIcon((value instanceof  Icon) ? (Icon) value : null);
5470                }
5471            }
5472
5473            static class BooleanRenderer extends JCheckBox implements 
5474                    TableCellRenderer, UIResource {
5475                private static final Border noFocusBorder = new EmptyBorder(1,
5476                        1, 1, 1);
5477
5478                public BooleanRenderer() {
5479                    super ();
5480                    setHorizontalAlignment(JLabel.CENTER);
5481                    setBorderPainted(true);
5482                }
5483
5484                public Component getTableCellRendererComponent(JTable table,
5485                        Object value, boolean isSelected, boolean hasFocus,
5486                        int row, int column) {
5487                    if (isSelected) {
5488                        setForeground(table.getSelectionForeground());
5489                        super .setBackground(table.getSelectionBackground());
5490                    } else {
5491                        setForeground(table.getForeground());
5492                        setBackground(table.getBackground());
5493                    }
5494                    setSelected((value != null && ((Boolean) value)
5495                            .booleanValue()));
5496
5497                    if (hasFocus) {
5498                        setBorder(UIManager
5499                                .getBorder("Table.focusCellHighlightBorder"));
5500                    } else {
5501                        setBorder(noFocusBorder);
5502                    }
5503
5504                    return this ;
5505                }
5506            }
5507
5508            private void setLazyEditor(Class c, String s) {
5509                setLazyValue(defaultEditorsByColumnClass, c, s);
5510            }
5511
5512            /**
5513             * Creates default cell editors for objects, numbers, and boolean values.
5514             * @see DefaultCellEditor
5515             */
5516            protected void createDefaultEditors() {
5517                defaultEditorsByColumnClass = new UIDefaults(3, 0.75f);
5518
5519                // Objects
5520                setLazyEditor(Object.class, "javax.swing.JTable$GenericEditor");
5521
5522                // Numbers
5523                setLazyEditor(Number.class, "javax.swing.JTable$NumberEditor");
5524
5525                // Booleans
5526                setLazyEditor(Boolean.class, "javax.swing.JTable$BooleanEditor");
5527            }
5528
5529            /**
5530             * Default Editors
5531             */
5532            static class GenericEditor extends DefaultCellEditor {
5533
5534                Class[] argTypes = new Class[] { String.class };
5535                java.lang.reflect.Constructor constructor;
5536                Object value;
5537
5538                public GenericEditor() {
5539                    super (new JTextField());
5540                    getComponent().setName("Table.editor");
5541                }
5542
5543                public boolean stopCellEditing() {
5544                    String s = (String) super .getCellEditorValue();
5545                    // Here we are dealing with the case where a user
5546                    // has deleted the string value in a cell, possibly
5547                    // after a failed validation. Return null, so that
5548                    // they have the option to replace the value with
5549                    // null or use escape to restore the original.
5550                    // For Strings, return "" for backward compatibility.
5551                    if ("".equals(s)) {
5552                        if (constructor.getDeclaringClass() == String.class) {
5553                            value = s;
5554                        }
5555                        super .stopCellEditing();
5556                    }
5557
5558                    try {
5559                        value = constructor.newInstance(new Object[] { s });
5560                    } catch (Exception e) {
5561                        ((JComponent) getComponent()).setBorder(new LineBorder(
5562                                Color.red));
5563                        return false;
5564                    }
5565                    return super .stopCellEditing();
5566                }
5567
5568                public Component getTableCellEditorComponent(JTable table,
5569                        Object value, boolean isSelected, int row, int column) {
5570                    this .value = null;
5571                    ((JComponent) getComponent()).setBorder(new LineBorder(
5572                            Color.black));
5573                    try {
5574                        Class type = table.getColumnClass(column);
5575                        // Since our obligation is to produce a value which is
5576                        // assignable for the required type it is OK to use the
5577                        // String constructor for columns which are declared
5578                        // to contain Objects. A String is an Object.
5579                        if (type == Object.class) {
5580                            type = String.class;
5581                        }
5582                        constructor = type.getConstructor(argTypes);
5583                    } catch (Exception e) {
5584                        return null;
5585                    }
5586                    return super .getTableCellEditorComponent(table, value,
5587                            isSelected, row, column);
5588                }
5589
5590                public Object getCellEditorValue() {
5591                    return value;
5592                }
5593            }
5594
5595            static class NumberEditor extends GenericEditor {
5596
5597                public NumberEditor() {
5598                    ((JTextField) getComponent())
5599                            .setHorizontalAlignment(JTextField.RIGHT);
5600                }
5601            }
5602
5603            static class BooleanEditor extends DefaultCellEditor {
5604                public BooleanEditor() {
5605                    super (new JCheckBox());
5606                    JCheckBox checkBox = (JCheckBox) getComponent();
5607                    checkBox.setHorizontalAlignment(JCheckBox.CENTER);
5608                }
5609            }
5610
5611            /**
5612             * Initializes table properties to their default values.
5613             */
5614            protected void initializeLocalVars() {
5615                updateSelectionOnSort = true;
5616                setOpaque(true);
5617                createDefaultRenderers();
5618                createDefaultEditors();
5619
5620                setTableHeader(createDefaultTableHeader());
5621
5622                setShowGrid(true);
5623                setAutoResizeMode(AUTO_RESIZE_SUBSEQUENT_COLUMNS);
5624                setRowHeight(16);
5625                isRowHeightSet = false;
5626                setRowMargin(1);
5627                setRowSelectionAllowed(true);
5628                setCellEditor(null);
5629                setEditingColumn(-1);
5630                setEditingRow(-1);
5631                setSurrendersFocusOnKeystroke(false);
5632                setPreferredScrollableViewportSize(new Dimension(450, 400));
5633
5634                // I'm registered to do tool tips so we can draw tips for the renderers
5635                ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
5636                toolTipManager.registerComponent(this );
5637
5638                setAutoscrolls(true);
5639            }
5640
5641            /**
5642             * Returns the default table model object, which is
5643             * a <code>DefaultTableModel</code>.  A subclass can override this
5644             * method to return a different table model object.
5645             *
5646             * @return the default table model object
5647             * @see javax.swing.table.DefaultTableModel
5648             */
5649            protected TableModel createDefaultDataModel() {
5650                return new DefaultTableModel();
5651            }
5652
5653            /**
5654             * Returns the default column model object, which is
5655             * a <code>DefaultTableColumnModel</code>.  A subclass can override this
5656             * method to return a different column model object.
5657             *
5658             * @return the default column model object
5659             * @see javax.swing.table.DefaultTableColumnModel
5660             */
5661            protected TableColumnModel createDefaultColumnModel() {
5662                return new DefaultTableColumnModel();
5663            }
5664
5665            /**
5666             * Returns the default selection model object, which is
5667             * a <code>DefaultListSelectionModel</code>.  A subclass can override this
5668             * method to return a different selection model object.
5669             *
5670             * @return the default selection model object
5671             * @see javax.swing.DefaultListSelectionModel
5672             */
5673            protected ListSelectionModel createDefaultSelectionModel() {
5674                return new DefaultListSelectionModel();
5675            }
5676
5677            /**
5678             * Returns the default table header object, which is
5679             * a <code>JTableHeader</code>.  A subclass can override this
5680             * method to return a different table header object.
5681             *
5682             * @return the default table header object
5683             * @see javax.swing.table.JTableHeader
5684             */
5685            protected JTableHeader createDefaultTableHeader() {
5686                return new JTableHeader(columnModel);
5687            }
5688
5689            /**
5690             * Equivalent to <code>revalidate</code> followed by <code>repaint</code>.
5691             */
5692            protected void resizeAndRepaint() {
5693                revalidate();
5694                repaint();
5695            }
5696
5697            /**
5698             * Returns the active cell editor, which is {@code null} if the table
5699             * is not currently editing.
5700             *
5701             * @return the {@code TableCellEditor} that does the editing,
5702             *         or {@code null} if the table is not currently editing.
5703             * @see #cellEditor
5704             * @see #getCellEditor(int, int)
5705             */
5706            public TableCellEditor getCellEditor() {
5707                return cellEditor;
5708            }
5709
5710            /**
5711             * Sets the active cell editor.
5712             *
5713             * @param anEditor the active cell editor
5714             * @see #cellEditor
5715             * @beaninfo
5716             *  bound: true
5717             *  description: The table's active cell editor.
5718             */
5719            public void setCellEditor(TableCellEditor anEditor) {
5720                TableCellEditor oldEditor = cellEditor;
5721                cellEditor = anEditor;
5722                firePropertyChange("tableCellEditor", oldEditor, anEditor);
5723            }
5724
5725            /**
5726             * Sets the <code>editingColumn</code> variable.
5727             * @param aColumn  the column of the cell to be edited
5728             *
5729             * @see #editingColumn
5730             */
5731            public void setEditingColumn(int aColumn) {
5732                editingColumn = aColumn;
5733            }
5734
5735            /**
5736             * Sets the <code>editingRow</code> variable.
5737             * @param aRow  the row of the cell to be edited
5738             *
5739             * @see #editingRow
5740             */
5741            public void setEditingRow(int aRow) {
5742                editingRow = aRow;
5743            }
5744
5745            /**
5746             * Returns an appropriate renderer for the cell specified by this row and
5747             * column. If the <code>TableColumn</code> for this column has a non-null
5748             * renderer, returns that.  If not, finds the class of the data in
5749             * this column (using <code>getColumnClass</code>)
5750             * and returns the default renderer for this type of data.
5751             * <p>
5752             * <b>Note:</b>
5753             * Throughout the table package, the internal implementations always
5754             * use this method to provide renderers so that this default behavior
5755             * can be safely overridden by a subclass.
5756             *
5757             * @param row       the row of the cell to render, where 0 is the first row
5758             * @param column    the column of the cell to render,
5759             *			where 0 is the first column
5760             * @return the assigned renderer; if <code>null</code>
5761             *			returns the default renderer
5762             * 			for this type of object
5763             * @see javax.swing.table.DefaultTableCellRenderer
5764             * @see javax.swing.table.TableColumn#setCellRenderer
5765             * @see #setDefaultRenderer
5766             */
5767            public TableCellRenderer getCellRenderer(int row, int column) {
5768                TableColumn tableColumn = getColumnModel().getColumn(column);
5769                TableCellRenderer renderer = tableColumn.getCellRenderer();
5770                if (renderer == null) {
5771                    renderer = getDefaultRenderer(getColumnClass(column));
5772                }
5773                return renderer;
5774            }
5775
5776            /**
5777             * Prepares the renderer by querying the data model for the
5778             * value and selection state
5779             * of the cell at <code>row</code>, <code>column</code>.
5780             * Returns the component (may be a <code>Component</code>
5781             * or a <code>JComponent</code>) under the event location.
5782             * <p>
5783             * During a printing operation, this method will configure the
5784             * renderer without indicating selection or focus, to prevent
5785             * them from appearing in the printed output. To do other
5786             * customizations based on whether or not the table is being
5787             * printed, you can check the value of
5788             * {@link javax.swing.JComponent#isPaintingForPrint()}, either here
5789             * or within custom renderers.
5790             * <p>
5791             * <b>Note:</b>
5792             * Throughout the table package, the internal implementations always
5793             * use this method to prepare renderers so that this default behavior
5794             * can be safely overridden by a subclass.
5795             *
5796             * @param renderer  the <code>TableCellRenderer</code> to prepare
5797             * @param row       the row of the cell to render, where 0 is the first row
5798             * @param column    the column of the cell to render,
5799             *			where 0 is the first column
5800             * @return          the <code>Component</code> under the event location
5801             */
5802            public Component prepareRenderer(TableCellRenderer renderer,
5803                    int row, int column) {
5804                Object value = getValueAt(row, column);
5805
5806                boolean isSelected = false;
5807                boolean hasFocus = false;
5808
5809                // Only indicate the selection and focused cell if not printing
5810                if (!isPaintingForPrint()) {
5811                    isSelected = isCellSelected(row, column);
5812
5813                    boolean rowIsLead = (selectionModel.getLeadSelectionIndex() == row);
5814                    boolean colIsLead = (columnModel.getSelectionModel()
5815                            .getLeadSelectionIndex() == column);
5816
5817                    hasFocus = (rowIsLead && colIsLead) && isFocusOwner();
5818                }
5819
5820                return renderer.getTableCellRendererComponent(this , value,
5821                        isSelected, hasFocus, row, column);
5822            }
5823
5824            /**
5825             * Returns an appropriate editor for the cell specified by
5826             * <code>row</code> and <code>column</code>. If the
5827             * <code>TableColumn</code> for this column has a non-null editor,
5828             * returns that.  If not, finds the class of the data in this
5829             * column (using <code>getColumnClass</code>)
5830             * and returns the default editor for this type of data.
5831             * <p>
5832             * <b>Note:</b>
5833             * Throughout the table package, the internal implementations always
5834             * use this method to provide editors so that this default behavior
5835             * can be safely overridden by a subclass.
5836             *
5837             * @param row       the row of the cell to edit, where 0 is the first row
5838             * @param column    the column of the cell to edit,
5839             *			where 0 is the first column
5840             * @return          the editor for this cell;
5841             *			if <code>null</code> return the default editor for
5842             *  		this type of cell
5843             * @see DefaultCellEditor
5844             */
5845            public TableCellEditor getCellEditor(int row, int column) {
5846                TableColumn tableColumn = getColumnModel().getColumn(column);
5847                TableCellEditor editor = tableColumn.getCellEditor();
5848                if (editor == null) {
5849                    editor = getDefaultEditor(getColumnClass(column));
5850                }
5851                return editor;
5852            }
5853
5854            /**
5855             * Prepares the editor by querying the data model for the value and
5856             * selection state of the cell at <code>row</code>, <code>column</code>.
5857             * <p>
5858             * <b>Note:</b>
5859             * Throughout the table package, the internal implementations always
5860             * use this method to prepare editors so that this default behavior
5861             * can be safely overridden by a subclass.
5862             *
5863             * @param editor  the <code>TableCellEditor</code> to set up
5864             * @param row     the row of the cell to edit,
5865             *		      where 0 is the first row
5866             * @param column  the column of the cell to edit,
5867             *		      where 0 is the first column
5868             * @return the <code>Component</code> being edited
5869             */
5870            public Component prepareEditor(TableCellEditor editor, int row,
5871                    int column) {
5872                Object value = getValueAt(row, column);
5873                boolean isSelected = isCellSelected(row, column);
5874                Component comp = editor.getTableCellEditorComponent(this ,
5875                        value, isSelected, row, column);
5876                if (comp instanceof  JComponent) {
5877                    JComponent jComp = (JComponent) comp;
5878                    if (jComp.getNextFocusableComponent() == null) {
5879                        jComp.setNextFocusableComponent(this );
5880                    }
5881                }
5882                return comp;
5883            }
5884
5885            /**
5886             * Discards the editor object and frees the real estate it used for
5887             * cell rendering.
5888             */
5889            public void removeEditor() {
5890                KeyboardFocusManager.getCurrentKeyboardFocusManager()
5891                        .removePropertyChangeListener("permanentFocusOwner",
5892                                editorRemover);
5893                editorRemover = null;
5894
5895                TableCellEditor editor = getCellEditor();
5896                if (editor != null) {
5897                    editor.removeCellEditorListener(this );
5898                    if (editorComp != null) {
5899                        Component focusOwner = KeyboardFocusManager
5900                                .getCurrentKeyboardFocusManager()
5901                                .getFocusOwner();
5902                        boolean isFocusOwnerInTheTable = focusOwner != null ? SwingUtilities
5903                                .isDescendingFrom(focusOwner, this )
5904                                : false;
5905                        remove(editorComp);
5906                        if (isFocusOwnerInTheTable) {
5907                            requestFocusInWindow();
5908                        }
5909                    }
5910
5911                    Rectangle cellRect = getCellRect(editingRow, editingColumn,
5912                            false);
5913
5914                    setCellEditor(null);
5915                    setEditingColumn(-1);
5916                    setEditingRow(-1);
5917                    editorComp = null;
5918
5919                    repaint(cellRect);
5920                }
5921            }
5922
5923            //
5924            // Serialization
5925            //
5926
5927            /**
5928             * See readObject() and writeObject() in JComponent for more
5929             * information about serialization in Swing.
5930             */
5931            private void writeObject(ObjectOutputStream s) throws IOException {
5932                s.defaultWriteObject();
5933                if (getUIClassID().equals(uiClassID)) {
5934                    byte count = JComponent.getWriteObjCounter(this );
5935                    JComponent.setWriteObjCounter(this , --count);
5936                    if (count == 0 && ui != null) {
5937                        ui.installUI(this );
5938                    }
5939                }
5940            }
5941
5942            private void readObject(ObjectInputStream s) throws IOException,
5943                    ClassNotFoundException {
5944                s.defaultReadObject();
5945                if ((ui != null) && (getUIClassID().equals(uiClassID))) {
5946                    ui.installUI(this );
5947                }
5948                createDefaultRenderers();
5949                createDefaultEditors();
5950
5951                // If ToolTipText != null, then the tooltip has already been
5952                // registered by JComponent.readObject() and we don't want
5953                // to re-register here
5954                if (getToolTipText() == null) {
5955                    ToolTipManager.sharedInstance().registerComponent(this );
5956                }
5957            }
5958
5959            /* Called from the JComponent's EnableSerializationFocusListener to
5960             * do any Swing-specific pre-serialization configuration.
5961             */
5962            void compWriteObjectNotify() {
5963                super .compWriteObjectNotify();
5964                // If ToolTipText != null, then the tooltip has already been
5965                // unregistered by JComponent.compWriteObjectNotify()
5966                if (getToolTipText() == null) {
5967                    ToolTipManager.sharedInstance().unregisterComponent(this );
5968                }
5969            }
5970
5971            /**
5972             * Returns a string representation of this table. This method
5973             * is intended to be used only for debugging purposes, and the
5974             * content and format of the returned string may vary between
5975             * implementations. The returned string may be empty but may not
5976             * be <code>null</code>.
5977             *
5978             * @return  a string representation of this table
5979             */
5980            protected String paramString() {
5981                String gridColorString = (gridColor != null ? gridColor
5982                        .toString() : "");
5983                String showHorizontalLinesString = (showHorizontalLines ? "true"
5984                        : "false");
5985                String showVerticalLinesString = (showVerticalLines ? "true"
5986                        : "false");
5987                String autoResizeModeString;
5988                if (autoResizeMode == AUTO_RESIZE_OFF) {
5989                    autoResizeModeString = "AUTO_RESIZE_OFF";
5990                } else if (autoResizeMode == AUTO_RESIZE_NEXT_COLUMN) {
5991                    autoResizeModeString = "AUTO_RESIZE_NEXT_COLUMN";
5992                } else if (autoResizeMode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) {
5993                    autoResizeModeString = "AUTO_RESIZE_SUBSEQUENT_COLUMNS";
5994                } else if (autoResizeMode == AUTO_RESIZE_LAST_COLUMN) {
5995                    autoResizeModeString = "AUTO_RESIZE_LAST_COLUMN";
5996                } else if (autoResizeMode == AUTO_RESIZE_ALL_COLUMNS) {
5997                    autoResizeModeString = "AUTO_RESIZE_ALL_COLUMNS";
5998                } else
5999                    autoResizeModeString = "";
6000                String autoCreateColumnsFromModelString = (autoCreateColumnsFromModel ? "true"
6001                        : "false");
6002                String preferredViewportSizeString = (preferredViewportSize != null ? preferredViewportSize
6003                        .toString()
6004                        : "");
6005                String rowSelectionAllowedString = (rowSelectionAllowed ? "true"
6006                        : "false");
6007                String cellSelectionEnabledString = (cellSelectionEnabled ? "true"
6008                        : "false");
6009                String selectionForegroundString = (selectionForeground != null ? selectionForeground
6010                        .toString()
6011                        : "");
6012                String selectionBackgroundString = (selectionBackground != null ? selectionBackground
6013                        .toString()
6014                        : "");
6015
6016                return super .paramString() + ",autoCreateColumnsFromModel="
6017                        + autoCreateColumnsFromModelString + ",autoResizeMode="
6018                        + autoResizeModeString + ",cellSelectionEnabled="
6019                        + cellSelectionEnabledString + ",editingColumn="
6020                        + editingColumn + ",editingRow=" + editingRow
6021                        + ",gridColor=" + gridColorString
6022                        + ",preferredViewportSize="
6023                        + preferredViewportSizeString + ",rowHeight="
6024                        + rowHeight + ",rowMargin=" + rowMargin
6025                        + ",rowSelectionAllowed=" + rowSelectionAllowedString
6026                        + ",selectionBackground=" + selectionBackgroundString
6027                        + ",selectionForeground=" + selectionForegroundString
6028                        + ",showHorizontalLines=" + showHorizontalLinesString
6029                        + ",showVerticalLines=" + showVerticalLinesString;
6030            }
6031
6032            // This class tracks changes in the keyboard focus state. It is used
6033            // when the JTable is editing to determine when to cancel the edit.
6034            // If focus switches to a component outside of the jtable, but in the
6035            // same window, this will cancel editing.
6036            class CellEditorRemover implements  PropertyChangeListener {
6037                KeyboardFocusManager focusManager;
6038
6039                public CellEditorRemover(KeyboardFocusManager fm) {
6040                    this .focusManager = fm;
6041                }
6042
6043                public void propertyChange(PropertyChangeEvent ev) {
6044                    if (!isEditing()
6045                            || getClientProperty("terminateEditOnFocusLost") != Boolean.TRUE) {
6046                        return;
6047                    }
6048
6049                    Component c = focusManager.getPermanentFocusOwner();
6050                    while (c != null) {
6051                        if (c == JTable.this ) {
6052                            // focus remains inside the table
6053                            return;
6054                        } else if ((c instanceof  Window)
6055                                || (c instanceof  Applet && c.getParent() == null)) {
6056                            if (c == SwingUtilities.getRoot(JTable.this )) {
6057                                if (!getCellEditor().stopCellEditing()) {
6058                                    getCellEditor().cancelCellEditing();
6059                                }
6060                            }
6061                            break;
6062                        }
6063                        c = c.getParent();
6064                    }
6065                }
6066            }
6067
6068            /////////////////
6069            // Printing Support
6070            /////////////////
6071
6072            /**
6073             * A convenience method that displays a printing dialog, and then prints
6074             * this <code>JTable</code> in mode <code>PrintMode.FIT_WIDTH</code>,
6075             * with no header or footer text. A modal progress dialog, with an abort
6076             * option, will be shown for the duration of printing.
6077             * <p>
6078             * Note: In headless mode, no dialogs are shown and printing
6079             * occurs on the default printer.
6080             *
6081             * @return true, unless printing is cancelled by the user
6082             * @throws SecurityException if this thread is not allowed to
6083             *                           initiate a print job request
6084             * @throws PrinterException if an error in the print system causes the job
6085             *                          to be aborted
6086             * @see #print(JTable.PrintMode, MessageFormat, MessageFormat,
6087             *             boolean, PrintRequestAttributeSet, boolean, PrintService)
6088             * @see #getPrintable
6089             *
6090             * @since 1.5
6091             */
6092            public boolean print() throws PrinterException {
6093
6094                return print(PrintMode.FIT_WIDTH);
6095            }
6096
6097            /**
6098             * A convenience method that displays a printing dialog, and then prints
6099             * this <code>JTable</code> in the given printing mode,
6100             * with no header or footer text. A modal progress dialog, with an abort
6101             * option, will be shown for the duration of printing.
6102             * <p>
6103             * Note: In headless mode, no dialogs are shown and printing
6104             * occurs on the default printer.
6105             *
6106             * @param  printMode        the printing mode that the printable should use
6107             * @return true, unless printing is cancelled by the user
6108             * @throws SecurityException if this thread is not allowed to
6109             *                           initiate a print job request
6110             * @throws PrinterException if an error in the print system causes the job
6111             *                          to be aborted
6112             * @see #print(JTable.PrintMode, MessageFormat, MessageFormat,
6113             *             boolean, PrintRequestAttributeSet, boolean, PrintService)
6114             * @see #getPrintable
6115             *
6116             * @since 1.5
6117             */
6118            public boolean print(PrintMode printMode) throws PrinterException {
6119
6120                return print(printMode, null, null);
6121            }
6122
6123            /**
6124             * A convenience method that displays a printing dialog, and then prints
6125             * this <code>JTable</code> in the given printing mode,
6126             * with the specified header and footer text. A modal progress dialog,
6127             * with an abort option, will be shown for the duration of printing.
6128             * <p>
6129             * Note: In headless mode, no dialogs are shown and printing
6130             * occurs on the default printer.
6131             *
6132             * @param  printMode        the printing mode that the printable should use
6133             * @param  headerFormat     a <code>MessageFormat</code> specifying the text
6134             *                          to be used in printing a header,
6135             *                          or null for none
6136             * @param  footerFormat     a <code>MessageFormat</code> specifying the text
6137             *                          to be used in printing a footer,
6138             *                          or null for none
6139             * @return true, unless printing is cancelled by the user
6140             * @throws SecurityException if this thread is not allowed to
6141             *                           initiate a print job request
6142             * @throws PrinterException if an error in the print system causes the job
6143             *                          to be aborted
6144             * @see #print(JTable.PrintMode, MessageFormat, MessageFormat,
6145             *             boolean, PrintRequestAttributeSet, boolean, PrintService)
6146             * @see #getPrintable
6147             *
6148             * @since 1.5
6149             */
6150            public boolean print(PrintMode printMode,
6151                    MessageFormat headerFormat, MessageFormat footerFormat)
6152                    throws PrinterException {
6153
6154                boolean showDialogs = !GraphicsEnvironment.isHeadless();
6155                return print(printMode, headerFormat, footerFormat,
6156                        showDialogs, null, showDialogs);
6157            }
6158
6159            /**
6160             * Prints this table, as specified by the fully featured
6161             * {@link #print(JTable.PrintMode, MessageFormat, MessageFormat,
6162             * boolean, PrintRequestAttributeSet, boolean, PrintService) print}
6163             * method, with the default printer specified as the print service.
6164             *
6165             * @param  printMode        the printing mode that the printable should use
6166             * @param  headerFormat     a <code>MessageFormat</code> specifying the text
6167             *                          to be used in printing a header,
6168             *                          or <code>null</code> for none
6169             * @param  footerFormat     a <code>MessageFormat</code> specifying the text
6170             *                          to be used in printing a footer,
6171             *                          or <code>null</code> for none
6172             * @param  showPrintDialog  whether or not to display a print dialog
6173             * @param  attr             a <code>PrintRequestAttributeSet</code>
6174             *                          specifying any printing attributes,
6175             *                          or <code>null</code> for none
6176             * @param  interactive      whether or not to print in an interactive mode
6177             * @return true, unless printing is cancelled by the user
6178             * @throws HeadlessException if the method is asked to show a printing
6179             *                           dialog or run interactively, and
6180             *                           <code>GraphicsEnvironment.isHeadless</code>
6181             *                           returns <code>true</code>
6182             * @throws SecurityException if this thread is not allowed to
6183             *                           initiate a print job request
6184             * @throws PrinterException if an error in the print system causes the job
6185             *                          to be aborted
6186             * @see #print(JTable.PrintMode, MessageFormat, MessageFormat,
6187             *             boolean, PrintRequestAttributeSet, boolean, PrintService)
6188             * @see #getPrintable
6189             *
6190             * @since 1.5
6191             */
6192            public boolean print(PrintMode printMode,
6193                    MessageFormat headerFormat, MessageFormat footerFormat,
6194                    boolean showPrintDialog, PrintRequestAttributeSet attr,
6195                    boolean interactive) throws PrinterException,
6196                    HeadlessException {
6197
6198                return print(printMode, headerFormat, footerFormat,
6199                        showPrintDialog, attr, interactive, null);
6200            }
6201
6202            /**
6203             * Prints this <code>JTable</code>. Takes steps that the majority of
6204             * developers would take in order to print a <code>JTable</code>.
6205             * In short, it prepares the table, calls <code>getPrintable</code> to
6206             * fetch an appropriate <code>Printable</code>, and then sends it to the
6207             * printer.
6208             * <p>
6209             * A <code>boolean</code> parameter allows you to specify whether or not
6210             * a printing dialog is displayed to the user. When it is, the user may
6211             * use the dialog to change the destination printer or printing attributes,
6212             * or even to cancel the print. Another two parameters allow for a
6213             * <code>PrintService</code> and printing attributes to be specified.
6214             * These parameters can be used either to provide initial values for the
6215             * print dialog, or to specify values when the dialog is not shown.
6216             * <p>
6217             * A second <code>boolean</code> parameter allows you to specify whether
6218             * or not to perform printing in an interactive mode. If <code>true</code>,
6219             * a modal progress dialog, with an abort option, is displayed for the
6220             * duration of printing . This dialog also prevents any user action which
6221             * may affect the table. However, it can not prevent the table from being
6222             * modified by code (for example, another thread that posts updates using
6223             * <code>SwingUtilities.invokeLater</code>). It is therefore the
6224             * responsibility of the developer to ensure that no other code modifies
6225             * the table in any way during printing (invalid modifications include
6226             * changes in: size, renderers, or underlying data). Printing behavior is
6227             * undefined when the table is changed during printing.
6228             * <p>
6229             * If <code>false</code> is specified for this parameter, no dialog will
6230             * be displayed and printing will begin immediately on the event-dispatch
6231             * thread. This blocks any other events, including repaints, from being
6232             * processed until printing is complete. Although this effectively prevents
6233             * the table from being changed, it doesn't provide a good user experience.
6234             * For this reason, specifying <code>false</code> is only recommended when
6235             * printing from an application with no visible GUI.
6236             * <p>
6237             * Note: Attempting to show the printing dialog or run interactively, while
6238             * in headless mode, will result in a <code>HeadlessException</code>.
6239             * <p>
6240             * Before fetching the printable, this method will gracefully terminate
6241             * editing, if necessary, to prevent an editor from showing in the printed
6242             * result. Additionally, <code>JTable</code> will prepare its renderers
6243             * during printing such that selection and focus are not indicated.
6244             * As far as customizing further how the table looks in the printout,
6245             * developers can provide custom renderers or paint code that conditionalize
6246             * on the value of {@link javax.swing.JComponent#isPaintingForPrint()}.
6247             * <p>
6248             * See {@link #getPrintable} for more description on how the table is
6249             * printed. 
6250             *
6251             * @param  printMode        the printing mode that the printable should use
6252             * @param  headerFormat     a <code>MessageFormat</code> specifying the text
6253             *                          to be used in printing a header,
6254             *                          or <code>null</code> for none
6255             * @param  footerFormat     a <code>MessageFormat</code> specifying the text
6256             *                          to be used in printing a footer,
6257             *                          or <code>null</code> for none
6258             * @param  showPrintDialog  whether or not to display a print dialog
6259             * @param  attr             a <code>PrintRequestAttributeSet</code>
6260             *                          specifying any printing attributes,
6261             *                          or <code>null</code> for none
6262             * @param  interactive      whether or not to print in an interactive mode
6263             * @param  service          the destination <code>PrintService</code>,
6264             *                          or <code>null</code> to use the default printer
6265             * @return true, unless printing is cancelled by the user
6266             * @throws HeadlessException if the method is asked to show a printing
6267             *                           dialog or run interactively, and
6268             *                           <code>GraphicsEnvironment.isHeadless</code>
6269             *                           returns <code>true</code>
6270             * @throws  SecurityException if a security manager exists and its
6271             *          {@link java.lang.SecurityManager#checkPrintJobAccess}
6272             *          method disallows this thread from creating a print job request
6273             * @throws PrinterException if an error in the print system causes the job
6274             *                          to be aborted
6275             * @see #getPrintable
6276             * @see java.awt.GraphicsEnvironment#isHeadless
6277             *
6278             * @since 1.6
6279             */
6280            public boolean print(PrintMode printMode,
6281                    MessageFormat headerFormat, MessageFormat footerFormat,
6282                    boolean showPrintDialog, PrintRequestAttributeSet attr,
6283                    boolean interactive, PrintService service)
6284                    throws PrinterException, HeadlessException {
6285
6286                // complain early if an invalid parameter is specified for headless mode
6287                boolean isHeadless = GraphicsEnvironment.isHeadless();
6288                if (isHeadless) {
6289                    if (showPrintDialog) {
6290                        throw new HeadlessException("Can't show print dialog.");
6291                    }
6292
6293                    if (interactive) {
6294                        throw new HeadlessException("Can't run interactively.");
6295                    }
6296                }
6297
6298                // Get a PrinterJob.
6299                // Do this before anything with side-effects since it may throw a
6300                // security exception - in which case we don't want to do anything else.
6301                final PrinterJob job = PrinterJob.getPrinterJob();
6302
6303                if (isEditing()) {
6304                    // try to stop cell editing, and failing that, cancel it
6305                    if (!getCellEditor().stopCellEditing()) {
6306                        getCellEditor().cancelCellEditing();
6307                    }
6308                }
6309
6310                if (attr == null) {
6311                    attr = new HashPrintRequestAttributeSet();
6312                }
6313
6314                final PrintingStatus printingStatus;
6315
6316                // fetch the Printable 
6317                Printable printable = getPrintable(printMode, headerFormat,
6318                        footerFormat);
6319
6320                if (interactive) {
6321                    // wrap the Printable so that we can print on another thread
6322                    printable = new ThreadSafePrintable(printable);
6323                    printingStatus = PrintingStatus.createPrintingStatus(this ,
6324                            job);
6325                    printable = printingStatus
6326                            .createNotificationPrintable(printable);
6327                } else {
6328                    // to please compiler
6329                    printingStatus = null;
6330                }
6331
6332                // set the printable on the PrinterJob 
6333                job.setPrintable(printable);
6334
6335                // if specified, set the PrintService on the PrinterJob
6336                if (service != null) {
6337                    job.setPrintService(service);
6338                }
6339
6340                // if requested, show the print dialog
6341                if (showPrintDialog && !job.printDialog(attr)) {
6342                    // the user cancelled the print dialog
6343                    return false;
6344                }
6345
6346                // if not interactive, just print on this thread (no dialog)
6347                if (!interactive) {
6348                    // do the printing
6349                    job.print(attr);
6350
6351                    // we're done
6352                    return true;
6353                }
6354
6355                // make sure this is clear since we'll check it after
6356                printError = null;
6357
6358                // to synchronize on
6359                final Object lock = new Object();
6360
6361                // copied so we can access from the inner class
6362                final PrintRequestAttributeSet copyAttr = attr;
6363
6364                // this runnable will be used to do the printing
6365                // (and save any throwables) on another thread
6366                Runnable runnable = new Runnable() {
6367                    public void run() {
6368                        try {
6369                            // do the printing
6370                            job.print(copyAttr);
6371                        } catch (Throwable t) {
6372                            // save any Throwable to be rethrown
6373                            synchronized (lock) {
6374                                printError = t;
6375                            }
6376                        } finally {
6377                            // we're finished - hide the dialog
6378                            printingStatus.dispose();
6379                        }
6380                    }
6381                };
6382
6383                // start printing on another thread
6384                Thread th = new Thread(runnable);
6385                th.start();
6386
6387                printingStatus.showModal(true);
6388
6389                // look for any error that the printing may have generated
6390                Throwable pe;
6391                synchronized (lock) {
6392                    pe = printError;
6393                    printError = null;
6394                }
6395
6396                // check the type of error and handle it
6397                if (pe != null) {
6398                    // a subclass of PrinterException meaning the job was aborted,
6399                    // in this case, by the user
6400                    if (pe instanceof  PrinterAbortException) {
6401                        return false;
6402                    } else if (pe instanceof  PrinterException) {
6403                        throw (PrinterException) pe;
6404                    } else if (pe instanceof  RuntimeException) {
6405                        throw (RuntimeException) pe;
6406                    } else if (pe instanceof  Error) {
6407                        throw (Error) pe;
6408                    }
6409
6410                    // can not happen
6411                    throw new AssertionError(pe);
6412                }
6413
6414                return true;
6415            }
6416
6417            /**
6418             * Return a <code>Printable</code> for use in printing this JTable.
6419             * <p>
6420             * This method is meant for those wishing to customize the default
6421             * <code>Printable</code> implementation used by <code>JTable</code>'s
6422             * <code>print</code> methods. Developers wanting simply to print the table
6423             * should use one of those methods directly.
6424             * <p>
6425             * The <code>Printable</code> can be requested in one of two printing modes.
6426             * In both modes, it spreads table rows naturally in sequence across
6427             * multiple pages, fitting as many rows as possible per page.
6428             * <code>PrintMode.NORMAL</code> specifies that the table be
6429             * printed at its current size. In this mode, there may be a need to spread
6430             * columns across pages in a similar manner to that of the rows. When the
6431             * need arises, columns are distributed in an order consistent with the
6432             * table's <code>ComponentOrientation</code>.
6433             * <code>PrintMode.FIT_WIDTH</code> specifies that the output be
6434             * scaled smaller, if necessary, to fit the table's entire width
6435             * (and thereby all columns) on each page. Width and height are scaled
6436             * equally, maintaining the aspect ratio of the output.
6437             * <p>
6438             * The <code>Printable</code> heads the portion of table on each page
6439             * with the appropriate section from the table's <code>JTableHeader</code>,
6440             * if it has one.
6441             * <p>
6442             * Header and footer text can be added to the output by providing
6443             * <code>MessageFormat</code> arguments. The printing code requests
6444             * Strings from the formats, providing a single item which may be included
6445             * in the formatted string: an <code>Integer</code> representing the current
6446             * page number.
6447             * <p>
6448             * You are encouraged to read the documentation for
6449             * <code>MessageFormat</code> as some characters, such as single-quote,
6450             * are special and need to be escaped.
6451             * <p>
6452             * Here's an example of creating a <code>MessageFormat</code> that can be
6453             * used to print "Duke's Table: Page - " and the current page number:
6454             * <p>
6455             * <pre>
6456             *     // notice the escaping of the single quote
6457             *     // notice how the page number is included with "{0}"
6458             *     MessageFormat format = new MessageFormat("Duke''s Table: Page - {0}");
6459             * </pre>
6460             * <p>
6461             * The <code>Printable</code> constrains what it draws to the printable
6462             * area of each page that it prints. Under certain circumstances, it may
6463             * find it impossible to fit all of a page's content into that area. In
6464             * these cases the output may be clipped, but the implementation
6465             * makes an effort to do something reasonable. Here are a few situations
6466             * where this is known to occur, and how they may be handled by this
6467             * particular implementation:
6468             * <ul>
6469             *   <li>In any mode, when the header or footer text is too wide to fit
6470             *       completely in the printable area -- print as much of the text as
6471             *       possible starting from the beginning, as determined by the table's
6472             *       <code>ComponentOrientation</code>.
6473             *   <li>In any mode, when a row is too tall to fit in the
6474             *       printable area -- print the upper-most portion of the row
6475             *       and paint no lower border on the table.
6476             *   <li>In <code>PrintMode.NORMAL</code> when a column
6477             *       is too wide to fit in the printable area -- print the center
6478             *       portion of the column and leave the left and right borders
6479             *       off the table.
6480             * </ul>
6481             * <p>
6482             * It is entirely valid for this <code>Printable</code> to be wrapped
6483             * inside another in order to create complex reports and documents. You may
6484             * even request that different pages be rendered into different sized
6485             * printable areas. The implementation must be prepared to handle this
6486             * (possibly by doing its layout calculations on the fly). However,
6487             * providing different heights to each page will likely not work well
6488             * with <code>PrintMode.NORMAL</code> when it has to spread columns
6489             * across pages.
6490             * <p>
6491             * As far as customizing how the table looks in the printed result,
6492             * <code>JTable</code> itself will take care of hiding the selection
6493             * and focus during printing. For additional customizations, your
6494             * renderers or painting code can customize the look based on the value
6495             * of {@link javax.swing.JComponent#isPaintingForPrint()}
6496             * <p>
6497             * Also, <i>before</i> calling this method you may wish to <i>first</i>
6498             * modify the state of the table, such as to cancel cell editing or
6499             * have the user size the table appropriately. However, you must not
6500             * modify the state of the table <i>after</i> this <code>Printable</code>
6501             * has been fetched (invalid modifications include changes in size or
6502             * underlying data). The behavior of the returned <code>Printable</code>
6503             * is undefined once the table has been changed.
6504             *
6505             * @param  printMode     the printing mode that the printable should use
6506             * @param  headerFormat  a <code>MessageFormat</code> specifying the text to
6507             *                       be used in printing a header, or null for none
6508             * @param  footerFormat  a <code>MessageFormat</code> specifying the text to
6509             *                       be used in printing a footer, or null for none
6510             * @return a <code>Printable</code> for printing this JTable
6511             * @see #print(JTable.PrintMode, MessageFormat, MessageFormat,
6512             *             boolean, PrintRequestAttributeSet, boolean)
6513             * @see Printable
6514             * @see PrinterJob
6515             *
6516             * @since 1.5
6517             */
6518            public Printable getPrintable(PrintMode printMode,
6519                    MessageFormat headerFormat, MessageFormat footerFormat) {
6520
6521                return new TablePrintable(this , printMode, headerFormat,
6522                        footerFormat);
6523            }
6524
6525            /**
6526             * A <code>Printable</code> implementation that wraps another
6527             * <code>Printable</code>, making it safe for printing on another thread.
6528             */
6529            private class ThreadSafePrintable implements  Printable {
6530
6531                /** The delegate <code>Printable</code>. */
6532                private Printable printDelegate;
6533
6534                /**
6535                 * To communicate any return value when delegating.
6536                 */
6537                private int retVal;
6538
6539                /**
6540                 * To communicate any <code>Throwable</code> when delegating.
6541                 */
6542                private Throwable retThrowable;
6543
6544                /**
6545                 * Construct a <code>ThreadSafePrintable</code> around the given
6546                 * delegate.
6547                 *
6548                 * @param printDelegate the <code>Printable</code> to delegate to
6549                 */
6550                public ThreadSafePrintable(Printable printDelegate) {
6551                    this .printDelegate = printDelegate;
6552                }
6553
6554                /**
6555                 * Prints the specified page into the given {@link Graphics}
6556                 * context, in the specified format.
6557                 * <p>
6558                 * Regardless of what thread this method is called on, all calls into
6559                 * the delegate will be done on the event-dispatch thread.
6560                 *
6561                 * @param   graphics    the context into which the page is drawn
6562                 * @param   pageFormat  the size and orientation of the page being drawn
6563                 * @param   pageIndex   the zero based index of the page to be drawn
6564                 * @return  PAGE_EXISTS if the page is rendered successfully, or
6565                 *          NO_SUCH_PAGE if a non-existent page index is specified
6566                 * @throws  PrinterException if an error causes printing to be aborted
6567                 */
6568                public int print(final Graphics graphics,
6569                        final PageFormat pageFormat, final int pageIndex)
6570                        throws PrinterException {
6571
6572                    // We'll use this Runnable
6573                    Runnable runnable = new Runnable() {
6574                        public synchronized void run() {
6575                            try {
6576                                // call into the delegate and save the return value
6577                                retVal = printDelegate.print(graphics,
6578                                        pageFormat, pageIndex);
6579                            } catch (Throwable throwable) {
6580                                // save any Throwable to be rethrown
6581                                retThrowable = throwable;
6582                            } finally {
6583                                // notify the caller that we're done
6584                                notifyAll();
6585                            }
6586                        }
6587                    };
6588
6589                    synchronized (runnable) {
6590                        // make sure these are initialized
6591                        retVal = -1;
6592                        retThrowable = null;
6593
6594                        // call into the EDT
6595                        SwingUtilities.invokeLater(runnable);
6596
6597                        // wait for the runnable to finish
6598                        while (retVal == -1 && retThrowable == null) {
6599                            try {
6600                                runnable.wait();
6601                            } catch (InterruptedException ie) {
6602                                // short process, safe to ignore interrupts
6603                            }
6604                        }
6605
6606                        // if the delegate threw a throwable, rethrow it here
6607                        if (retThrowable != null) {
6608                            if (retThrowable instanceof  PrinterException) {
6609                                throw (PrinterException) retThrowable;
6610                            } else if (retThrowable instanceof  RuntimeException) {
6611                                throw (RuntimeException) retThrowable;
6612                            } else if (retThrowable instanceof  Error) {
6613                                throw (Error) retThrowable;
6614                            }
6615
6616                            // can not happen
6617                            throw new AssertionError(retThrowable);
6618                        }
6619
6620                        return retVal;
6621                    }
6622                }
6623            }
6624
6625            /////////////////
6626            // Accessibility support
6627            ////////////////
6628
6629            /**
6630             * Gets the AccessibleContext associated with this JTable.
6631             * For tables, the AccessibleContext takes the form of an
6632             * AccessibleJTable.
6633             * A new AccessibleJTable instance is created if necessary.
6634             *
6635             * @return an AccessibleJTable that serves as the
6636             *         AccessibleContext of this JTable
6637             */
6638            public AccessibleContext getAccessibleContext() {
6639                if (accessibleContext == null) {
6640                    accessibleContext = new AccessibleJTable();
6641                }
6642                return accessibleContext;
6643            }
6644
6645            //
6646            // *** should also implement AccessibleSelection?
6647            // *** and what's up with keyboard navigation/manipulation?
6648            //
6649            /**
6650             * This class implements accessibility support for the
6651             * <code>JTable</code> class.  It provides an implementation of the
6652             * Java Accessibility API appropriate to table user-interface elements.
6653             * <p>
6654             * <strong>Warning:</strong>
6655             * Serialized objects of this class will not be compatible with
6656             * future Swing releases. The current serialization support is
6657             * appropriate for short term storage or RMI between applications running
6658             * the same version of Swing.  As of 1.4, support for long term storage
6659             * of all JavaBeans<sup><font size="-2">TM</font></sup>
6660             * has been added to the <code>java.beans</code> package.
6661             * Please see {@link java.beans.XMLEncoder}.
6662             */
6663            protected class AccessibleJTable extends AccessibleJComponent
6664                    implements  AccessibleSelection, ListSelectionListener,
6665                    TableModelListener, TableColumnModelListener,
6666                    CellEditorListener, PropertyChangeListener,
6667                    AccessibleExtendedTable {
6668
6669                int lastSelectedRow;
6670                int lastSelectedCol;
6671
6672                /**
6673                 * AccessibleJTable constructor
6674                 *
6675                 * @since 1.5
6676                 */
6677                protected AccessibleJTable() {
6678                    super ();
6679                    JTable.this .addPropertyChangeListener(this );
6680                    JTable.this .getSelectionModel().addListSelectionListener(
6681                            this );
6682                    TableColumnModel tcm = JTable.this .getColumnModel();
6683                    tcm.addColumnModelListener(this );
6684                    tcm.getSelectionModel().addListSelectionListener(this );
6685                    JTable.this .getModel().addTableModelListener(this );
6686                    lastSelectedRow = JTable.this .getSelectedRow();
6687                    lastSelectedCol = JTable.this .getSelectedColumn();
6688                }
6689
6690                // Listeners to track model, etc. changes to as to re-place the other
6691                // listeners
6692
6693                /**
6694                 * Track changes to selection model, column model, etc. so as to
6695                 * be able to re-place listeners on those in order to pass on
6696                 * information to the Accessibility PropertyChange mechanism
6697                 */
6698                public void propertyChange(PropertyChangeEvent e) {
6699                    String name = e.getPropertyName();
6700                    Object oldValue = e.getOldValue();
6701                    Object newValue = e.getNewValue();
6702
6703                    // re-set tableModel listeners
6704                    if (name.compareTo("model") == 0) {
6705
6706                        if (oldValue != null && oldValue instanceof  TableModel) {
6707                            ((TableModel) oldValue)
6708                                    .removeTableModelListener(this );
6709                        }
6710                        if (newValue != null && newValue instanceof  TableModel) {
6711                            ((TableModel) newValue).addTableModelListener(this );
6712                        }
6713
6714                        // re-set selectionModel listeners
6715                    } else if (name.compareTo("selectionModel") == 0) {
6716
6717                        Object source = e.getSource();
6718                        if (source == JTable.this ) { // row selection model
6719
6720                            if (oldValue != null
6721                                    && oldValue instanceof  ListSelectionModel) {
6722                                ((ListSelectionModel) oldValue)
6723                                        .removeListSelectionListener(this );
6724                            }
6725                            if (newValue != null
6726                                    && newValue instanceof  ListSelectionModel) {
6727                                ((ListSelectionModel) newValue)
6728                                        .addListSelectionListener(this );
6729                            }
6730
6731                        } else if (source == JTable.this .getColumnModel()) {
6732
6733                            if (oldValue != null
6734                                    && oldValue instanceof  ListSelectionModel) {
6735                                ((ListSelectionModel) oldValue)
6736                                        .removeListSelectionListener(this );
6737                            }
6738                            if (newValue != null
6739                                    && newValue instanceof  ListSelectionModel) {
6740                                ((ListSelectionModel) newValue)
6741                                        .addListSelectionListener(this );
6742                            }
6743
6744                        } else {
6745                            //	    System.out.println("!!! Bug in source of selectionModel propertyChangeEvent");
6746                        }
6747
6748                        // re-set columnModel listeners
6749                        // and column's selection property listener as well
6750                    } else if (name.compareTo("columnModel") == 0) {
6751
6752                        if (oldValue != null
6753                                && oldValue instanceof  TableColumnModel) {
6754                            TableColumnModel tcm = (TableColumnModel) oldValue;
6755                            tcm.removeColumnModelListener(this );
6756                            tcm.getSelectionModel()
6757                                    .removeListSelectionListener(this );
6758                        }
6759                        if (newValue != null
6760                                && newValue instanceof  TableColumnModel) {
6761                            TableColumnModel tcm = (TableColumnModel) newValue;
6762                            tcm.addColumnModelListener(this );
6763                            tcm.getSelectionModel().addListSelectionListener(
6764                                    this );
6765                        }
6766
6767                        // re-se cellEditor listeners
6768                    } else if (name.compareTo("tableCellEditor") == 0) {
6769
6770                        if (oldValue != null
6771                                && oldValue instanceof  TableCellEditor) {
6772                            ((TableCellEditor) oldValue)
6773                                    .removeCellEditorListener((CellEditorListener) this );
6774                        }
6775                        if (newValue != null
6776                                && newValue instanceof  TableCellEditor) {
6777                            ((TableCellEditor) newValue)
6778                                    .addCellEditorListener((CellEditorListener) this );
6779                        }
6780                    }
6781                }
6782
6783                // Listeners to echo changes to the AccessiblePropertyChange mechanism
6784
6785                /*
6786                 * Describes a change in the accessible table model.
6787                 */
6788                protected class AccessibleJTableModelChange implements 
6789                        AccessibleTableModelChange {
6790
6791                    protected int type;
6792                    protected int firstRow;
6793                    protected int lastRow;
6794                    protected int firstColumn;
6795                    protected int lastColumn;
6796
6797                    protected AccessibleJTableModelChange(int type,
6798                            int firstRow, int lastRow, int firstColumn,
6799                            int lastColumn) {
6800                        this .type = type;
6801                        this .firstRow = firstRow;
6802                        this .lastRow = lastRow;
6803                        this .firstColumn = firstColumn;
6804                        this .lastColumn = lastColumn;
6805                    }
6806
6807                    public int getType() {
6808                        return type;
6809                    }
6810
6811                    public int getFirstRow() {
6812                        return firstRow;
6813                    }
6814
6815                    public int getLastRow() {
6816                        return lastRow;
6817                    }
6818
6819                    public int getFirstColumn() {
6820                        return firstColumn;
6821                    }
6822
6823                    public int getLastColumn() {
6824                        return lastColumn;
6825                    }
6826                }
6827
6828                /**
6829                 * Track changes to the table contents
6830                 */
6831                public void tableChanged(TableModelEvent e) {
6832                    firePropertyChange(
6833                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
6834                            null, null);
6835                    if (e != null) {
6836                        int firstColumn = e.getColumn();
6837                        int lastColumn = e.getColumn();
6838                        if (firstColumn == TableModelEvent.ALL_COLUMNS) {
6839                            firstColumn = 0;
6840                            lastColumn = getColumnCount() - 1;
6841                        }
6842
6843                        // Fire a property change event indicating the table model
6844                        // has changed.
6845                        AccessibleJTableModelChange change = new AccessibleJTableModelChange(
6846                                e.getType(), e.getFirstRow(), e.getLastRow(),
6847                                firstColumn, lastColumn);
6848                        firePropertyChange(
6849                                AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
6850                                null, change);
6851                    }
6852                }
6853
6854                /**
6855                 * Track changes to the table contents (row insertions)
6856                 */
6857                public void tableRowsInserted(TableModelEvent e) {
6858                    firePropertyChange(
6859                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
6860                            null, null);
6861
6862                    // Fire a property change event indicating the table model
6863                    // has changed.
6864                    int firstColumn = e.getColumn();
6865                    int lastColumn = e.getColumn();
6866                    if (firstColumn == TableModelEvent.ALL_COLUMNS) {
6867                        firstColumn = 0;
6868                        lastColumn = getColumnCount() - 1;
6869                    }
6870                    AccessibleJTableModelChange change = new AccessibleJTableModelChange(
6871                            e.getType(), e.getFirstRow(), e.getLastRow(),
6872                            firstColumn, lastColumn);
6873                    firePropertyChange(
6874                            AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
6875                            null, change);
6876                }
6877
6878                /**
6879                 * Track changes to the table contents (row deletions)
6880                 */
6881                public void tableRowsDeleted(TableModelEvent e) {
6882                    firePropertyChange(
6883                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
6884                            null, null);
6885
6886                    // Fire a property change event indicating the table model
6887                    // has changed.
6888                    int firstColumn = e.getColumn();
6889                    int lastColumn = e.getColumn();
6890                    if (firstColumn == TableModelEvent.ALL_COLUMNS) {
6891                        firstColumn = 0;
6892                        lastColumn = getColumnCount() - 1;
6893                    }
6894                    AccessibleJTableModelChange change = new AccessibleJTableModelChange(
6895                            e.getType(), e.getFirstRow(), e.getLastRow(),
6896                            firstColumn, lastColumn);
6897                    firePropertyChange(
6898                            AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
6899                            null, change);
6900                }
6901
6902                /**
6903                 * Track changes to the table contents (column insertions)
6904                 */
6905                public void columnAdded(TableColumnModelEvent e) {
6906                    firePropertyChange(
6907                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
6908                            null, null);
6909
6910                    // Fire a property change event indicating the table model
6911                    // has changed.
6912                    int type = AccessibleTableModelChange.INSERT;
6913                    AccessibleJTableModelChange change = new AccessibleJTableModelChange(
6914                            type, 0, 0, e.getFromIndex(), e.getToIndex());
6915                    firePropertyChange(
6916                            AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
6917                            null, change);
6918                }
6919
6920                /**
6921                 * Track changes to the table contents (column deletions)
6922                 */
6923                public void columnRemoved(TableColumnModelEvent e) {
6924                    firePropertyChange(
6925                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
6926                            null, null);
6927                    // Fire a property change event indicating the table model
6928                    // has changed.
6929                    int type = AccessibleTableModelChange.DELETE;
6930                    AccessibleJTableModelChange change = new AccessibleJTableModelChange(
6931                            type, 0, 0, e.getFromIndex(), e.getToIndex());
6932                    firePropertyChange(
6933                            AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
6934                            null, change);
6935                }
6936
6937                /**
6938                 * Track changes of a column repositioning.
6939                 *
6940                 * @see TableColumnModelListener
6941                 */
6942                public void columnMoved(TableColumnModelEvent e) {
6943                    firePropertyChange(
6944                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
6945                            null, null);
6946
6947                    // Fire property change events indicating the table model
6948                    // has changed.
6949                    int type = AccessibleTableModelChange.DELETE;
6950                    AccessibleJTableModelChange change = new AccessibleJTableModelChange(
6951                            type, 0, 0, e.getFromIndex(), e.getFromIndex());
6952                    firePropertyChange(
6953                            AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
6954                            null, change);
6955
6956                    int type2 = AccessibleTableModelChange.INSERT;
6957                    AccessibleJTableModelChange change2 = new AccessibleJTableModelChange(
6958                            type2, 0, 0, e.getToIndex(), e.getToIndex());
6959                    firePropertyChange(
6960                            AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
6961                            null, change2);
6962                }
6963
6964                /**
6965                 * Track changes of a column moving due to margin changes.
6966                 *
6967                 * @see TableColumnModelListener
6968                 */
6969                public void columnMarginChanged(ChangeEvent e) {
6970                    firePropertyChange(
6971                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
6972                            null, null);
6973                }
6974
6975                /**
6976                 * Track that the selection model of the TableColumnModel changed.
6977                 *
6978                 * @see TableColumnModelListener
6979                 */
6980                public void columnSelectionChanged(ListSelectionEvent e) {
6981                    // we should now re-place our TableColumn listener
6982                }
6983
6984                /**
6985                 * Track changes to a cell's contents.
6986                 *
6987                 * Invoked when editing is finished. The changes are saved, the
6988                 * editor object is discarded, and the cell is rendered once again.
6989                 *
6990                 * @see CellEditorListener
6991                 */
6992                public void editingStopped(ChangeEvent e) {
6993                    // it'd be great if we could figure out which cell, and pass that
6994                    // somehow as a parameter
6995                    firePropertyChange(
6996                            AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
6997                            null, null);
6998                }
6999
7000                /**
7001                 * Invoked when editing is canceled. The editor object is discarded
7002                 * and the cell is rendered once again.
7003                 *
7004                 * @see CellEditorListener
7005                 */
7006                public void editingCanceled(ChangeEvent e) {
7007                    // nothing to report, 'cause nothing changed
7008                }
7009
7010                /**
7011                 * Track changes to table cell selections
7012                 */
7013                public void valueChanged(ListSelectionEvent e) {
7014                    firePropertyChange(
7015                            AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
7016                            Boolean.valueOf(false), Boolean.valueOf(true));
7017
7018                    int selectedRow = JTable.this .getSelectedRow();
7019                    int selectedCol = JTable.this .getSelectedColumn();
7020                    if (selectedRow != lastSelectedRow
7021                            || selectedCol != lastSelectedCol) {
7022                        Accessible oldA = getAccessibleAt(lastSelectedRow,
7023                                lastSelectedCol);
7024                        Accessible newA = getAccessibleAt(selectedRow,
7025                                selectedCol);
7026                        firePropertyChange(
7027                                AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY,
7028                                oldA, newA);
7029                        lastSelectedRow = selectedRow;
7030                        lastSelectedCol = selectedCol;
7031                    }
7032                }
7033
7034                // AccessibleContext support
7035
7036                /**
7037                 * Get the AccessibleSelection associated with this object.  In the
7038                 * implementation of the Java Accessibility API for this class,
7039                 * return this object, which is responsible for implementing the
7040                 * AccessibleSelection interface on behalf of itself.
7041                 *
7042                 * @return this object
7043                 */
7044                public AccessibleSelection getAccessibleSelection() {
7045                    return this ;
7046                }
7047
7048                /**
7049                 * Gets the role of this object.
7050                 *
7051                 * @return an instance of AccessibleRole describing the role of the
7052                 * object
7053                 * @see AccessibleRole
7054                 */
7055                public AccessibleRole getAccessibleRole() {
7056                    return AccessibleRole.TABLE;
7057                }
7058
7059                /**
7060                 * Returns the <code>Accessible</code> child, if one exists,
7061                 * contained at the local coordinate <code>Point</code>.
7062                 *
7063                 * @param p the point defining the top-left corner of the
7064                 *    <code>Accessible</code>, given in the coordinate space
7065                 *    of the object's parent
7066                 * @return the <code>Accessible</code>, if it exists,
7067                 *    at the specified location; else <code>null</code>
7068                 */
7069                public Accessible getAccessibleAt(Point p) {
7070                    int column = columnAtPoint(p);
7071                    int row = rowAtPoint(p);
7072
7073                    if ((column != -1) && (row != -1)) {
7074                        TableColumn aColumn = getColumnModel()
7075                                .getColumn(column);
7076                        TableCellRenderer renderer = aColumn.getCellRenderer();
7077                        if (renderer == null) {
7078                            Class<?> columnClass = getColumnClass(column);
7079                            renderer = getDefaultRenderer(columnClass);
7080                        }
7081                        Component component = renderer
7082                                .getTableCellRendererComponent(JTable.this ,
7083                                        null, false, false, row, column);
7084                        return new AccessibleJTableCell(JTable.this , row,
7085                                column, getAccessibleIndexAt(row, column));
7086                    }
7087                    return null;
7088                }
7089
7090                /**
7091                 * Returns the number of accessible children in the object.  If all
7092                 * of the children of this object implement <code>Accessible</code>,
7093                 * then this method should return the number of children of this object.
7094                 *
7095                 * @return the number of accessible children in the object
7096                 */
7097                public int getAccessibleChildrenCount() {
7098                    return (JTable.this .getColumnCount() * JTable.this 
7099                            .getRowCount());
7100                }
7101
7102                /**
7103                 * Returns the nth <code>Accessible</code> child of the object.
7104                 *
7105                 * @param i zero-based index of child
7106                 * @return the nth Accessible child of the object
7107                 */
7108                public Accessible getAccessibleChild(int i) {
7109                    if (i < 0 || i >= getAccessibleChildrenCount()) {
7110                        return null;
7111                    } else {
7112                        // children increase across, and then down, for tables
7113                        // (arbitrary decision)
7114                        int column = getAccessibleColumnAtIndex(i);
7115                        int row = getAccessibleRowAtIndex(i);
7116
7117                        TableColumn aColumn = getColumnModel()
7118                                .getColumn(column);
7119                        TableCellRenderer renderer = aColumn.getCellRenderer();
7120                        if (renderer == null) {
7121                            Class<?> columnClass = getColumnClass(column);
7122                            renderer = getDefaultRenderer(columnClass);
7123                        }
7124                        Component component = renderer
7125                                .getTableCellRendererComponent(JTable.this ,
7126                                        null, false, false, row, column);
7127                        return new AccessibleJTableCell(JTable.this , row,
7128                                column, getAccessibleIndexAt(row, column));
7129                    }
7130                }
7131
7132                // AccessibleSelection support
7133
7134                /**
7135                 * Returns the number of <code>Accessible</code> children
7136                 * currently selected.
7137                 * If no children are selected, the return value will be 0.
7138                 *
7139                 * @return the number of items currently selected
7140                 */
7141                public int getAccessibleSelectionCount() {
7142                    int rowsSel = JTable.this .getSelectedRowCount();
7143                    int colsSel = JTable.this .getSelectedColumnCount();
7144
7145                    if (JTable.this .cellSelectionEnabled) { // a contiguous block
7146                        return rowsSel * colsSel;
7147
7148                    } else {
7149                        // a column swath and a row swath, with a shared block
7150                        if (JTable.this .getRowSelectionAllowed()
7151                                && JTable.this .getColumnSelectionAllowed()) {
7152                            return rowsSel * JTable.this .getColumnCount()
7153                                    + colsSel * JTable.this .getRowCount()
7154                                    - rowsSel * colsSel;
7155
7156                            // just one or more rows in selection
7157                        } else if (JTable.this .getRowSelectionAllowed()) {
7158                            return rowsSel * JTable.this .getColumnCount();
7159
7160                            // just one or more rows in selection
7161                        } else if (JTable.this .getColumnSelectionAllowed()) {
7162                            return colsSel * JTable.this .getRowCount();
7163
7164                        } else {
7165                            return 0; // JTable doesn't allow selections
7166                        }
7167                    }
7168                }
7169
7170                /**
7171                 * Returns an <code>Accessible</code> representing the
7172                 * specified selected child in the object.  If there
7173                 * isn't a selection, or there are fewer children selected
7174                 * than the integer passed in, the return
7175                 * value will be <code>null</code>.
7176                 * <p>Note that the index represents the i-th selected child, which
7177                 * is different from the i-th child.
7178                 *
7179                 * @param i the zero-based index of selected children
7180                 * @return the i-th selected child
7181                 * @see #getAccessibleSelectionCount
7182                 */
7183                public Accessible getAccessibleSelection(int i) {
7184                    if (i < 0 || i > getAccessibleSelectionCount()) {
7185                        return (Accessible) null;
7186                    }
7187
7188                    int rowsSel = JTable.this .getSelectedRowCount();
7189                    int colsSel = JTable.this .getSelectedColumnCount();
7190                    int rowIndicies[] = getSelectedRows();
7191                    int colIndicies[] = getSelectedColumns();
7192                    int ttlCols = JTable.this .getColumnCount();
7193                    int ttlRows = JTable.this .getRowCount();
7194                    int r;
7195                    int c;
7196
7197                    if (JTable.this .cellSelectionEnabled) { // a contiguous block
7198                        r = rowIndicies[i / colsSel];
7199                        c = colIndicies[i % colsSel];
7200                        return getAccessibleChild((r * ttlCols) + c);
7201                    } else {
7202
7203                        // a column swath and a row swath, with a shared block
7204                        if (JTable.this .getRowSelectionAllowed()
7205                                && JTable.this .getColumnSelectionAllowed()) {
7206
7207                            // Situation:
7208                            //   We have a table, like the 6x3 table below,
7209                            //   wherein three colums and one row selected
7210                            //   (selected cells marked with "*", unselected "0"):
7211                            //
7212                            //            0 * 0 * * 0
7213                            //            * * * * * *
7214                            //            0 * 0 * * 0
7215                            //
7216
7217                            // State machine below walks through the array of
7218                            // selected rows in two states: in a selected row,
7219                            // and not in one; continuing until we are in a row
7220                            // in which the ith selection exists.  Then we return
7221                            // the appropriate cell.  In the state machine, we
7222                            // always do rows above the "current" selected row first,
7223                            // then the cells in the selected row.  If we're done
7224                            // with the state machine before finding the requested
7225                            // selected child, we handle the rows below the last
7226                            // selected row at the end.
7227                            //
7228                            int curIndex = i;
7229                            final int IN_ROW = 0;
7230                            final int NOT_IN_ROW = 1;
7231                            int state = (rowIndicies[0] == 0 ? IN_ROW
7232                                    : NOT_IN_ROW);
7233                            int j = 0;
7234                            int prevRow = -1;
7235                            while (j < rowIndicies.length) {
7236                                switch (state) {
7237
7238                                case IN_ROW: // on individual row full of selections
7239                                    if (curIndex < ttlCols) { // it's here!
7240                                        c = curIndex % ttlCols;
7241                                        r = rowIndicies[j];
7242                                        return getAccessibleChild((r * ttlCols)
7243                                                + c);
7244                                    } else { // not here
7245                                        curIndex -= ttlCols;
7246                                    }
7247                                    // is the next row in table selected or not?
7248                                    if (j + 1 == rowIndicies.length
7249                                            || rowIndicies[j] != rowIndicies[j + 1] - 1) {
7250                                        state = NOT_IN_ROW;
7251                                        prevRow = rowIndicies[j];
7252                                    }
7253                                    j++; // we didn't return earlier, so go to next row
7254                                    break;
7255
7256                                case NOT_IN_ROW: // sparse bunch of rows of selections
7257                                    if (curIndex < (colsSel * (rowIndicies[j] - (prevRow == -1 ? 0
7258                                            : (prevRow + 1))))) {
7259
7260                                        // it's here!
7261                                        c = colIndicies[curIndex % colsSel];
7262                                        r = (j > 0 ? rowIndicies[j - 1] + 1 : 0)
7263                                                + curIndex / colsSel;
7264                                        return getAccessibleChild((r * ttlCols)
7265                                                + c);
7266                                    } else { // not here
7267                                        curIndex -= colsSel
7268                                                * (rowIndicies[j] - (prevRow == -1 ? 0
7269                                                        : (prevRow + 1)));
7270                                    }
7271                                    state = IN_ROW;
7272                                    break;
7273                                }
7274                            }
7275                            // we got here, so we didn't find it yet; find it in
7276                            // the last sparse bunch of rows
7277                            if (curIndex < (colsSel * (ttlRows - (prevRow == -1 ? 0
7278                                    : (prevRow + 1))))) { // it's here!
7279                                c = colIndicies[curIndex % colsSel];
7280                                r = rowIndicies[j - 1] + curIndex / colsSel + 1;
7281                                return getAccessibleChild((r * ttlCols) + c);
7282                            } else { // not here
7283                                // we shouldn't get to this spot in the code!
7284                                //                      System.out.println("Bug in AccessibleJTable.getAccessibleSelection()");
7285                            }
7286
7287                            // one or more rows selected
7288                        } else if (JTable.this .getRowSelectionAllowed()) {
7289                            c = i % ttlCols;
7290                            r = rowIndicies[i / ttlCols];
7291                            return getAccessibleChild((r * ttlCols) + c);
7292
7293                            // one or more columns selected
7294                        } else if (JTable.this .getColumnSelectionAllowed()) {
7295                            c = colIndicies[i % colsSel];
7296                            r = i / colsSel;
7297                            return getAccessibleChild((r * ttlCols) + c);
7298                        }
7299                    }
7300                    return (Accessible) null;
7301                }
7302
7303                /**
7304                 * Determines if the current child of this object is selected.
7305                 *
7306                 * @param i the zero-based index of the child in this
7307                 *    <code>Accessible</code> object
7308                 * @return true if the current child of this object is selected
7309                 * @see AccessibleContext#getAccessibleChild
7310                 */
7311                public boolean isAccessibleChildSelected(int i) {
7312                    int column = getAccessibleColumnAtIndex(i);
7313                    int row = getAccessibleRowAtIndex(i);
7314                    return JTable.this .isCellSelected(row, column);
7315                }
7316
7317                /**
7318                 * Adds the specified <code>Accessible</code> child of the
7319                 * object to the object's selection.  If the object supports
7320                 * multiple selections, the specified child is added to
7321                 * any existing selection, otherwise
7322                 * it replaces any existing selection in the object.  If the
7323                 * specified child is already selected, this method has no effect.
7324                 * <p>
7325                 * This method only works on <code>JTable</code>s which have
7326                 * individual cell selection enabled.
7327                 *
7328                 * @param i the zero-based index of the child
7329                 * @see AccessibleContext#getAccessibleChild
7330                 */
7331                public void addAccessibleSelection(int i) {
7332                    // TIGER - 4495286
7333                    int column = getAccessibleColumnAtIndex(i);
7334                    int row = getAccessibleRowAtIndex(i);
7335                    JTable.this .changeSelection(row, column, true, false);
7336                }
7337
7338                /**
7339                 * Removes the specified child of the object from the object's
7340                 * selection.  If the specified item isn't currently selected, this
7341                 * method has no effect.
7342                 * <p>
7343                 * This method only works on <code>JTables</code> which have
7344                 * individual cell selection enabled.
7345                 *
7346                 * @param i the zero-based index of the child
7347                 * @see AccessibleContext#getAccessibleChild
7348                 */
7349                public void removeAccessibleSelection(int i) {
7350                    if (JTable.this .cellSelectionEnabled) {
7351                        int column = getAccessibleColumnAtIndex(i);
7352                        int row = getAccessibleRowAtIndex(i);
7353                        JTable.this .removeRowSelectionInterval(row, row);
7354                        JTable.this .removeColumnSelectionInterval(column,
7355                                column);
7356                    }
7357                }
7358
7359                /**
7360                 * Clears the selection in the object, so that no children in the
7361                 * object are selected.
7362                 */
7363                public void clearAccessibleSelection() {
7364                    JTable.this .clearSelection();
7365                }
7366
7367                /**
7368                 * Causes every child of the object to be selected, but only
7369                 * if the <code>JTable</code> supports multiple selections,
7370                 * and if individual cell selection is enabled.
7371                 */
7372                public void selectAllAccessibleSelection() {
7373                    if (JTable.this .cellSelectionEnabled) {
7374                        JTable.this .selectAll();
7375                    }
7376                }
7377
7378                // begin AccessibleExtendedTable implementation -------------
7379
7380                /**
7381                 * Returns the row number of an index in the table.
7382                 *
7383                 * @param index the zero-based index in the table
7384                 * @return the zero-based row of the table if one exists;
7385                 * otherwise -1.
7386                 * @since 1.4
7387                 */
7388                public int getAccessibleRow(int index) {
7389                    return getAccessibleRowAtIndex(index);
7390                }
7391
7392                /**
7393                 * Returns the column number of an index in the table.
7394                 *
7395                 * @param index the zero-based index in the table
7396                 * @return the zero-based column of the table if one exists;
7397                 * otherwise -1.
7398                 * @since 1.4
7399                 */
7400                public int getAccessibleColumn(int index) {
7401                    return getAccessibleColumnAtIndex(index);
7402                }
7403
7404                /**
7405                 * Returns the index at a row and column in the table.
7406                 *
7407                 * @param r zero-based row of the table
7408                 * @param c zero-based column of the table
7409                 * @return the zero-based index in the table if one exists;
7410                 * otherwise -1.
7411                 * @since 1.4
7412                 */
7413                public int getAccessibleIndex(int r, int c) {
7414                    return getAccessibleIndexAt(r, c);
7415                }
7416
7417                // end of AccessibleExtendedTable implementation ------------
7418
7419                // start of AccessibleTable implementation ------------------
7420
7421                private Accessible caption;
7422                private Accessible summary;
7423                private Accessible[] rowDescription;
7424                private Accessible[] columnDescription;
7425
7426                /**
7427                 * Gets the <code>AccessibleTable</code> associated with this
7428                 * object.  In the implementation of the Java Accessibility
7429                 * API for this class, return this object, which is responsible
7430                 * for implementing the <code>AccessibleTables</code> interface
7431                 * on behalf of itself.
7432                 *
7433                 * @return this object
7434                 * @since 1.3
7435                 */
7436                public AccessibleTable getAccessibleTable() {
7437                    return this ;
7438                }
7439
7440                /**
7441                 * Returns the caption for the table.
7442                 *
7443                 * @return the caption for the table
7444                 * @since 1.3
7445                 */
7446                public Accessible getAccessibleCaption() {
7447                    return this .caption;
7448                }
7449
7450                /**
7451                 * Sets the caption for the table.
7452                 *
7453                 * @param a the caption for the table
7454                 * @since 1.3
7455                 */
7456                public void setAccessibleCaption(Accessible a) {
7457                    Accessible oldCaption = caption;
7458                    this .caption = a;
7459                    firePropertyChange(
7460                            AccessibleContext.ACCESSIBLE_TABLE_CAPTION_CHANGED,
7461                            oldCaption, this .caption);
7462                }
7463
7464                /**
7465                 * Returns the summary description of the table.
7466                 *
7467                 * @return the summary description of the table
7468                 * @since 1.3
7469                 */
7470                public Accessible getAccessibleSummary() {
7471                    return this .summary;
7472                }
7473
7474                /**
7475                 * Sets the summary description of the table.
7476                 *
7477                 * @param a the summary description of the table
7478                 * @since 1.3
7479                 */
7480                public void setAccessibleSummary(Accessible a) {
7481                    Accessible oldSummary = summary;
7482                    this .summary = a;
7483                    firePropertyChange(
7484                            AccessibleContext.ACCESSIBLE_TABLE_SUMMARY_CHANGED,
7485                            oldSummary, this .summary);
7486                }
7487
7488                /*
7489                 * Returns the total number of rows in this table.
7490                 *
7491                 * @return the total number of rows in this table
7492                 */
7493                public int getAccessibleRowCount() {
7494                    return JTable.this .getRowCount();
7495                }
7496
7497                /*
7498                 * Returns the total number of columns in the table.
7499                 *
7500                 * @return the total number of columns in the table
7501                 */
7502                public int getAccessibleColumnCount() {
7503                    return JTable.this .getColumnCount();
7504                }
7505
7506                /*
7507                 * Returns the <code>Accessible</code> at a specified row
7508                 * and column in the table.
7509                 *
7510                 * @param r zero-based row of the table
7511                 * @param c zero-based column of the table
7512                 * @return the <code>Accessible</code> at the specified row and column
7513                 * in the table
7514                 */
7515                public Accessible getAccessibleAt(int r, int c) {
7516                    return getAccessibleChild((r * getAccessibleColumnCount())
7517                            + c);
7518                }
7519
7520                /**
7521                 * Returns the number of rows occupied by the <code>Accessible</code>
7522                 * at a specified row and column in the table.
7523                 *
7524                 * @return the number of rows occupied by the <code>Accessible</code>
7525                 *     at a specified row and column in the table
7526                 * @since 1.3
7527                 */
7528                public int getAccessibleRowExtentAt(int r, int c) {
7529                    return 1;
7530                }
7531
7532                /**
7533                 * Returns the number of columns occupied by the
7534                 * <code>Accessible</code> at a given (row, column).
7535                 *
7536                 * @return the number of columns occupied by the <code>Accessible</code>
7537                 *     at a specified row and column in the table
7538                 * @since 1.3
7539                 */
7540                public int getAccessibleColumnExtentAt(int r, int c) {
7541                    return 1;
7542                }
7543
7544                /**
7545                 * Returns the row headers as an <code>AccessibleTable</code>.
7546                 *
7547                 * @return an <code>AccessibleTable</code> representing the row
7548                 * headers
7549                 * @since 1.3
7550                 */
7551                public AccessibleTable getAccessibleRowHeader() {
7552                    // row headers are not supported
7553                    return null;
7554                }
7555
7556                /**
7557                 * Sets the row headers as an <code>AccessibleTable</code>.
7558                 *
7559                 * @param a an <code>AccessibleTable</code> representing the row
7560                 *  headers 
7561                 * @since 1.3
7562                 */
7563                public void setAccessibleRowHeader(AccessibleTable a) {
7564                    // row headers are not supported
7565                }
7566
7567                /**
7568                 * Returns the column headers as an <code>AccessibleTable</code>.
7569                 *
7570                 *  @return an <code>AccessibleTable</code> representing the column
7571                 *          headers, or <code>null</code> if the table header is
7572                 *          <code>null</code>
7573                 * @since 1.3
7574                 */
7575                public AccessibleTable getAccessibleColumnHeader() {
7576                    JTableHeader header = JTable.this .getTableHeader();
7577                    return header == null ? null : new AccessibleTableHeader(
7578                            header);
7579                }
7580
7581                /*
7582                 * Private class representing a table column header
7583                 */
7584                private class AccessibleTableHeader implements  AccessibleTable {
7585                    private JTableHeader header;
7586                    private TableColumnModel headerModel;
7587
7588                    AccessibleTableHeader(JTableHeader header) {
7589                        this .header = header;
7590                        this .headerModel = header.getColumnModel();
7591                    }
7592
7593                    /**
7594                     * Returns the caption for the table.
7595                     *
7596                     * @return the caption for the table
7597                     */
7598                    public Accessible getAccessibleCaption() {
7599                        return null;
7600                    }
7601
7602                    /**
7603                     * Sets the caption for the table.
7604                     *
7605                     * @param a the caption for the table
7606                     */
7607                    public void setAccessibleCaption(Accessible a) {
7608                    }
7609
7610                    /**
7611                     * Returns the summary description of the table.
7612                     * 
7613                     * @return the summary description of the table
7614                     */
7615                    public Accessible getAccessibleSummary() {
7616                        return null;
7617                    }
7618
7619                    /**
7620                     * Sets the summary description of the table
7621                     *
7622                     * @param a the summary description of the table
7623                     */
7624                    public void setAccessibleSummary(Accessible a) {
7625                    }
7626
7627                    /**
7628                     * Returns the number of rows in the table.
7629                     *
7630                     * @return the number of rows in the table
7631                     */
7632                    public int getAccessibleRowCount() {
7633                        return 1;
7634                    }
7635
7636                    /**
7637                     * Returns the number of columns in the table.
7638                     *
7639                     * @return the number of columns in the table
7640                     */
7641                    public int getAccessibleColumnCount() {
7642                        return headerModel.getColumnCount();
7643                    }
7644
7645                    /**
7646                     * Returns the Accessible at a specified row and column
7647                     * in the table.
7648                     *
7649                     * @param row zero-based row of the table
7650                     * @param column zero-based column of the table
7651                     * @return the Accessible at the specified row and column
7652                     */
7653                    public Accessible getAccessibleAt(int row, int column) {
7654
7655                        // TIGER - 4715503 
7656                        TableColumn aColumn = headerModel.getColumn(column);
7657                        TableCellRenderer renderer = aColumn
7658                                .getHeaderRenderer();
7659                        if (renderer == null) {
7660                            renderer = header.getDefaultRenderer();
7661                        }
7662                        Component component = renderer
7663                                .getTableCellRendererComponent(header
7664                                        .getTable(), aColumn.getHeaderValue(),
7665                                        false, false, -1, column);
7666
7667                        return new AccessibleJTableHeaderCell(row, column,
7668                                JTable.this .getTableHeader(), component);
7669                    }
7670
7671                    /**
7672                     * Returns the number of rows occupied by the Accessible at
7673                     * a specified row and column in the table.
7674                     *
7675                     * @return the number of rows occupied by the Accessible at a
7676                     * given specified (row, column)
7677                     */
7678                    public int getAccessibleRowExtentAt(int r, int c) {
7679                        return 1;
7680                    }
7681
7682                    /**
7683                     * Returns the number of columns occupied by the Accessible at
7684                     * a specified row and column in the table.
7685                     *
7686                     * @return the number of columns occupied by the Accessible at a
7687                     * given specified row and column
7688                     */
7689                    public int getAccessibleColumnExtentAt(int r, int c) {
7690                        return 1;
7691                    }
7692
7693                    /**
7694                     * Returns the row headers as an AccessibleTable.
7695                     *
7696                     * @return an AccessibleTable representing the row
7697                     * headers
7698                     */
7699                    public AccessibleTable getAccessibleRowHeader() {
7700                        return null;
7701                    }
7702
7703                    /**
7704                     * Sets the row headers.
7705                     *
7706                     * @param table an AccessibleTable representing the
7707                     * row headers
7708                     */
7709                    public void setAccessibleRowHeader(AccessibleTable table) {
7710                    }
7711
7712                    /**
7713                     * Returns the column headers as an AccessibleTable.
7714                     *
7715                     * @return an AccessibleTable representing the column
7716                     * headers
7717                     */
7718                    public AccessibleTable getAccessibleColumnHeader() {
7719                        return null;
7720                    }
7721
7722                    /**
7723                     * Sets the column headers.
7724                     *
7725                     * @param table an AccessibleTable representing the
7726                     * column headers
7727                     * @since 1.3
7728                     */
7729                    public void setAccessibleColumnHeader(AccessibleTable table) {
7730                    }
7731
7732                    /**
7733                     * Returns the description of the specified row in the table.
7734                     *
7735                     * @param r zero-based row of the table
7736                     * @return the description of the row
7737                     * @since 1.3
7738                     */
7739                    public Accessible getAccessibleRowDescription(int r) {
7740                        return null;
7741                    }
7742
7743                    /**
7744                     * Sets the description text of the specified row of the table.
7745                     *
7746                     * @param r zero-based row of the table
7747                     * @param a the description of the row
7748                     * @since 1.3
7749                     */
7750                    public void setAccessibleRowDescription(int r, Accessible a) {
7751                    }
7752
7753                    /**
7754                     * Returns the description text of the specified column in the table.
7755                     *
7756                     * @param c zero-based column of the table
7757                     * @return the text description of the column
7758                     * @since 1.3
7759                     */
7760                    public Accessible getAccessibleColumnDescription(int c) {
7761                        return null;
7762                    }
7763
7764                    /**
7765                     * Sets the description text of the specified column in the table.
7766                     *
7767                     * @param c zero-based column of the table
7768                     * @param a the text description of the column
7769                     * @since 1.3
7770                     */
7771                    public void setAccessibleColumnDescription(int c,
7772                            Accessible a) {
7773                    }
7774
7775                    /**
7776                     * Returns a boolean value indicating whether the accessible at
7777                     * a specified row and column is selected.
7778                     *
7779                     * @param r zero-based row of the table
7780                     * @param c zero-based column of the table
7781                     * @return the boolean value true if the accessible at the
7782                     * row and column is selected. Otherwise, the boolean value 
7783                     * false
7784                     * @since 1.3
7785                     */
7786                    public boolean isAccessibleSelected(int r, int c) {
7787                        return false;
7788                    }
7789
7790                    /**
7791                     * Returns a boolean value indicating whether the specified row
7792                     * is selected.
7793                     *
7794                     * @param r zero-based row of the table
7795                     * @return the boolean value true if the specified row is selected.
7796                     * Otherwise, false.
7797                     * @since 1.3
7798                     */
7799                    public boolean isAccessibleRowSelected(int r) {
7800                        return false;
7801                    }
7802
7803                    /**
7804                     * Returns a boolean value indicating whether the specified column
7805                     * is selected.
7806                     *
7807                     * @param r zero-based column of the table
7808                     * @return the boolean value true if the specified column is selected.
7809                     * Otherwise, false.
7810                     * @since 1.3
7811                     */
7812                    public boolean isAccessibleColumnSelected(int c) {
7813                        return false;
7814                    }
7815
7816                    /**
7817                     * Returns the selected rows in a table.
7818                     *
7819                     * @return an array of selected rows where each element is a
7820                     * zero-based row of the table
7821                     * @since 1.3
7822                     */
7823                    public int[] getSelectedAccessibleRows() {
7824                        return new int[0];
7825                    }
7826
7827                    /**
7828                     * Returns the selected columns in a table.
7829                     *
7830                     * @return an array of selected columns where each element is a
7831                     * zero-based column of the table
7832                     * @since 1.3
7833                     */
7834                    public int[] getSelectedAccessibleColumns() {
7835                        return new int[0];
7836                    }
7837                }
7838
7839                /**
7840                 * Sets the column headers as an <code>AccessibleTable</code>.
7841                 *
7842                 * @param a an <code>AccessibleTable</code> representing the
7843                 * column headers
7844                 * @since 1.3
7845                 */
7846                public void setAccessibleColumnHeader(AccessibleTable a) {
7847                    // XXX not implemented
7848                }
7849
7850                /**
7851                 * Returns the description of the specified row in the table.
7852                 *
7853                 * @param r zero-based row of the table
7854                 * @return the description of the row
7855                 * @since 1.3
7856                 */
7857                public Accessible getAccessibleRowDescription(int r) {
7858                    if (r < 0 || r >= getAccessibleRowCount()) {
7859                        throw new IllegalArgumentException(new Integer(r)
7860                                .toString());
7861                    }
7862                    if (rowDescription == null) {
7863                        return null;
7864                    } else {
7865                        return rowDescription[r];
7866                    }
7867                }
7868
7869                /**
7870                 * Sets the description text of the specified row of the table.
7871                 *
7872                 * @param r zero-based row of the table
7873                 * @param a the description of the row
7874                 * @since 1.3
7875                 */
7876                public void setAccessibleRowDescription(int r, Accessible a) {
7877                    if (r < 0 || r >= getAccessibleRowCount()) {
7878                        throw new IllegalArgumentException(new Integer(r)
7879                                .toString());
7880                    }
7881                    if (rowDescription == null) {
7882                        int numRows = getAccessibleRowCount();
7883                        rowDescription = new Accessible[numRows];
7884                    }
7885                    rowDescription[r] = a;
7886                }
7887
7888                /**
7889                 * Returns the description of the specified column in the table.
7890                 *
7891                 * @param c zero-based column of the table
7892                 * @return the description of the column
7893                 * @since 1.3
7894                 */
7895                public Accessible getAccessibleColumnDescription(int c) {
7896                    if (c < 0 || c >= getAccessibleColumnCount()) {
7897                        throw new IllegalArgumentException(new Integer(c)
7898                                .toString());
7899                    }
7900                    if (columnDescription == null) {
7901                        return null;
7902                    } else {
7903                        return columnDescription[c];
7904                    }
7905                }
7906
7907                /**
7908                 * Sets the description text of the specified column of the table.
7909                 *
7910                 * @param c zero-based column of the table
7911                 * @param a the description of the column
7912                 * @since 1.3
7913                 */
7914                public void setAccessibleColumnDescription(int c, Accessible a) {
7915                    if (c < 0 || c >= getAccessibleColumnCount()) {
7916                        throw new IllegalArgumentException(new Integer(c)
7917                                .toString());
7918                    }
7919                    if (columnDescription == null) {
7920                        int numColumns = getAccessibleColumnCount();
7921                        columnDescription = new Accessible[numColumns];
7922                    }
7923                    columnDescription[c] = a;
7924                }
7925
7926                /**
7927                 * Returns a boolean value indicating whether the accessible at a
7928                 * given (row, column) is selected.
7929                 *
7930                 * @param r zero-based row of the table
7931                 * @param c zero-based column of the table
7932                 * @return the boolean value true if the accessible at (row, column)
7933                 *     is selected; otherwise, the boolean value false
7934                 * @since 1.3
7935                 */
7936                public boolean isAccessibleSelected(int r, int c) {
7937                    return JTable.this .isCellSelected(r, c);
7938                }
7939
7940                /**
7941                 * Returns a boolean value indicating whether the specified row
7942                 * is selected.
7943                 *
7944                 * @param r zero-based row of the table
7945                 * @return the boolean value true if the specified row is selected;
7946                 *     otherwise, false
7947                 * @since 1.3
7948                 */
7949                public boolean isAccessibleRowSelected(int r) {
7950                    return JTable.this .isRowSelected(r);
7951                }
7952
7953                /**
7954                 * Returns a boolean value indicating whether the specified column
7955                 * is selected.
7956                 *
7957                 * @param c zero-based column of the table
7958                 * @return the boolean value true if the specified column is selected;
7959                 *     otherwise, false
7960                 * @since 1.3
7961                 */
7962                public boolean isAccessibleColumnSelected(int c) {
7963                    return JTable.this .isColumnSelected(c);
7964                }
7965
7966                /**
7967                 * Returns the selected rows in a table.
7968                 *
7969                 * @return an array of selected rows where each element is a
7970                 *     zero-based row of the table
7971                 * @since 1.3
7972                 */
7973                public int[] getSelectedAccessibleRows() {
7974                    return JTable.this .getSelectedRows();
7975                }
7976
7977                /**
7978                 * Returns the selected columns in a table.
7979                 *
7980                 * @return an array of selected columns where each element is a
7981                 *     zero-based column of the table
7982                 * @since 1.3
7983                 */
7984                public int[] getSelectedAccessibleColumns() {
7985                    return JTable.this .getSelectedColumns();
7986                }
7987
7988                /**
7989                 * Returns the row at a given index into the table.
7990                 *
7991                 * @param i zero-based index into the table
7992                 * @return the row at a given index
7993                 * @since 1.3
7994                 */
7995                public int getAccessibleRowAtIndex(int i) {
7996                    int columnCount = getAccessibleColumnCount();
7997                    if (columnCount == 0) {
7998                        return -1;
7999                    } else {
8000                        return (i / columnCount);
8001                    }
8002                }
8003
8004                /**
8005                 * Returns the column at a given index into the table.
8006                 *
8007                 * @param i zero-based index into the table
8008                 * @return the column at a given index
8009                 * @since 1.3
8010                 */
8011                public int getAccessibleColumnAtIndex(int i) {
8012                    int columnCount = getAccessibleColumnCount();
8013                    if (columnCount == 0) {
8014                        return -1;
8015                    } else {
8016                        return (i % columnCount);
8017                    }
8018                }
8019
8020                /**
8021                 * Returns the index at a given (row, column) in the table.
8022                 *
8023                 * @param r zero-based row of the table
8024                 * @param c zero-based column of the table
8025                 * @return the index into the table
8026                 * @since 1.3
8027                 */
8028                public int getAccessibleIndexAt(int r, int c) {
8029                    return ((r * getAccessibleColumnCount()) + c);
8030                }
8031
8032                // end of AccessibleTable implementation --------------------
8033
8034                /**
8035                 * The class provides an implementation of the Java Accessibility
8036                 * API appropriate to table cells.
8037                 */
8038                protected class AccessibleJTableCell extends AccessibleContext
8039                        implements  Accessible, AccessibleComponent {
8040
8041                    private JTable parent;
8042                    private int row;
8043                    private int column;
8044                    private int index;
8045
8046                    /**
8047                     *  Constructs an <code>AccessibleJTableHeaderEntry</code>.
8048                     * @since 1.4
8049                     */
8050                    public AccessibleJTableCell(JTable t, int r, int c, int i) {
8051                        parent = t;
8052                        row = r;
8053                        column = c;
8054                        index = i;
8055                        this .setAccessibleParent(parent);
8056                    }
8057
8058                    /**
8059                     * Gets the <code>AccessibleContext</code> associated with this
8060                     * component. In the implementation of the Java Accessibility
8061                     * API for this class, return this object, which is its own
8062                     * <code>AccessibleContext</code>.
8063                     *
8064                     * @return this object
8065                     */
8066                    public AccessibleContext getAccessibleContext() {
8067                        return this ;
8068                    }
8069
8070                    /**
8071                     * Gets the AccessibleContext for the table cell renderer.
8072                     *
8073                     * @return the <code>AccessibleContext</code> for the table 
8074                     * cell renderer if one exists;
8075                     * otherwise, returns <code>null</code>.
8076                     * @since 1.6
8077                     */
8078                    protected AccessibleContext getCurrentAccessibleContext() {
8079                        TableColumn aColumn = getColumnModel()
8080                                .getColumn(column);
8081                        TableCellRenderer renderer = aColumn.getCellRenderer();
8082                        if (renderer == null) {
8083                            Class<?> columnClass = getColumnClass(column);
8084                            renderer = getDefaultRenderer(columnClass);
8085                        }
8086                        Component component = renderer
8087                                .getTableCellRendererComponent(JTable.this ,
8088                                        getValueAt(row, column), false, false,
8089                                        row, column);
8090                        if (component instanceof  Accessible) {
8091                            return ((Accessible) component)
8092                                    .getAccessibleContext();
8093                        } else {
8094                            return null;
8095                        }
8096                    }
8097
8098                    /**
8099                     * Gets the table cell renderer component.
8100                     *
8101                     * @return the table cell renderer component if one exists;
8102                     * otherwise, returns <code>null</code>.
8103                     * @since 1.6
8104                     */
8105                    protected Component getCurrentComponent() {
8106                        TableColumn aColumn = getColumnModel()
8107                                .getColumn(column);
8108                        TableCellRenderer renderer = aColumn.getCellRenderer();
8109                        if (renderer == null) {
8110                            Class<?> columnClass = getColumnClass(column);
8111                            renderer = getDefaultRenderer(columnClass);
8112                        }
8113                        return renderer.getTableCellRendererComponent(
8114                                JTable.this , null, false, false, row, column);
8115                    }
8116
8117                    // AccessibleContext methods
8118
8119                    /**
8120                     * Gets the accessible name of this object.
8121                     *
8122                     * @return the localized name of the object; <code>null</code>
8123                     *     if this object does not have a name
8124                     */
8125                    public String getAccessibleName() {
8126                        AccessibleContext ac = getCurrentAccessibleContext();
8127                        if (ac != null) {
8128                            String name = ac.getAccessibleName();
8129                            if ((name != null) && (name != "")) {
8130                                // return the cell renderer's AccessibleName
8131                                return name;
8132                            }
8133                        }
8134                        if ((accessibleName != null) && (accessibleName != "")) {
8135                            return accessibleName;
8136                        } else {
8137                            // fall back to the client property 
8138                            return (String) getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
8139                        }
8140                    }
8141
8142                    /**
8143                     * Sets the localized accessible name of this object.
8144                     *
8145                     * @param s the new localized name of the object
8146                     */
8147                    public void setAccessibleName(String s) {
8148                        AccessibleContext ac = getCurrentAccessibleContext();
8149                        if (ac != null) {
8150                            ac.setAccessibleName(s);
8151                        } else {
8152                            super .setAccessibleName(s);
8153                        }
8154                    }
8155
8156                    //
8157                    // *** should check toolTip text for desc. (needs MouseEvent)
8158                    //
8159                    /**
8160                     * Gets the accessible description of this object.
8161                     *
8162                     * @return the localized description of the object;
8163                     *     <code>null</code> if this object does not have
8164                     *     a description
8165                     */
8166                    public String getAccessibleDescription() {
8167                        AccessibleContext ac = getCurrentAccessibleContext();
8168                        if (ac != null) {
8169                            return ac.getAccessibleDescription();
8170                        } else {
8171                            return super .getAccessibleDescription();
8172                        }
8173                    }
8174
8175                    /**
8176                     * Sets the accessible description of this object.
8177                     *
8178                     * @param s the new localized description of the object
8179                     */
8180                    public void setAccessibleDescription(String s) {
8181                        AccessibleContext ac = getCurrentAccessibleContext();
8182                        if (ac != null) {
8183                            ac.setAccessibleDescription(s);
8184                        } else {
8185                            super .setAccessibleDescription(s);
8186                        }
8187                    }
8188
8189                    /**
8190                     * Gets the role of this object.
8191                     *
8192                     * @return an instance of <code>AccessibleRole</code>
8193                     *      describing the role of the object
8194                     * @see AccessibleRole
8195                     */
8196                    public AccessibleRole getAccessibleRole() {
8197                        AccessibleContext ac = getCurrentAccessibleContext();
8198                        if (ac != null) {
8199                            return ac.getAccessibleRole();
8200                        } else {
8201                            return AccessibleRole.UNKNOWN;
8202                        }
8203                    }
8204
8205                    /**
8206                     * Gets the state set of this object.
8207                     *
8208                     * @return an instance of <code>AccessibleStateSet</code>
8209                     *     containing the current state set of the object
8210                     * @see AccessibleState
8211                     */
8212                    public AccessibleStateSet getAccessibleStateSet() {
8213                        AccessibleContext ac = getCurrentAccessibleContext();
8214                        AccessibleStateSet as = null;
8215
8216                        if (ac != null) {
8217                            as = ac.getAccessibleStateSet();
8218                        }
8219                        if (as == null) {
8220                            as = new AccessibleStateSet();
8221                        }
8222                        Rectangle rjt = JTable.this .getVisibleRect();
8223                        Rectangle rcell = JTable.this .getCellRect(row, column,
8224                                false);
8225                        if (rjt.intersects(rcell)) {
8226                            as.add(AccessibleState.SHOWING);
8227                        } else {
8228                            if (as.contains(AccessibleState.SHOWING)) {
8229                                as.remove(AccessibleState.SHOWING);
8230                            }
8231                        }
8232                        if (parent.isCellSelected(row, column)) {
8233                            as.add(AccessibleState.SELECTED);
8234                        } else if (as.contains(AccessibleState.SELECTED)) {
8235                            as.remove(AccessibleState.SELECTED);
8236                        }
8237                        if ((row == getSelectedRow())
8238                                && (column == getSelectedColumn())) {
8239                            as.add(AccessibleState.ACTIVE);
8240                        }
8241                        as.add(AccessibleState.TRANSIENT);
8242                        return as;
8243                    }
8244
8245                    /**
8246                     * Gets the <code>Accessible</code> parent of this object.
8247                     *
8248                     * @return the Accessible parent of this object;
8249                     *     <code>null</code> if this object does not
8250                     *     have an <code>Accessible</code> parent
8251                     */
8252                    public Accessible getAccessibleParent() {
8253                        return parent;
8254                    }
8255
8256                    /**
8257                     * Gets the index of this object in its accessible parent.
8258                     *
8259                     * @return the index of this object in its parent; -1 if this
8260                     *     object does not have an accessible parent
8261                     * @see #getAccessibleParent
8262                     */
8263                    public int getAccessibleIndexInParent() {
8264                        return index;
8265                    }
8266
8267                    /**
8268                     * Returns the number of accessible children in the object.
8269                     *
8270                     * @return the number of accessible children in the object
8271                     */
8272                    public int getAccessibleChildrenCount() {
8273                        AccessibleContext ac = getCurrentAccessibleContext();
8274                        if (ac != null) {
8275                            return ac.getAccessibleChildrenCount();
8276                        } else {
8277                            return 0;
8278                        }
8279                    }
8280
8281                    /**
8282                     * Returns the specified <code>Accessible</code> child of the
8283                     * object.
8284                     *
8285                     * @param i zero-based index of child
8286                     * @return the <code>Accessible</code> child of the object
8287                     */
8288                    public Accessible getAccessibleChild(int i) {
8289                        AccessibleContext ac = getCurrentAccessibleContext();
8290                        if (ac != null) {
8291                            Accessible accessibleChild = ac
8292                                    .getAccessibleChild(i);
8293                            ac.setAccessibleParent(this );
8294                            return accessibleChild;
8295                        } else {
8296                            return null;
8297                        }
8298                    }
8299
8300                    /**
8301                     * Gets the locale of the component. If the component
8302                     * does not have a locale, then the locale of its parent
8303                     * is returned.
8304                     *
8305                     * @return this component's locale; if this component does
8306                     *    not have a locale, the locale of its parent is returned
8307                     * @exception IllegalComponentStateException if the
8308                     *    <code>Component</code> does not have its own locale
8309                     *    and has not yet been added to a containment hierarchy
8310                     *    such that the locale can be determined from the
8311                     *    containing parent
8312                     * @see #setLocale
8313                     */
8314                    public Locale getLocale() {
8315                        AccessibleContext ac = getCurrentAccessibleContext();
8316                        if (ac != null) {
8317                            return ac.getLocale();
8318                        } else {
8319                            return null;
8320                        }
8321                    }
8322
8323                    /**
8324                     * Adds a <code>PropertyChangeListener</code> to the listener list.
8325                     * The listener is registered for all properties.
8326                     *
8327                     * @param l  the <code>PropertyChangeListener</code>
8328                     *     to be added
8329                     */
8330                    public void addPropertyChangeListener(
8331                            PropertyChangeListener l) {
8332                        AccessibleContext ac = getCurrentAccessibleContext();
8333                        if (ac != null) {
8334                            ac.addPropertyChangeListener(l);
8335                        } else {
8336                            super .addPropertyChangeListener(l);
8337                        }
8338                    }
8339
8340                    /**
8341                     * Removes a <code>PropertyChangeListener</code> from the
8342                     * listener list. This removes a <code>PropertyChangeListener</code>
8343                     * that was registered for all properties.
8344                     *
8345                     * @param l  the <code>PropertyChangeListener</code>
8346                     *    to be removed
8347                     */
8348                    public void removePropertyChangeListener(
8349                            PropertyChangeListener l) {
8350                        AccessibleContext ac = getCurrentAccessibleContext();
8351                        if (ac != null) {
8352                            ac.removePropertyChangeListener(l);
8353                        } else {
8354                            super .removePropertyChangeListener(l);
8355                        }
8356                    }
8357
8358                    /**
8359                     * Gets the <code>AccessibleAction</code> associated with this
8360                     * object if one exists.  Otherwise returns <code>null</code>.
8361                     *
8362                     * @return the <code>AccessibleAction</code>, or <code>null</code>
8363                     */
8364                    public AccessibleAction getAccessibleAction() {
8365                        return getCurrentAccessibleContext()
8366                                .getAccessibleAction();
8367                    }
8368
8369                    /**
8370                     * Gets the <code>AccessibleComponent</code> associated with
8371                     * this object if one exists.  Otherwise returns <code>null</code>.
8372                     *
8373                     * @return the <code>AccessibleComponent</code>, or
8374                     *    <code>null</code>
8375                     */
8376                    public AccessibleComponent getAccessibleComponent() {
8377                        return this ; // to override getBounds()
8378                    }
8379
8380                    /**
8381                     * Gets the <code>AccessibleSelection</code> associated with
8382                     * this object if one exists.  Otherwise returns <code>null</code>.
8383                     *
8384                     * @return the <code>AccessibleSelection</code>, or
8385                     *    <code>null</code>
8386                     */
8387                    public AccessibleSelection getAccessibleSelection() {
8388                        return getCurrentAccessibleContext()
8389                                .getAccessibleSelection();
8390                    }
8391
8392                    /**
8393                     * Gets the <code>AccessibleText</code> associated with this
8394                     * object if one exists.  Otherwise returns <code>null</code>.
8395                     *
8396                     * @return the <code>AccessibleText</code>, or <code>null</code>
8397                     */
8398                    public AccessibleText getAccessibleText() {
8399                        return getCurrentAccessibleContext()
8400                                .getAccessibleText();
8401                    }
8402
8403                    /**
8404                     * Gets the <code>AccessibleValue</code> associated with
8405                     * this object if one exists.  Otherwise returns <code>null</code>.
8406                     *
8407                     * @return the <code>AccessibleValue</code>, or <code>null</code>
8408                     */
8409                    public AccessibleValue getAccessibleValue() {
8410                        return getCurrentAccessibleContext()
8411                                .getAccessibleValue();
8412                    }
8413
8414                    // AccessibleComponent methods
8415
8416                    /**
8417                     * Gets the background color of this object.
8418                     *
8419                     * @return the background color, if supported, of the object;
8420                     *     otherwise, <code>null</code>
8421                     */
8422                    public Color getBackground() {
8423                        AccessibleContext ac = getCurrentAccessibleContext();
8424                        if (ac instanceof  AccessibleComponent) {
8425                            return ((AccessibleComponent) ac).getBackground();
8426                        } else {
8427                            Component c = getCurrentComponent();
8428                            if (c != null) {
8429                                return c.getBackground();
8430                            } else {
8431                                return null;
8432                            }
8433                        }
8434                    }
8435
8436                    /**
8437                     * Sets the background color of this object.
8438                     *
8439                     * @param c the new <code>Color</code> for the background
8440                     */
8441                    public void setBackground(Color c) {
8442                        AccessibleContext ac = getCurrentAccessibleContext();
8443                        if (ac instanceof  AccessibleComponent) {
8444                            ((AccessibleComponent) ac).setBackground(c);
8445                        } else {
8446                            Component cp = getCurrentComponent();
8447                            if (cp != null) {
8448                                cp.setBackground(c);
8449                            }
8450                        }
8451                    }
8452
8453                    /**
8454                     * Gets the foreground color of this object.
8455                     *
8456                     * @return the foreground color, if supported, of the object;
8457                     *     otherwise, <code>null</code>
8458                     */
8459                    public Color getForeground() {
8460                        AccessibleContext ac = getCurrentAccessibleContext();
8461                        if (ac instanceof  AccessibleComponent) {
8462                            return ((AccessibleComponent) ac).getForeground();
8463                        } else {
8464                            Component c = getCurrentComponent();
8465                            if (c != null) {
8466                                return c.getForeground();
8467                            } else {
8468                                return null;
8469                            }
8470                        }
8471                    }
8472
8473                    /**
8474                     * Sets the foreground color of this object.
8475                     *
8476                     * @param c the new <code>Color</code> for the foreground
8477                     */
8478                    public void setForeground(Color c) {
8479                        AccessibleContext ac = getCurrentAccessibleContext();
8480                        if (ac instanceof  AccessibleComponent) {
8481                            ((AccessibleComponent) ac).setForeground(c);
8482                        } else {
8483                            Component cp = getCurrentComponent();
8484                            if (cp != null) {
8485                                cp.setForeground(c);
8486                            }
8487                        }
8488                    }
8489
8490                    /**
8491                     * Gets the <code>Cursor</code> of this object.
8492                     *
8493                     * @return the <code>Cursor</code>, if supported,
8494                     *    of the object; otherwise, <code>null</code>
8495                     */
8496                    public Cursor getCursor() {
8497                        AccessibleContext ac = getCurrentAccessibleContext();
8498                        if (ac instanceof  AccessibleComponent) {
8499                            return ((AccessibleComponent) ac).getCursor();
8500                        } else {
8501                            Component c = getCurrentComponent();
8502                            if (c != null) {
8503                                return c.getCursor();
8504                            } else {
8505                                Accessible ap = getAccessibleParent();
8506                                if (ap instanceof  AccessibleComponent) {
8507                                    return ((AccessibleComponent) ap)
8508                                            .getCursor();
8509                                } else {
8510                                    return null;
8511                                }
8512                            }
8513                        }
8514                    }
8515
8516                    /**
8517                     * Sets the <code>Cursor</code> of this object.
8518                     *
8519                     * @param c the new <code>Cursor</code> for the object
8520                     */
8521                    public void setCursor(Cursor c) {
8522                        AccessibleContext ac = getCurrentAccessibleContext();
8523                        if (ac instanceof  AccessibleComponent) {
8524                            ((AccessibleComponent) ac).setCursor(c);
8525                        } else {
8526                            Component cp = getCurrentComponent();
8527                            if (cp != null) {
8528                                cp.setCursor(c);
8529                            }
8530                        }
8531                    }
8532
8533                    /**
8534                     * Gets the <code>Font</code> of this object.
8535                     *
8536                     * @return the <code>Font</code>,if supported,
8537                     *   for the object; otherwise, <code>null</code>
8538                     */
8539                    public Font getFont() {
8540                        AccessibleContext ac = getCurrentAccessibleContext();
8541                        if (ac instanceof  AccessibleComponent) {
8542                            return ((AccessibleComponent) ac).getFont();
8543                        } else {
8544                            Component c = getCurrentComponent();
8545                            if (c != null) {
8546                                return c.getFont();
8547                            } else {
8548                                return null;
8549                            }
8550                        }
8551                    }
8552
8553                    /**
8554                     * Sets the <code>Font</code> of this object.
8555                     *
8556                     * @param f the new <code>Font</code> for the object
8557                     */
8558                    public void setFont(Font f) {
8559                        AccessibleContext ac = getCurrentAccessibleContext();
8560                        if (ac instanceof  AccessibleComponent) {
8561                            ((AccessibleComponent) ac).setFont(f);
8562                        } else {
8563                            Component c = getCurrentComponent();
8564                            if (c != null) {
8565                                c.setFont(f);
8566                            }
8567                        }
8568                    }
8569
8570                    /**
8571                     * Gets the <code>FontMetrics</code> of this object.
8572                     *
8573                     * @param f the <code>Font</code>
8574                     * @return the <code>FontMetrics</code> object, if supported;
8575                     *    otherwise <code>null</code>
8576                     * @see #getFont
8577                     */
8578                    public FontMetrics getFontMetrics(Font f) {
8579                        AccessibleContext ac = getCurrentAccessibleContext();
8580                        if (ac instanceof  AccessibleComponent) {
8581                            return ((AccessibleComponent) ac).getFontMetrics(f);
8582                        } else {
8583                            Component c = getCurrentComponent();
8584                            if (c != null) {
8585                                return c.getFontMetrics(f);
8586                            } else {
8587                                return null;
8588                            }
8589                        }
8590                    }
8591
8592                    /**
8593                     * Determines if the object is enabled.
8594                     *
8595                     * @return true if object is enabled; otherwise, false
8596                     */
8597                    public boolean isEnabled() {
8598                        AccessibleContext ac = getCurrentAccessibleContext();
8599                        if (ac instanceof  AccessibleComponent) {
8600                            return ((AccessibleComponent) ac).isEnabled();
8601                        } else {
8602                            Component c = getCurrentComponent();
8603                            if (c != null) {
8604                                return c.isEnabled();
8605                            } else {
8606                                return false;
8607                            }
8608                        }
8609                    }
8610
8611                    /**
8612                     * Sets the enabled state of the object.
8613                     *
8614                     * @param b if true, enables this object; otherwise, disables it
8615                     */
8616                    public void setEnabled(boolean b) {
8617                        AccessibleContext ac = getCurrentAccessibleContext();
8618                        if (ac instanceof  AccessibleComponent) {
8619                            ((AccessibleComponent) ac).setEnabled(b);
8620                        } else {
8621                            Component c = getCurrentComponent();
8622                            if (c != null) {
8623                                c.setEnabled(b);
8624                            }
8625                        }
8626                    }
8627
8628                    /**
8629                     * Determines if this object is visible.  Note: this means that the
8630                     * object intends to be visible; however, it may not in fact be
8631                     * showing on the screen because one of the objects that this object
8632                     * is contained by is not visible.  To determine if an object is
8633                     * showing on the screen, use <code>isShowing</code>.
8634                     *
8635                     * @return true if object is visible; otherwise, false
8636                     */
8637                    public boolean isVisible() {
8638                        AccessibleContext ac = getCurrentAccessibleContext();
8639                        if (ac instanceof  AccessibleComponent) {
8640                            return ((AccessibleComponent) ac).isVisible();
8641                        } else {
8642                            Component c = getCurrentComponent();
8643                            if (c != null) {
8644                                return c.isVisible();
8645                            } else {
8646                                return false;
8647                            }
8648                        }
8649                    }
8650
8651                    /**
8652                     * Sets the visible state of the object.
8653                     *
8654                     * @param b if true, shows this object; otherwise, hides it
8655                     */
8656                    public void setVisible(boolean b) {
8657                        AccessibleContext ac = getCurrentAccessibleContext();
8658                        if (ac instanceof  AccessibleComponent) {
8659                            ((AccessibleComponent) ac).setVisible(b);
8660                        } else {
8661                            Component c = getCurrentComponent();
8662                            if (c != null) {
8663                                c.setVisible(b);
8664                            }
8665                        }
8666                    }
8667
8668                    /**
8669                     * Determines if the object is showing.  This is determined
8670                     * by checking the visibility of the object and ancestors
8671                     * of the object.  Note: this will return true even if the
8672                     * object is obscured by another (for example,
8673                     * it happens to be underneath a menu that was pulled down).
8674                     *
8675                     * @return true if the object is showing; otherwise, false
8676                     */
8677                    public boolean isShowing() {
8678                        AccessibleContext ac = getCurrentAccessibleContext();
8679                        if (ac instanceof  AccessibleComponent) {
8680                            if (ac.getAccessibleParent() != null) {
8681                                return ((AccessibleComponent) ac).isShowing();
8682                            } else {
8683                                // Fixes 4529616 - AccessibleJTableCell.isShowing()
8684                                // returns false when the cell on the screen
8685                                // if no parent
8686                                return isVisible();
8687                            }
8688                        } else {
8689                            Component c = getCurrentComponent();
8690                            if (c != null) {
8691                                return c.isShowing();
8692                            } else {
8693                                return false;
8694                            }
8695                        }
8696                    }
8697
8698                    /**
8699                     * Checks whether the specified point is within this
8700                     * object's bounds, where the point's x and y coordinates
8701                     * are defined to be relative to the coordinate system of
8702                     * the object.
8703                     *
8704                     * @param p the <code>Point</code> relative to the
8705                     *    coordinate system of the object
8706                     * @return true if object contains <code>Point</code>;
8707                     *    otherwise false
8708                     */
8709                    public boolean contains(Point p) {
8710                        AccessibleContext ac = getCurrentAccessibleContext();
8711                        if (ac instanceof  AccessibleComponent) {
8712                            Rectangle r = ((AccessibleComponent) ac)
8713                                    .getBounds();
8714                            return r.contains(p);
8715                        } else {
8716                            Component c = getCurrentComponent();
8717                            if (c != null) {
8718                                Rectangle r = c.getBounds();
8719                                return r.contains(p);
8720                            } else {
8721                                return getBounds().contains(p);
8722                            }
8723                        }
8724                    }
8725
8726                    /**
8727                     * Returns the location of the object on the screen.
8728                     *
8729                     * @return location of object on screen -- can be
8730                     *    <code>null</code> if this object is not on the screen
8731                     */
8732                    public Point getLocationOnScreen() {
8733                        if (parent != null) {
8734                            Point parentLocation = parent.getLocationOnScreen();
8735                            Point componentLocation = getLocation();
8736                            componentLocation.translate(parentLocation.x,
8737                                    parentLocation.y);
8738                            return componentLocation;
8739                        } else {
8740                            return null;
8741                        }
8742                    }
8743
8744                    /**
8745                     * Gets the location of the object relative to the parent
8746                     * in the form of a point specifying the object's
8747                     * top-left corner in the screen's coordinate space.
8748                     *
8749                     * @return an instance of <code>Point</code> representing
8750                     *    the top-left corner of the object's bounds in the
8751                     *    coordinate space of the screen; <code>null</code> if
8752                     *    this object or its parent are not on the screen
8753                     */
8754                    public Point getLocation() {
8755                        if (parent != null) {
8756                            Rectangle r = parent
8757                                    .getCellRect(row, column, false);
8758                            if (r != null) {
8759                                return r.getLocation();
8760                            }
8761                        }
8762                        return null;
8763                    }
8764
8765                    /**
8766                     * Sets the location of the object relative to the parent.
8767                     */
8768                    public void setLocation(Point p) {
8769                        //              if ((parent != null)  && (parent.contains(p))) {
8770                        //                  ensureIndexIsVisible(indexInParent);
8771                        //              }
8772                    }
8773
8774                    public Rectangle getBounds() {
8775                        if (parent != null) {
8776                            return parent.getCellRect(row, column, false);
8777                        } else {
8778                            return null;
8779                        }
8780                    }
8781
8782                    public void setBounds(Rectangle r) {
8783                        AccessibleContext ac = getCurrentAccessibleContext();
8784                        if (ac instanceof  AccessibleComponent) {
8785                            ((AccessibleComponent) ac).setBounds(r);
8786                        } else {
8787                            Component c = getCurrentComponent();
8788                            if (c != null) {
8789                                c.setBounds(r);
8790                            }
8791                        }
8792                    }
8793
8794                    public Dimension getSize() {
8795                        if (parent != null) {
8796                            Rectangle r = parent
8797                                    .getCellRect(row, column, false);
8798                            if (r != null) {
8799                                return r.getSize();
8800                            }
8801                        }
8802                        return null;
8803                    }
8804
8805                    public void setSize(Dimension d) {
8806                        AccessibleContext ac = getCurrentAccessibleContext();
8807                        if (ac instanceof  AccessibleComponent) {
8808                            ((AccessibleComponent) ac).setSize(d);
8809                        } else {
8810                            Component c = getCurrentComponent();
8811                            if (c != null) {
8812                                c.setSize(d);
8813                            }
8814                        }
8815                    }
8816
8817                    public Accessible getAccessibleAt(Point p) {
8818                        AccessibleContext ac = getCurrentAccessibleContext();
8819                        if (ac instanceof  AccessibleComponent) {
8820                            return ((AccessibleComponent) ac)
8821                                    .getAccessibleAt(p);
8822                        } else {
8823                            return null;
8824                        }
8825                    }
8826
8827                    public boolean isFocusTraversable() {
8828                        AccessibleContext ac = getCurrentAccessibleContext();
8829                        if (ac instanceof  AccessibleComponent) {
8830                            return ((AccessibleComponent) ac)
8831                                    .isFocusTraversable();
8832                        } else {
8833                            Component c = getCurrentComponent();
8834                            if (c != null) {
8835                                return c.isFocusTraversable();
8836                            } else {
8837                                return false;
8838                            }
8839                        }
8840                    }
8841
8842                    public void requestFocus() {
8843                        AccessibleContext ac = getCurrentAccessibleContext();
8844                        if (ac instanceof  AccessibleComponent) {
8845                            ((AccessibleComponent) ac).requestFocus();
8846                        } else {
8847                            Component c = getCurrentComponent();
8848                            if (c != null) {
8849                                c.requestFocus();
8850                            }
8851                        }
8852                    }
8853
8854                    public void addFocusListener(FocusListener l) {
8855                        AccessibleContext ac = getCurrentAccessibleContext();
8856                        if (ac instanceof  AccessibleComponent) {
8857                            ((AccessibleComponent) ac).addFocusListener(l);
8858                        } else {
8859                            Component c = getCurrentComponent();
8860                            if (c != null) {
8861                                c.addFocusListener(l);
8862                            }
8863                        }
8864                    }
8865
8866                    public void removeFocusListener(FocusListener l) {
8867                        AccessibleContext ac = getCurrentAccessibleContext();
8868                        if (ac instanceof  AccessibleComponent) {
8869                            ((AccessibleComponent) ac).removeFocusListener(l);
8870                        } else {
8871                            Component c = getCurrentComponent();
8872                            if (c != null) {
8873                                c.removeFocusListener(l);
8874                            }
8875                        }
8876                    }
8877
8878                } // inner class AccessibleJTableCell
8879
8880                // Begin AccessibleJTableHeader ========== // TIGER - 4715503 
8881
8882                /**
8883                 * This class implements accessibility for JTable header cells.
8884                 */
8885                private class AccessibleJTableHeaderCell extends
8886                        AccessibleContext implements  Accessible,
8887                        AccessibleComponent {
8888
8889                    private int row;
8890                    private int column;
8891                    private JTableHeader parent;
8892                    private Component rendererComponent;
8893
8894                    /**
8895                     * Constructs an <code>AccessibleJTableHeaderEntry</code> instance.
8896                     *
8897                     * @param row header cell row index
8898                     * @param column header cell column index
8899                     * @param parent header cell parent
8900                     * @param rendererComponent component that renders the header cell
8901                     */
8902                    public AccessibleJTableHeaderCell(int row, int column,
8903                            JTableHeader parent, Component rendererComponent) {
8904                        this .row = row;
8905                        this .column = column;
8906                        this .parent = parent;
8907                        this .rendererComponent = rendererComponent;
8908                        this .setAccessibleParent(parent);
8909                    }
8910
8911                    /**
8912                     * Gets the <code>AccessibleContext</code> associated with this
8913                     * component. In the implementation of the Java Accessibility
8914                     * API for this class, return this object, which is its own
8915                     * <code>AccessibleContext</code>.
8916                     *
8917                     * @return this object
8918                     */
8919                    public AccessibleContext getAccessibleContext() {
8920                        return this ;
8921                    }
8922
8923                    /*
8924                     * Returns the AccessibleContext for the header cell
8925                     * renderer.
8926                     */
8927                    private AccessibleContext getCurrentAccessibleContext() {
8928                        return rendererComponent.getAccessibleContext();
8929                    }
8930
8931                    /*
8932                     * Returns the component that renders the header cell.
8933                     */
8934                    private Component getCurrentComponent() {
8935                        return rendererComponent;
8936                    }
8937
8938                    // AccessibleContext methods ==========
8939
8940                    /**
8941                     * Gets the accessible name of this object.
8942                     *
8943                     * @return the localized name of the object; <code>null</code>
8944                     *     if this object does not have a name
8945                     */
8946                    public String getAccessibleName() {
8947                        AccessibleContext ac = getCurrentAccessibleContext();
8948                        if (ac != null) {
8949                            String name = ac.getAccessibleName();
8950                            if ((name != null) && (name != "")) {
8951                                return ac.getAccessibleName();
8952                            }
8953                        }
8954                        if ((accessibleName != null) && (accessibleName != "")) {
8955                            return accessibleName;
8956                        } else {
8957                            return null;
8958                        }
8959                    }
8960
8961                    /**
8962                     * Sets the localized accessible name of this object.
8963                     *
8964                     * @param s the new localized name of the object
8965                     */
8966                    public void setAccessibleName(String s) {
8967                        AccessibleContext ac = getCurrentAccessibleContext();
8968                        if (ac != null) {
8969                            ac.setAccessibleName(s);
8970                        } else {
8971                            super .setAccessibleName(s);
8972                        }
8973                    }
8974
8975                    /**
8976                     * Gets the accessible description of this object.
8977                     *
8978                     * @return the localized description of the object;
8979                     *     <code>null</code> if this object does not have
8980                     *     a description
8981                     */
8982                    public String getAccessibleDescription() {
8983                        AccessibleContext ac = getCurrentAccessibleContext();
8984                        if (ac != null) {
8985                            return ac.getAccessibleDescription();
8986                        } else {
8987                            return super .getAccessibleDescription();
8988                        }
8989                    }
8990
8991                    /**
8992                     * Sets the accessible description of this object.
8993                     *
8994                     * @param s the new localized description of the object
8995                     */
8996                    public void setAccessibleDescription(String s) {
8997                        AccessibleContext ac = getCurrentAccessibleContext();
8998                        if (ac != null) {
8999                            ac.setAccessibleDescription(s);
9000                        } else {
9001                            super .setAccessibleDescription(s);
9002                        }
9003                    }
9004
9005                    /**
9006                     * Gets the role of this object.
9007                     *
9008                     * @return an instance of <code>AccessibleRole</code>
9009                     *      describing the role of the object
9010                     * @see AccessibleRole
9011                     */
9012                    public AccessibleRole getAccessibleRole() {
9013                        AccessibleContext ac = getCurrentAccessibleContext();
9014                        if (ac != null) {
9015                            return ac.getAccessibleRole();
9016                        } else {
9017                            return AccessibleRole.UNKNOWN;
9018                        }
9019                    }
9020
9021                    /**
9022                     * Gets the state set of this object.
9023                     *
9024                     * @return an instance of <code>AccessibleStateSet</code>
9025                     *     containing the current state set of the object
9026                     * @see AccessibleState
9027                     */
9028                    public AccessibleStateSet getAccessibleStateSet() {
9029                        AccessibleContext ac = getCurrentAccessibleContext();
9030                        AccessibleStateSet as = null;
9031
9032                        if (ac != null) {
9033                            as = ac.getAccessibleStateSet();
9034                        }
9035                        if (as == null) {
9036                            as = new AccessibleStateSet();
9037                        }
9038                        Rectangle rjt = JTable.this .getVisibleRect();
9039                        Rectangle rcell = JTable.this .getCellRect(row, column,
9040                                false);
9041                        if (rjt.intersects(rcell)) {
9042                            as.add(AccessibleState.SHOWING);
9043                        } else {
9044                            if (as.contains(AccessibleState.SHOWING)) {
9045                                as.remove(AccessibleState.SHOWING);
9046                            }
9047                        }
9048                        if (JTable.this .isCellSelected(row, column)) {
9049                            as.add(AccessibleState.SELECTED);
9050                        } else if (as.contains(AccessibleState.SELECTED)) {
9051                            as.remove(AccessibleState.SELECTED);
9052                        }
9053                        if ((row == getSelectedRow())
9054                                && (column == getSelectedColumn())) {
9055                            as.add(AccessibleState.ACTIVE);
9056                        }
9057                        as.add(AccessibleState.TRANSIENT);
9058                        return as;
9059                    }
9060
9061                    /**
9062                     * Gets the <code>Accessible</code> parent of this object.
9063                     *
9064                     * @return the Accessible parent of this object;
9065                     *     <code>null</code> if this object does not
9066                     *     have an <code>Accessible</code> parent
9067                     */
9068                    public Accessible getAccessibleParent() {
9069                        return parent;
9070                    }
9071
9072                    /**
9073                     * Gets the index of this object in its accessible parent.
9074                     *
9075                     * @return the index of this object in its parent; -1 if this
9076                     *     object does not have an accessible parent
9077                     * @see #getAccessibleParent
9078                     */
9079                    public int getAccessibleIndexInParent() {
9080                        return column;
9081                    }
9082
9083                    /**
9084                     * Returns the number of accessible children in the object.
9085                     *
9086                     * @return the number of accessible children in the object
9087                     */
9088                    public int getAccessibleChildrenCount() {
9089                        AccessibleContext ac = getCurrentAccessibleContext();
9090                        if (ac != null) {
9091                            return ac.getAccessibleChildrenCount();
9092                        } else {
9093                            return 0;
9094                        }
9095                    }
9096
9097                    /**
9098                     * Returns the specified <code>Accessible</code> child of the
9099                     * object.
9100                     *
9101                     * @param i zero-based index of child
9102                     * @return the <code>Accessible</code> child of the object
9103                     */
9104                    public Accessible getAccessibleChild(int i) {
9105                        AccessibleContext ac = getCurrentAccessibleContext();
9106                        if (ac != null) {
9107                            Accessible accessibleChild = ac
9108                                    .getAccessibleChild(i);
9109                            ac.setAccessibleParent(this );
9110                            return accessibleChild;
9111                        } else {
9112                            return null;
9113                        }
9114                    }
9115
9116                    /**
9117                     * Gets the locale of the component. If the component
9118                     * does not have a locale, then the locale of its parent
9119                     * is returned.
9120                     *
9121                     * @return this component's locale; if this component does
9122                     *    not have a locale, the locale of its parent is returned
9123                     * @exception IllegalComponentStateException if the
9124                     *    <code>Component</code> does not have its own locale
9125                     *    and has not yet been added to a containment hierarchy
9126                     *    such that the locale can be determined from the
9127                     *    containing parent
9128                     * @see #setLocale
9129                     */
9130                    public Locale getLocale() {
9131                        AccessibleContext ac = getCurrentAccessibleContext();
9132                        if (ac != null) {
9133                            return ac.getLocale();
9134                        } else {
9135                            return null;
9136                        }
9137                    }
9138
9139                    /**
9140                     * Adds a <code>PropertyChangeListener</code> to the listener list.
9141                     * The listener is registered for all properties.
9142                     *
9143                     * @param l  the <code>PropertyChangeListener</code>
9144                     *     to be added
9145                     */
9146                    public void addPropertyChangeListener(
9147                            PropertyChangeListener l) {
9148                        AccessibleContext ac = getCurrentAccessibleContext();
9149                        if (ac != null) {
9150                            ac.addPropertyChangeListener(l);
9151                        } else {
9152                            super .addPropertyChangeListener(l);
9153                        }
9154                    }
9155
9156                    /**
9157                     * Removes a <code>PropertyChangeListener</code> from the
9158                     * listener list. This removes a <code>PropertyChangeListener</code>
9159                     * that was registered for all properties.
9160                     *
9161                     * @param l  the <code>PropertyChangeListener</code>
9162                     *    to be removed
9163                     */
9164                    public void removePropertyChangeListener(
9165                            PropertyChangeListener l) {
9166                        AccessibleContext ac = getCurrentAccessibleContext();
9167                        if (ac != null) {
9168                            ac.removePropertyChangeListener(l);
9169                        } else {
9170                            super .removePropertyChangeListener(l);
9171                        }
9172                    }
9173
9174                    /**
9175                     * Gets the <code>AccessibleAction</code> associated with this
9176                     * object if one exists.  Otherwise returns <code>null</code>.
9177                     *
9178                     * @return the <code>AccessibleAction</code>, or <code>null</code>
9179                     */
9180                    public AccessibleAction getAccessibleAction() {
9181                        return getCurrentAccessibleContext()
9182                                .getAccessibleAction();
9183                    }
9184
9185                    /**
9186                     * Gets the <code>AccessibleComponent</code> associated with
9187                     * this object if one exists.  Otherwise returns <code>null</code>.
9188                     *
9189                     * @return the <code>AccessibleComponent</code>, or
9190                     *    <code>null</code>
9191                     */
9192                    public AccessibleComponent getAccessibleComponent() {
9193                        return this ; // to override getBounds()
9194                    }
9195
9196                    /**
9197                     * Gets the <code>AccessibleSelection</code> associated with
9198                     * this object if one exists.  Otherwise returns <code>null</code>.
9199                     *
9200                     * @return the <code>AccessibleSelection</code>, or
9201                     *    <code>null</code>
9202                     */
9203                    public AccessibleSelection getAccessibleSelection() {
9204                        return getCurrentAccessibleContext()
9205                                .getAccessibleSelection();
9206                    }
9207
9208                    /**
9209                     * Gets the <code>AccessibleText</code> associated with this
9210                     * object if one exists.  Otherwise returns <code>null</code>.
9211                     *
9212                     * @return the <code>AccessibleText</code>, or <code>null</code>
9213                     */
9214                    public AccessibleText getAccessibleText() {
9215                        return getCurrentAccessibleContext()
9216                                .getAccessibleText();
9217                    }
9218
9219                    /**
9220                     * Gets the <code>AccessibleValue</code> associated with
9221                     * this object if one exists.  Otherwise returns <code>null</code>.
9222                     *
9223                     * @return the <code>AccessibleValue</code>, or <code>null</code>
9224                     */
9225                    public AccessibleValue getAccessibleValue() {
9226                        return getCurrentAccessibleContext()
9227                                .getAccessibleValue();
9228                    }
9229
9230                    // AccessibleComponent methods ==========
9231
9232                    /**
9233                     * Gets the background color of this object.
9234                     *
9235                     * @return the background color, if supported, of the object;
9236                     *     otherwise, <code>null</code>
9237                     */
9238                    public Color getBackground() {
9239                        AccessibleContext ac = getCurrentAccessibleContext();
9240                        if (ac instanceof  AccessibleComponent) {
9241                            return ((AccessibleComponent) ac).getBackground();
9242                        } else {
9243                            Component c = getCurrentComponent();
9244                            if (c != null) {
9245                                return c.getBackground();
9246                            } else {
9247                                return null;
9248                            }
9249                        }
9250                    }
9251
9252                    /**
9253                     * Sets the background color of this object.
9254                     *
9255                     * @param c the new <code>Color</code> for the background
9256                     */
9257                    public void setBackground(Color c) {
9258                        AccessibleContext ac = getCurrentAccessibleContext();
9259                        if (ac instanceof  AccessibleComponent) {
9260                            ((AccessibleComponent) ac).setBackground(c);
9261                        } else {
9262                            Component cp = getCurrentComponent();
9263                            if (cp != null) {
9264                                cp.setBackground(c);
9265                            }
9266                        }
9267                    }
9268
9269                    /**
9270                     * Gets the foreground color of this object.
9271                     *
9272                     * @return the foreground color, if supported, of the object;
9273                     *     otherwise, <code>null</code>
9274                     */
9275                    public Color getForeground() {
9276                        AccessibleContext ac = getCurrentAccessibleContext();
9277                        if (ac instanceof  AccessibleComponent) {
9278                            return ((AccessibleComponent) ac).getForeground();
9279                        } else {
9280                            Component c = getCurrentComponent();
9281                            if (c != null) {
9282                                return c.getForeground();
9283                            } else {
9284                                return null;
9285                            }
9286                        }
9287                    }
9288
9289                    /**
9290                     * Sets the foreground color of this object.
9291                     *
9292                     * @param c the new <code>Color</code> for the foreground
9293                     */
9294                    public void setForeground(Color c) {
9295                        AccessibleContext ac = getCurrentAccessibleContext();
9296                        if (ac instanceof  AccessibleComponent) {
9297                            ((AccessibleComponent) ac).setForeground(c);
9298                        } else {
9299                            Component cp = getCurrentComponent();
9300                            if (cp != null) {
9301                                cp.setForeground(c);
9302                            }
9303                        }
9304                    }
9305
9306                    /**
9307                     * Gets the <code>Cursor</code> of this object.
9308                     *
9309                     * @return the <code>Cursor</code>, if supported,
9310                     *    of the object; otherwise, <code>null</code>
9311                     */
9312                    public Cursor getCursor() {
9313                        AccessibleContext ac = getCurrentAccessibleContext();
9314                        if (ac instanceof  AccessibleComponent) {
9315                            return ((AccessibleComponent) ac).getCursor();
9316                        } else {
9317                            Component c = getCurrentComponent();
9318                            if (c != null) {
9319                                return c.getCursor();
9320                            } else {
9321                                Accessible ap = getAccessibleParent();
9322                                if (ap instanceof  AccessibleComponent) {
9323                                    return ((AccessibleComponent) ap)
9324                                            .getCursor();
9325                                } else {
9326                                    return null;
9327                                }
9328                            }
9329                        }
9330                    }
9331
9332                    /**
9333                     * Sets the <code>Cursor</code> of this object.
9334                     *
9335                     * @param c the new <code>Cursor</code> for the object
9336                     */
9337                    public void setCursor(Cursor c) {
9338                        AccessibleContext ac = getCurrentAccessibleContext();
9339                        if (ac instanceof  AccessibleComponent) {
9340                            ((AccessibleComponent) ac).setCursor(c);
9341                        } else {
9342                            Component cp = getCurrentComponent();
9343                            if (cp != null) {
9344                                cp.setCursor(c);
9345                            }
9346                        }
9347                    }
9348
9349                    /**
9350                     * Gets the <code>Font</code> of this object.
9351                     *
9352                     * @return the <code>Font</code>,if supported,
9353                     *   for the object; otherwise, <code>null</code>
9354                     */
9355                    public Font getFont() {
9356                        AccessibleContext ac = getCurrentAccessibleContext();
9357                        if (ac instanceof  AccessibleComponent) {
9358                            return ((AccessibleComponent) ac).getFont();
9359                        } else {
9360                            Component c = getCurrentComponent();
9361                            if (c != null) {
9362                                return c.getFont();
9363                            } else {
9364                                return null;
9365                            }
9366                        }
9367                    }
9368
9369                    /**
9370                     * Sets the <code>Font</code> of this object.
9371                     *
9372                     * @param f the new <code>Font</code> for the object
9373                     */
9374                    public void setFont(Font f) {
9375                        AccessibleContext ac = getCurrentAccessibleContext();
9376                        if (ac instanceof  AccessibleComponent) {
9377                            ((AccessibleComponent) ac).setFont(f);
9378                        } else {
9379                            Component c = getCurrentComponent();
9380                            if (c != null) {
9381                                c.setFont(f);
9382                            }
9383                        }
9384                    }
9385
9386                    /**
9387                     * Gets the <code>FontMetrics</code> of this object.
9388                     *
9389                     * @param f the <code>Font</code>
9390                     * @return the <code>FontMetrics</code> object, if supported;
9391                     *    otherwise <code>null</code>
9392                     * @see #getFont
9393                     */
9394                    public FontMetrics getFontMetrics(Font f) {
9395                        AccessibleContext ac = getCurrentAccessibleContext();
9396                        if (ac instanceof  AccessibleComponent) {
9397                            return ((AccessibleComponent) ac).getFontMetrics(f);
9398                        } else {
9399                            Component c = getCurrentComponent();
9400                            if (c != null) {
9401                                return c.getFontMetrics(f);
9402                            } else {
9403                                return null;
9404                            }
9405                        }
9406                    }
9407
9408                    /**
9409                     * Determines if the object is enabled.
9410                     *
9411                     * @return true if object is enabled; otherwise, false
9412                     */
9413                    public boolean isEnabled() {
9414                        AccessibleContext ac = getCurrentAccessibleContext();
9415                        if (ac instanceof  AccessibleComponent) {
9416                            return ((AccessibleComponent) ac).isEnabled();
9417                        } else {
9418                            Component c = getCurrentComponent();
9419                            if (c != null) {
9420                                return c.isEnabled();
9421                            } else {
9422                                return false;
9423                            }
9424                        }
9425                    }
9426
9427                    /**
9428                     * Sets the enabled state of the object.
9429                     *
9430                     * @param b if true, enables this object; otherwise, disables it
9431                     */
9432                    public void setEnabled(boolean b) {
9433                        AccessibleContext ac = getCurrentAccessibleContext();
9434                        if (ac instanceof  AccessibleComponent) {
9435                            ((AccessibleComponent) ac).setEnabled(b);
9436                        } else {
9437                            Component c = getCurrentComponent();
9438                            if (c != null) {
9439                                c.setEnabled(b);
9440                            }
9441                        }
9442                    }
9443
9444                    /**
9445                     * Determines if this object is visible.  Note: this means that the
9446                     * object intends to be visible; however, it may not in fact be
9447                     * showing on the screen because one of the objects that this object
9448                     * is contained by is not visible.  To determine if an object is
9449                     * showing on the screen, use <code>isShowing</code>.
9450                     *
9451                     * @return true if object is visible; otherwise, false
9452                     */
9453                    public boolean isVisible() {
9454                        AccessibleContext ac = getCurrentAccessibleContext();
9455                        if (ac instanceof  AccessibleComponent) {
9456                            return ((AccessibleComponent) ac).isVisible();
9457                        } else {
9458                            Component c = getCurrentComponent();
9459                            if (c != null) {
9460                                return c.isVisible();
9461                            } else {
9462                                return false;
9463                            }
9464                        }
9465                    }
9466
9467                    /**
9468                     * Sets the visible state of the object.
9469                     *
9470                     * @param b if true, shows this object; otherwise, hides it
9471                     */
9472                    public void setVisible(boolean b) {
9473                        AccessibleContext ac = getCurrentAccessibleContext();
9474                        if (ac instanceof  AccessibleComponent) {
9475                            ((AccessibleComponent) ac).setVisible(b);
9476                        } else {
9477                            Component c = getCurrentComponent();
9478                            if (c != null) {
9479                                c.setVisible(b);
9480                            }
9481                        }
9482                    }
9483
9484                    /**
9485                     * Determines if the object is showing.  This is determined
9486                     * by checking the visibility of the object and ancestors
9487                     * of the object.  Note: this will return true even if the
9488                     * object is obscured by another (for example,
9489                     * it happens to be underneath a menu that was pulled down).
9490                     *
9491                     * @return true if the object is showing; otherwise, false
9492                     */
9493                    public boolean isShowing() {
9494                        AccessibleContext ac = getCurrentAccessibleContext();
9495                        if (ac instanceof  AccessibleComponent) {
9496                            if (ac.getAccessibleParent() != null) {
9497                                return ((AccessibleComponent) ac).isShowing();
9498                            } else {
9499                                // Fixes 4529616 - AccessibleJTableCell.isShowing()
9500                                // returns false when the cell on the screen
9501                                // if no parent
9502                                return isVisible();
9503                            }
9504                        } else {
9505                            Component c = getCurrentComponent();
9506                            if (c != null) {
9507                                return c.isShowing();
9508                            } else {
9509                                return false;
9510                            }
9511                        }
9512                    }
9513
9514                    /**
9515                     * Checks whether the specified point is within this
9516                     * object's bounds, where the point's x and y coordinates
9517                     * are defined to be relative to the coordinate system of
9518                     * the object.
9519                     *
9520                     * @param p the <code>Point</code> relative to the
9521                     *    coordinate system of the object
9522                     * @return true if object contains <code>Point</code>;
9523                     *    otherwise false
9524                     */
9525                    public boolean contains(Point p) {
9526                        AccessibleContext ac = getCurrentAccessibleContext();
9527                        if (ac instanceof  AccessibleComponent) {
9528                            Rectangle r = ((AccessibleComponent) ac)
9529                                    .getBounds();
9530                            return r.contains(p);
9531                        } else {
9532                            Component c = getCurrentComponent();
9533                            if (c != null) {
9534                                Rectangle r = c.getBounds();
9535                                return r.contains(p);
9536                            } else {
9537                                return getBounds().contains(p);
9538                            }
9539                        }
9540                    }
9541
9542                    /**
9543                     * Returns the location of the object on the screen.
9544                     *
9545                     * @return location of object on screen -- can be
9546                     *    <code>null</code> if this object is not on the screen
9547                     */
9548                    public Point getLocationOnScreen() {
9549                        if (parent != null) {
9550                            Point parentLocation = parent.getLocationOnScreen();
9551                            Point componentLocation = getLocation();
9552                            componentLocation.translate(parentLocation.x,
9553                                    parentLocation.y);
9554                            return componentLocation;
9555                        } else {
9556                            return null;
9557                        }
9558                    }
9559
9560                    /**
9561                     * Gets the location of the object relative to the parent
9562                     * in the form of a point specifying the object's
9563                     * top-left corner in the screen's coordinate space.
9564                     *
9565                     * @return an instance of <code>Point</code> representing
9566                     *    the top-left corner of the object's bounds in the
9567                     *    coordinate space of the screen; <code>null</code> if
9568                     *    this object or its parent are not on the screen
9569                     */
9570                    public Point getLocation() {
9571                        if (parent != null) {
9572                            Rectangle r = parent.getHeaderRect(column);
9573                            if (r != null) {
9574                                return r.getLocation();
9575                            }
9576                        }
9577                        return null;
9578                    }
9579
9580                    /** 
9581                     * Sets the location of the object relative to the parent.
9582                     * @param p the new position for the top-left corner
9583                     * @see #getLocation
9584                     */
9585                    public void setLocation(Point p) {
9586                    }
9587
9588                    /** 
9589                     * Gets the bounds of this object in the form of a Rectangle object. 
9590                     * The bounds specify this object's width, height, and location
9591                     * relative to its parent. 
9592                     *
9593                     * @return A rectangle indicating this component's bounds; null if 
9594                     * this object is not on the screen.
9595                     * @see #contains
9596                     */
9597                    public Rectangle getBounds() {
9598                        if (parent != null) {
9599                            return parent.getHeaderRect(column);
9600                        } else {
9601                            return null;
9602                        }
9603                    }
9604
9605                    /** 
9606                     * Sets the bounds of this object in the form of a Rectangle object. 
9607                     * The bounds specify this object's width, height, and location
9608                     * relative to its parent.
9609                     *	
9610                     * @param r rectangle indicating this component's bounds
9611                     * @see #getBounds
9612                     */
9613                    public void setBounds(Rectangle r) {
9614                        AccessibleContext ac = getCurrentAccessibleContext();
9615                        if (ac instanceof  AccessibleComponent) {
9616                            ((AccessibleComponent) ac).setBounds(r);
9617                        } else {
9618                            Component c = getCurrentComponent();
9619                            if (c != null) {
9620                                c.setBounds(r);
9621                            }
9622                        }
9623                    }
9624
9625                    /** 
9626                     * Returns the size of this object in the form of a Dimension object. 
9627                     * The height field of the Dimension object contains this object's
9628                     * height, and the width field of the Dimension object contains this 
9629                     * object's width. 
9630                     *
9631                     * @return A Dimension object that indicates the size of this component; 
9632                     * null if this object is not on the screen
9633                     * @see #setSize
9634                     */
9635                    public Dimension getSize() {
9636                        if (parent != null) {
9637                            Rectangle r = parent.getHeaderRect(column);
9638                            if (r != null) {
9639                                return r.getSize();
9640                            }
9641                        }
9642                        return null;
9643                    }
9644
9645                    /** 
9646                     * Resizes this object so that it has width and height. 
9647                     *	
9648                     * @param d The dimension specifying the new size of the object. 
9649                     * @see #getSize
9650                     */
9651                    public void setSize(Dimension d) {
9652                        AccessibleContext ac = getCurrentAccessibleContext();
9653                        if (ac instanceof  AccessibleComponent) {
9654                            ((AccessibleComponent) ac).setSize(d);
9655                        } else {
9656                            Component c = getCurrentComponent();
9657                            if (c != null) {
9658                                c.setSize(d);
9659                            }
9660                        }
9661                    }
9662
9663                    /**
9664                     * Returns the Accessible child, if one exists, contained at the local 
9665                     * coordinate Point.
9666                     *
9667                     * @param p The point relative to the coordinate system of this object.
9668                     * @return the Accessible, if it exists, at the specified location; 
9669                     * otherwise null
9670                     */
9671                    public Accessible getAccessibleAt(Point p) {
9672                        AccessibleContext ac = getCurrentAccessibleContext();
9673                        if (ac instanceof  AccessibleComponent) {
9674                            return ((AccessibleComponent) ac)
9675                                    .getAccessibleAt(p);
9676                        } else {
9677                            return null;
9678                        }
9679                    }
9680
9681                    /**
9682                     * Returns whether this object can accept focus or not.   Objects that 
9683                     * can accept focus will also have the AccessibleState.FOCUSABLE state 
9684                     * set in their AccessibleStateSets.
9685                     *
9686                     * @return true if object can accept focus; otherwise false
9687                     * @see AccessibleContext#getAccessibleStateSet
9688                     * @see AccessibleState#FOCUSABLE
9689                     * @see AccessibleState#FOCUSED
9690                     * @see AccessibleStateSet
9691                     */
9692                    public boolean isFocusTraversable() {
9693                        AccessibleContext ac = getCurrentAccessibleContext();
9694                        if (ac instanceof  AccessibleComponent) {
9695                            return ((AccessibleComponent) ac)
9696                                    .isFocusTraversable();
9697                        } else {
9698                            Component c = getCurrentComponent();
9699                            if (c != null) {
9700                                return c.isFocusTraversable();
9701                            } else {
9702                                return false;
9703                            }
9704                        }
9705                    }
9706
9707                    /**
9708                     * Requests focus for this object.  If this object cannot accept focus,
9709                     * nothing will happen.  Otherwise, the object will attempt to take
9710                     * focus.
9711                     * @see #isFocusTraversable
9712                     */
9713                    public void requestFocus() {
9714                        AccessibleContext ac = getCurrentAccessibleContext();
9715                        if (ac instanceof  AccessibleComponent) {
9716                            ((AccessibleComponent) ac).requestFocus();
9717                        } else {
9718                            Component c = getCurrentComponent();
9719                            if (c != null) {
9720                                c.requestFocus();
9721                            }
9722                        }
9723                    }
9724
9725                    /**
9726                     * Adds the specified focus listener to receive focus events from this 
9727                     * component. 
9728                     *
9729                     * @param l the focus listener
9730                     * @see #removeFocusListener
9731                     */
9732                    public void addFocusListener(FocusListener l) {
9733                        AccessibleContext ac = getCurrentAccessibleContext();
9734                        if (ac instanceof  AccessibleComponent) {
9735                            ((AccessibleComponent) ac).addFocusListener(l);
9736                        } else {
9737                            Component c = getCurrentComponent();
9738                            if (c != null) {
9739                                c.addFocusListener(l);
9740                            }
9741                        }
9742                    }
9743
9744                    /**
9745                     * Removes the specified focus listener so it no longer receives focus 
9746                     * events from this component.
9747                     *
9748                     * @param l the focus listener
9749                     * @see #addFocusListener
9750                     */
9751                    public void removeFocusListener(FocusListener l) {
9752                        AccessibleContext ac = getCurrentAccessibleContext();
9753                        if (ac instanceof  AccessibleComponent) {
9754                            ((AccessibleComponent) ac).removeFocusListener(l);
9755                        } else {
9756                            Component c = getCurrentComponent();
9757                            if (c != null) {
9758                                c.removeFocusListener(l);
9759                            }
9760                        }
9761                    }
9762
9763                } // inner class AccessibleJTableHeaderCell
9764
9765            } // inner class AccessibleJTable
9766
9767        } // End of Class JTable
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.