home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / swing / JTable.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  135.3 KB  |  3,696 lines

  1. /*
  2.  * @(#)JTable.java    1.71 98/02/12
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20.  
  21. package java.awt.swing;
  22.  
  23. import java.lang.Thread;
  24.  
  25. import java.util.*;
  26.  
  27. import java.awt.*;
  28. import java.awt.event.*;
  29.  
  30. import java.io.Serializable;
  31. import java.io.ObjectOutputStream;
  32. import java.io.ObjectInputStream;
  33. import java.io.IOException;
  34.  
  35. import java.beans.PropertyChangeListener;
  36.  
  37. import java.awt.accessibility.*;
  38.  
  39. import java.awt.swing.*;
  40. import java.awt.swing.event.*;
  41. import java.awt.swing.plaf.*;
  42. import java.awt.swing.table.*;
  43. import java.awt.swing.border.*;
  44.  
  45. /**
  46.  *  WARNING: The API and internal implementation of the JTable have changed a great
  47.  *  deal since swing release 0.6.1; the reasons for the changes, details of
  48.  *  the public methods which have changed and some advice for porting code
  49.  *  based on the old API are are given in the README.txt files of this distribution.
  50.  *  <p>
  51.  *  JTable is a user-interface component that presents data in a two-dimensional
  52.  *  table format. The JTable has many features that make it possible to
  53.  *  customize its rendering and editing but provides defaults
  54.  *  for these features so that simple tables can be set up easily.
  55.  *  For example, to set up a table with 10 rows and 10 columns of numbers:
  56.  *  <p>
  57.  *  <pre>
  58.  *       TableModel dataModel = new AbstractTableModel() {
  59.  *           public int getColumnCount() { return 10; }
  60.  *           public int getRowCount() { return 10;}
  61.  *           public Object getValueAt(int row, int col) { return new Integer(row*col); }
  62.  *       };
  63.  *       JTable table = new JTable(dataModel);
  64.  *       JScrollPane scrollpane = JTable.createScrollPaneForTable(table);
  65.  *  </pre>
  66.  *  <p>
  67.  *  Because the JTable is now much easier to set up with custom models
  68.  *  the DefaultTableModel is less useful than it was in previous releases.
  69.  *  Instead of copying the data in an application into the DefaultTableModel,
  70.  *  we recommend wrapping it in the methods of the TableModel interface and
  71.  *  passing the real data to the JTable as above. This technique is nearly as concise
  72.  *  as using a DefaultTableModel and starting this way has a number of advantages
  73.  *  over the longer term. In particular: it is a scalable technique,
  74.  *  is easier to handle dynamic or editable tables and often results in much
  75.  *  more efficient applications because the model is free to choose the
  76.  *  internal representation that best suits the data.
  77.  *  <p>
  78.  *  The "Table" directory in the examples/demo area gives a number of complete
  79.  *  examples of JTable usage, covering how the JTable can be used to provide
  80.  *  an editable view of data taken from a database and how to modify the columns
  81.  *  in the display to use specialized renderers and editors.
  82.  *  <p>
  83.  *  Instead of using integers and identifiers for the columns, the JTable now
  84.  *  uses integers exclusively to refer to both the rows and the columns. As well as
  85.  *  simplifying the API considerably by removing all the methods that had to
  86.  *  be implemented for both integers and identifiers this has made
  87.  *  future rendering optimizations possible behind the same API.
  88.  *  <p>
  89.  *  It is still possible to build TableModels which use identifiers, either for
  90.  *  the columns or the rows and this can be a good way to
  91.  *  give meaning to data values which is independent of position.
  92.  *  That said, the JTable no longer requires the model to manage identifiers
  93.  *  and these methods have been removed from the TableModel interface.
  94.  *  The JTable simply takes a tabular range of cells and uses
  95.  *  <code>getValueAt(int, int)</code> to retrieve and display them.
  96.  *  <p>
  97.  *  If <code>getTableHeader().setReorderingAllowed(boolean)</code> is used to
  98.  *  enable column reordering columns may be rearranged in the JTable so that the
  99.  *  view's columns appear in a different order to the columns in the model.
  100.  *  This does not affect the implementation of the model at all: when the
  101.  *  columns are reordered, the JTable maintains the new order of the columns
  102.  *  internally and converts its column indices before querying the model.
  103.  *  So, when writing a TableModel, it is not necessary to listen for column
  104.  *  reordering events as the the model is queried in its own co-ordinate
  105.  *  system regardless of what is happening in the view.
  106.  *  In the examples area there is a demonstration of a sorting algorithm making
  107.  *  use of exactly this technique to interpose yet another co-ordinate system
  108.  *  where the order of the rows is changed, rather than the order of the columns.
  109.  *  <p>
  110.  *  The general rule for the JTable API and the APIs of all its associated classes,
  111.  *  including the the column model and both the row and column selection models, is
  112.  *  the same as it was in previous releases: methods using integer indices for rows
  113.  *  and columns always use the co-ordinate system of the view. There are three
  114.  *  exceptions to this rule:
  115.  *  <ul>
  116.  *  <li> All references to rows and columns in the TableModel
  117.  *       interface are in the co-ordinate system of the model.
  118.  *  <li> The index <I>modelIndex</I> in the TableColumn constructors
  119.  *       refers to the index of the column in the model, not the view.
  120.  *  <li> All constructors for the TableModelEvent, which describes changes
  121.  *       that have taken place in a table model, use the co-ordinate system
  122.  *       of the model.
  123.  *  </ul>
  124.  *  The TableColumn continues to provide a slot for holding an identifier or
  125.  *  "tag" and the JTable and TableColumModel both continue to support their
  126.  *  <I>getColumn(Object id)</I> conveniences for locating columns by their
  127.  *  identifier. If no identifier is explicitly set, the TableColumn returns
  128.  *  its header value (the name of the column) as a default. A different identifier,
  129.  *  which can be of any type, can be set using the TableColumn's <I>setIdentifier()</I>
  130.  *  method. All of the JTable's functions now operate correctly regardless of the
  131.  *  type and uniqueness of these identifiers.
  132.  *  <p>
  133.  *  The <I>convertColumnIndexToView()</I> and
  134.  *  <I>convertColumnIndexToModel()</I> methods have been provided to
  135.  *  convert between the two co-ordinate systems but
  136.  *  they are rarely needed during normal use.
  137.  * <p>
  138.  * See <a href="http://java.sun.com/docs/books/tutorial/ui/swing/table.html">How to Use Tables</a>
  139.  * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
  140.  * for further documentation.
  141.  * <p>
  142.  * Warning: serialized objects of this class will not be compatible with
  143.  * future swing releases.  The current serialization support is appropriate
  144.  * for short term storage or RMI between Swing1.0 applications.  It will
  145.  * not be possible to load serialized Swing1.0 objects with future releases
  146.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  147.  * baseline for the serialized form of Swing objects.
  148.  *
  149.  *
  150.  * @beaninfo
  151.  *   attribute: isContainer false
  152.  *
  153.  * @version 1.71 02/12/98
  154.  * @author Alan Chung
  155.  * @author Philip Milne
  156.  */
  157. public class JTable extends JComponent implements TableModelListener, Scrollable,
  158.     TableColumnModelListener, ListSelectionListener, CellEditorListener,
  159.     Accessible
  160. {
  161. //
  162. // Static Constants
  163. //
  164.  
  165.     /** Do not auto resize column when table is resized. */
  166.     public static final int     AUTO_RESIZE_OFF = 0;
  167.  
  168.     /** Auto resize last column only when table is resized */
  169.     public static final int     AUTO_RESIZE_LAST_COLUMN = 1;
  170.  
  171.     /** Proportionately resize all columns when table is resized */
  172.     public static final int     AUTO_RESIZE_ALL_COLUMNS = 2;
  173.  
  174.  
  175. //
  176. // Instance Variables
  177. //
  178.  
  179.     /** The TableModel of the table */
  180.     protected TableModel        dataModel;
  181.  
  182.     /** The TableColumnModel of the table */
  183.     protected TableColumnModel  columnModel;
  184.  
  185.     /** The ListSelectionModel of the table, used to keep track of row selections */
  186.     protected ListSelectionModel selectionModel;
  187.  
  188.     /** The TableHeader working with the table */
  189.     protected JTableHeader      tableHeader;
  190.  
  191.     /** The height of all rows in the table */
  192.     protected int               rowHeight;
  193.  
  194.     /** The height margin between rows */
  195.     protected int               rowMargin;
  196.  
  197.     /** The color of the grid */
  198.     protected Color             gridColor;
  199.  
  200.     /** The table draws horizontal lines between cells if showHorizontalLines is true */
  201.     protected boolean           showHorizontalLines;
  202.  
  203.     /** The table draws vertical lines between cells if showVerticalLines is true */
  204.     protected boolean           showVerticalLines;
  205.  
  206.     /**
  207.      *  This mode value determines if table automatically resizes the
  208.      *  width the table's columns to take up the entire width of the
  209.      *  table, and how it does the resizing.
  210.      */
  211.     protected int               autoResizeMode;
  212.  
  213.     /**
  214.      *  The table will query the TableModel to build the default
  215.      *  set of columns if this is true.
  216.      */
  217.     protected boolean           autoCreateColumnsFromModel;
  218.  
  219.     /** Used by the Scrollable interface to determine the initial visible area */
  220.     protected Dimension         preferredViewportSize;
  221.  
  222.     /** Row selection allowed in this table */
  223.     protected boolean           rowSelectionAllowed;
  224.  
  225.     /**
  226.      * If this is true, then both a row selection and a column selection
  227.      * can be non-empty at the same time, the selected cells are the
  228.      * the cells whose row and column are both selected.
  229.      */
  230.     protected boolean           cellSelectionEnabled;
  231.  
  232.     /** If editing, Component that is handling the editing. */
  233.     transient protected Component       editorComp;
  234.  
  235.     /**
  236.      * The object that overwrites the screen real estate occupied by the
  237.      * current cell and allows the user to change those contents.
  238.      */
  239.     transient protected TableCellEditor cellEditor;
  240.  
  241.     /** Identifies the column of the cell being edited. */
  242.     transient protected int             editingColumn;
  243.  
  244.     /** Identifies the row of the cell being edited. */
  245.     transient protected int             editingRow;
  246.  
  247.     /**
  248.      * A table of objects that display the contents of a cell,
  249.      * indexed by class.
  250.      */
  251.     transient protected Hashtable defaultRenderersByColumnClass;
  252.  
  253.     /**
  254.      * A table of objects that display and edit the contents of a cell,
  255.      * indexed by class.
  256.      */
  257.     transient protected Hashtable defaultEditorsByColumnClass;
  258.  
  259.     /** The foreground color of selected cells */
  260.     protected Color selectionForeground;
  261.  
  262.     /** The background color of selected cells */
  263.     protected Color selectionBackground;
  264.  
  265. //
  266. // Constructors
  267. //
  268.  
  269.     /**
  270.      * Constructs a default JTable which is initialized with a default
  271.      * data model, a default column model, and a default selection
  272.      * model.
  273.      *
  274.      * @see #createDefaultDataModel()
  275.      * @see #createDefaultColumnModel()
  276.      * @see #createDefaultSelectionModel()
  277.      */
  278.     public JTable() {
  279.         this(null, null, null);
  280.     }
  281.  
  282.     /**
  283.      * Constructs a JTable which is initialized with <i>dm</i> as the
  284.      * data model, a default column model, and a default selection
  285.      * model.
  286.      *
  287.      * @param dm        The data model for the table
  288.      * @see #createDefaultColumnModel()
  289.      * @see #createDefaultSelectionModel()
  290.      */
  291.     public JTable(TableModel dm) {
  292.         this(dm, null, null);
  293.     }
  294.  
  295.     /**
  296.      * Constructs a JTable which is initialized with <i>dm</i> as the
  297.      * data model, <i>cm</i> as the column model, and a default selection
  298.      * model.
  299.      *
  300.      * @param dm        The data model for the table
  301.      * @param cm        The column model for the table
  302.      * @see #createDefaultSelectionModel()
  303.      */
  304.     public JTable(TableModel dm, TableColumnModel cm) {
  305.         this(dm, cm, null);
  306.     }
  307.  
  308.     /**
  309.      * Constructs a JTable which is initialized with <i>dm</i> as the
  310.      * data model, <i>cm</i> as the column model, and <i>sm</i> as the
  311.      * selection model.  If any of the parameters are <b>null</b> this
  312.      * method will initialize the table with the corresponding
  313.      * default model.
  314.      *
  315.      * @param dm        The data model for the table
  316.      * @param cm        The column model for the table
  317.      * @param sm        The row selection model for the table
  318.      * @see #createDefaultDataModel()
  319.      * @see #createDefaultColumnModel()
  320.      * @see #createDefaultSelectionModel()
  321.      */
  322.     public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
  323.         super();
  324.         setLayout(null);
  325.  
  326.         if (dm == null)
  327.             dm = createDefaultDataModel();
  328.         setModel(dm);
  329.  
  330.         if (cm == null)
  331.             cm = createDefaultColumnModel();
  332.         setColumnModel(cm);
  333.  
  334.         if (sm == null)
  335.             sm = createDefaultSelectionModel();
  336.         setSelectionModel(sm);
  337.  
  338.         initializeLocalVars();
  339.         updateUI();
  340.     }
  341.  
  342.     /**
  343.      * Constructs a JTable with <i>numColumns</i> and <i>numRows</i> of
  344.      * empty cells using the DefaultTableModel.  The columns will have
  345.      * names of the form "A", "B", "C", etc.
  346.      *
  347.      * @param numColumns        The number of columns the table holds
  348.      * @param numRows           The number of rows the table holds
  349.      * @see java.awt.swing.table.DefaultTableModel
  350.      */
  351.     public JTable(int numColumns, int numRows) {
  352.         this(new DefaultTableModel(numColumns, numRows));
  353.     }
  354.  
  355.     /**
  356.      * Constructs a JTable using a DefaultTableModel and initialize the table
  357.      * with the values in the <i>data</i> Vector.  The vectors contained
  358.      * in the outer vector should each contain a single row of values.
  359.      * In other words, the value of the cell at column 5, row 1
  360.      * can be obtain with the follow code: <p>
  361.      *
  362.      * <code>((Vector)data.elementAt(1)).elementAt(5);</code>
  363.      *
  364.      * @param data              The data for the new table
  365.      * @param columnNames       Names of each column
  366.      * @exception IllegalArgumentException if data is null or if the number
  367.      *                          of columns in data does not equal the
  368.      *                          number of names in columnNames.
  369.      */
  370.     public JTable(Vector data, Vector columnNames) {
  371.         this(new DefaultTableModel(data, columnNames));
  372.     }
  373.  
  374.     /**
  375.      * Constructs a JTable using a DefaultTableModel and initialize the
  376.      * table with the values in the <i>data</i> array.  The first index
  377.      * in the Object[][] is the row index and the second is
  378.      * the column index.
  379.      *
  380.      * @param data              The data for the new table
  381.      * @param columnNames       Names of each column
  382.      * @exception IllegalArgumentException if data is null or if the number
  383.      *                          of columns in data does not equal the
  384.      *                          number of names in columnNames.
  385.      */
  386.     public JTable(Object[][] data, Object[] columnNames) {
  387.         this(new DefaultTableModel(data, columnNames));
  388.     }
  389.  
  390. //
  391. // Static Methods
  392. //
  393.  
  394.     /**
  395.      * This static method is provided to simplify the task of wrapping
  396.      * a JTable in a scroll pane.  This method will take care of
  397.      * putting the table and its header in the correct place.  If <i>aTable</i>
  398.      * is <b>null</b> this will create a default JTable.
  399.      *
  400.      * @param aTable    The table to install in a scrollPane.
  401.      */
  402.     static public JScrollPane createScrollPaneForTable(JTable aTable) {
  403.         if (aTable == null) {
  404.             aTable = new JTable();
  405.         }
  406.         JScrollPane scrollpane = new JScrollPane(aTable);
  407.         scrollpane.setColumnHeaderView(aTable.getTableHeader());
  408.         scrollpane.getViewport().setBackingStoreEnabled(true);
  409.     scrollpane.setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
  410.         return scrollpane;
  411.     }
  412.  
  413. //
  414. // Table Attributes
  415. //
  416.  
  417.     /**
  418.      * Sets the tableHeader working with this JTable to <I>newHeader</I>.
  419.      * It is legal to have a <B>null</B> tableHeader.
  420.      *
  421.      * @param   newHeader                       new tableHeader
  422.      * @see     #getTableHeader()
  423.      * @beaninfo
  424.      * description: The JTableHeader instance which renders the column headers.
  425.      */
  426.     public void setTableHeader(JTableHeader newHeader) {
  427.         if (tableHeader != newHeader) {
  428.             // Release the old header
  429.             if (tableHeader != null)
  430.                 tableHeader.setTable(null);
  431.  
  432.             tableHeader = newHeader;
  433.             if (tableHeader != null)
  434.                 tableHeader.setTable(this);
  435.         }
  436.     }
  437.  
  438.     /**
  439.      * Returns the tableHeader working with this JTable.
  440.      *
  441.      * @return  the tableHeader working with the receiver
  442.      * @see     #setTableHeader()
  443.      */
  444.     public JTableHeader getTableHeader() {
  445.         return tableHeader;
  446.     }
  447.  
  448.     /**
  449.      * Sets the height for rows to <I>newRowHeight</I> and invokes tile
  450.      *
  451.      * @param   newRowHeight                    new row height
  452.      * @exception IllegalArgumentException      If <I>newRowHeight</I> is
  453.      *                                          less than 1.
  454.      * @see     #getRowHeight()
  455.      * @beaninfo
  456.      * description: The height of the cells including the inter-cell spacing.
  457.      */
  458.     public void setRowHeight(int newHeight) {
  459.         if (newHeight <= 0) {
  460.             throw new IllegalArgumentException("New row height less than 1");
  461.         }
  462.         rowHeight = newHeight;
  463.  
  464.         resizeAndRepaint();
  465.     }
  466.  
  467.     /**
  468.      * Returns the height of a table row in the receiver.
  469.      * The default row height is 16.0.
  470.      *
  471.      * @return  the height of each row in the receiver
  472.      * @see     #setRowHeight()
  473.      */
  474.     public int getRowHeight() {
  475.         return rowHeight;
  476.     }
  477.  
  478.     /**
  479.      * Sets the width and height between cells to <I>newSpacing</I> and
  480.      * redisplays the receiver.
  481.      *
  482.      * @param   newSpacing              The new width and height intercellSpacing
  483.      * @see     #getIntercellSpacing()
  484.      * @beaninfo
  485.      * description: The spacing between the cells, drawn in the background color of the JTable.
  486.      */
  487.     public void setIntercellSpacing(Dimension newSpacing) {
  488.         // Set the rowMargin here and columnMargin in the TableColumnModel
  489.         rowMargin = newSpacing.height;
  490.         getColumnModel().setColumnMargin(newSpacing.width);
  491.  
  492.         resizeAndRepaint();
  493.     }
  494.  
  495.     /**
  496.      * Returns the horizontal and vertical spacing between cells.
  497.      * The default spacing is (3, 2).
  498.      *
  499.      * @return  the horizontal and vertical spacing between cells
  500.      * @see     #setIntercellSpacing()
  501.      */
  502.     public Dimension getIntercellSpacing() {
  503.         return new Dimension(getColumnModel().getColumnMargin(), rowMargin);
  504.     }
  505.  
  506.     /**
  507.      * Sets the color used to draw grid lines to <I>color</I> and redisplays
  508.      * the receiver.
  509.      * The default color is gray.
  510.      *
  511.      * @param   color                           new color of the grid
  512.      * @exception IllegalArgumentException      if <I>color</I> is null
  513.      * @see     #getGridColor()
  514.      */
  515.     public void setGridColor(Color newColor) {
  516.         if (newColor == null) {
  517.             throw new IllegalArgumentException("New color is null");
  518.         }
  519.         gridColor = newColor;
  520.  
  521.         // Redraw
  522.         repaint();
  523.     }
  524.  
  525.     /**
  526.      * Returns the color used to draw grid lines. The default color is gray.
  527.      *
  528.      * @return  the color used to draw grid lines
  529.      * @see     #setGridColor()
  530.      */
  531.     public Color getGridColor() {
  532.         return gridColor;
  533.     }
  534.  
  535.     /**
  536.      *  Sets whether the receiver draws grid lines around cells.
  537.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  538.      *  There is no getShowGrid() method as the this state is held
  539.      *  in two variables: showHorizontalLines and showVerticalLines
  540.      *  each of which may be queried independently.
  541.      *
  542.      * @param   flag                    true if table view should draw grid lines
  543.      *
  544.      * @see     #setShowVerticalLines
  545.      * @see     #setShowHorizontalLines
  546.      * @beaninfo
  547.      * description: The color used to draw the grid lines.
  548.      */
  549.     public void setShowGrid(boolean b) {
  550.         setShowHorizontalLines(b);
  551.         setShowVerticalLines(b);
  552.  
  553.         // Redraw
  554.         repaint();
  555.     }
  556.  
  557.     /**
  558.      *  Sets whether the receiver draws horizontal lines between cells.
  559.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  560.      *
  561.      * @param   flag                    true if table view should draw horizontal lines
  562.      * @see     #getShowHorizontalLines
  563.      * @see     #setShowGrid
  564.      * @see     #setShowVerticalLines
  565.      * @beaninfo
  566.      * description: Whether horizontal lines should be drawn in between the cells.
  567.      */
  568.     public void setShowHorizontalLines(boolean b) {
  569.         showHorizontalLines = b;
  570.  
  571.         // Redraw
  572.         repaint();
  573.     }
  574.  
  575.     /**
  576.      *  Sets whether the receiver draws vertical lines between cells.
  577.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  578.      *
  579.      * @param   flag                    true if table view should draw vertical lines
  580.      * @see     #getShowVerticalLines
  581.      * @see     #setShowGrid
  582.      * @see     #setShowHorizontalLines
  583.      * @beaninfo
  584.      * description: Whether vertical lines should be drawn in between the cells.
  585.      */
  586.     public void setShowVerticalLines(boolean b) {
  587.         showVerticalLines = b;
  588.  
  589.         // Redraw
  590.         repaint();
  591.     }
  592.  
  593.     /**
  594.      * Returns true if the receiver draws horizontal lines between cells, false if it
  595.      * doesn't. The default is true.
  596.      *
  597.      * @return  true if the receiver draws horizontal lines between cells, false if it
  598.      *          doesn't
  599.      * @see     #setShowHorizontalLines
  600.      */
  601.     public boolean getShowHorizontalLines() {
  602.         return showHorizontalLines;
  603.     }
  604.  
  605.     /**
  606.      * Returns true if the receiver draws vertical lines between cells, false if it
  607.      * doesn't. The default is true.
  608.      *
  609.      * @return  true if the receiver draws vertical lines between cells, false if it
  610.      *          doesn't
  611.      * @see     #setShowVerticalLines
  612.      */
  613.     public boolean getShowVerticalLines() {
  614.         return showVerticalLines;
  615.     }
  616.  
  617.     /**
  618.      * Sets the table's auto resize mode when the table is resized.
  619.      *
  620.      * @param   mode            One of 3 legal values: AUTO_RESIZE_OFF,
  621.      *                          AUTO_RESIZE_LAST_COLUMN, AUTO_RESIZE_ALL_COLUMNS
  622.      *
  623.      * @see     #getAutoResizeMode()
  624.      * @see     #sizeColumnsToFit()
  625.      * @beaninfo
  626.      * description: Whether the columns should adjust themselves automatically to accomodate changes.
  627.      *        enum: AUTO_RESIZE_OFF          JTable.AUTO_RESIZE_OFF
  628.      *              AUTO_RESIZE_LAST_COLUMN  JTable.AUTO_RESIZE_LAST_COLUMN
  629.      *              AUTO_RESIZE_ALL_COLUMNS  JTable.AUTO_RESIZE_ALL_COLUMNS
  630.      */
  631.     public void setAutoResizeMode(int mode) {
  632.         if ((mode == AUTO_RESIZE_ALL_COLUMNS) ||
  633.             (mode == AUTO_RESIZE_LAST_COLUMN) ||
  634.             (mode == AUTO_RESIZE_OFF)) {
  635.             autoResizeMode = mode;
  636.             resizeAndRepaint();
  637.             tableHeader.resizeAndRepaint();
  638.         }
  639.     }
  640.  
  641.     /**
  642.      * Returns auto resize mode of the table.  The default is
  643.      * AUTO_RESIZE_ALL_COLUMNS.
  644.      *
  645.      * @return  the autoResizeMode of the table
  646.      *
  647.      * @see     #setAutoResizeMode()
  648.      * @see     #sizeColumnsToFit()
  649.      */
  650.     public int getAutoResizeMode() {
  651.         return autoResizeMode;
  652.     }
  653.  
  654.     /**
  655.      * Sets the table's autoCreateColumnsFromModel flag.  This method
  656.      * will call createDefaultColumnsFromModel() if <i>createColumns</i>
  657.      * is true.
  658.      *
  659.      * @param   createColumns   true if JTable should auto create columns
  660.      * @see     #getAutoCreateColumnsFromModel()
  661.      * @see     #createDefaultColumnsFromModel()
  662.      * @beaninfo
  663.      * description: Automatically populate the columnModel when a new TableModel is submitted.
  664.      */
  665.     public void setAutoCreateColumnsFromModel(boolean createColumns) {
  666.         if (autoCreateColumnsFromModel != createColumns) {
  667.             autoCreateColumnsFromModel = createColumns;
  668.  
  669.             if (autoCreateColumnsFromModel)
  670.                 createDefaultColumnsFromModel();
  671.         }
  672.     }
  673.  
  674.     /**
  675.      * Returns whether the table will create default columns from the model.
  676.      * If this is true, setModel() will clear any existing columns and
  677.      * create new columns from the new model.  Also if the event in the
  678.      * the tableChanged() notification specified the entired table changed
  679.      * then the columns will be rebuilt.  The default is true.
  680.      *
  681.      * @return  the autoCreateColumnsFromModel of the table
  682.      * @see     #setAutoCreateColumnsFromModel()
  683.      * @see     #createDefaultColumnsFromModel()
  684.      */
  685.     public boolean getAutoCreateColumnsFromModel() {
  686.         return autoCreateColumnsFromModel;
  687.     }
  688.  
  689.     /**
  690.      * This method will create default columns for the table from
  691.      * the data model using the getColumnCount() and getColumnType() methods
  692.      * defined in the TableModel interface.
  693.      * <p>
  694.      * This method will clear any exsiting columns before creating the
  695.      * new columns based on information from the model.
  696.      *
  697.      * @see     #getAutoCreateColumnsFromModel()
  698.      */
  699.     public void createDefaultColumnsFromModel() {
  700.         TableModel m = getModel();
  701.         if (m != null) {
  702.             // Remove any current columns
  703.             TableColumnModel cm = getColumnModel();
  704.             cm.removeColumnModelListener(this);
  705.             while (cm.getColumnCount() > 0)
  706.                 cm.removeColumn(cm.getColumn(0));
  707.  
  708.             // Create new columns from the data model info
  709.             for (int i = 0; i < m.getColumnCount(); i++) {
  710.                 TableColumn newColumn = new TableColumn(i);
  711.                 addColumn(newColumn);
  712.             }
  713.             cm.addColumnModelListener(this);
  714.         }
  715.     }
  716.  
  717.     /**
  718.      * Set a default renderer to be used if no renderer has been set in
  719.      * a TableColumn.
  720.      *
  721.      * @see     #getDefaultRenderer
  722.      * @see     #setDefaultEditor
  723.      */
  724.     public void setDefaultRenderer(Class columnClass, TableCellRenderer renderer) {
  725.         defaultRenderersByColumnClass.put(columnClass, renderer);
  726.     }
  727.  
  728.     /**
  729.      * Returns the renderer to be used when no renderer has been set in
  730.      * a TableColumn. During the rendering of cells the renderer is fetched from
  731.      * a Hashtable of entries according to the class of the cells in the column. If
  732.      * there is no entry for this <I>columnClass</I> the method returns
  733.      * the entry for the most specific superclass. The JTable installs entries
  734.      * for <I>Object</I>, <I>Number</I> and <I>Boolean</I> all which can be modified
  735.      * or replaced.
  736.      *
  737.      * @see     #setDefaultRenderer
  738.      * @see     #getColumnClass
  739.      */
  740.     public TableCellRenderer getDefaultRenderer(Class columnClass) {
  741.         if (columnClass == null) {
  742.             return null;
  743.         }
  744.         else {
  745.             Object renderer = defaultRenderersByColumnClass.get(columnClass);
  746.             if (renderer != null) {
  747.                 return (TableCellRenderer)renderer;
  748.             }
  749.             else {
  750.                 return getDefaultRenderer(columnClass.getSuperclass());
  751.             }
  752.         }
  753.     }
  754.  
  755.     /**
  756.      * Set a default editor to be used if no editor has been set in
  757.      * a TableColumn. If no editing is required in a table or a
  758.      * particular column in a table use the isCellEditable()
  759.      * method in the TableModel interface to ensure that the
  760.      * JTable will not start an editor in these columns.
  761.      *
  762.      * @see     TableModel#isCellEditable
  763.      * @see     #getDefaultEditor
  764.      * @see     #setDefaultRenderer
  765.      */
  766.     public void setDefaultEditor(Class columnClass, TableCellEditor editor) {
  767.         defaultEditorsByColumnClass.put(columnClass, editor);
  768.     }
  769.  
  770.     /**
  771.      * Returns the editor to be used when no editor has been set in
  772.      * a TableColumn. During the editing of cells the editor is fetched from
  773.      * a Hashtable of entries according to the class of the cells in the column. If
  774.      * there is no entry for this <I>columnClass</I> the method returns
  775.      * the entry for the most specific superclass. The JTable installs entries
  776.      * for <I>Object</I>, <I>Number</I> and <I>Boolean</I> all which can be modified
  777.      * or replaced.
  778.      *
  779.      * @see     #setDefaultEditor
  780.      * @see     #getColumnClass
  781.      */
  782.     public TableCellEditor getDefaultEditor(Class columnClass) {
  783.         if (columnClass == null) {
  784.             return null;
  785.         }
  786.         else {
  787.             Object editor = defaultEditorsByColumnClass.get(columnClass);
  788.             if (editor != null) {
  789.                 return (TableCellEditor)editor;
  790.             }
  791.             else {
  792.                 return getDefaultEditor(columnClass.getSuperclass());
  793.             }
  794.         }
  795.     }
  796.  
  797. //
  798. // Selection methods
  799. //
  800.     /**
  801.      * Sets the table's selection mode to allow only single selections, a single
  802.      * contiguous interval, or multiple intervals.
  803.      *
  804.      * NOTE:<br>
  805.      * JTable provides all the methods for handling column and row selection.
  806.      * When setting states, such as setSelectionMode, it not only
  807.      * updates the mode for the row selection model but also sets similar
  808.      * values in the selection model of the columnModel.
  809.      * If you want to have states that is different between rows and columns
  810.      * you can get the columnModel and change that directly.
  811.      * <p>
  812.      * Both the row and column selection models for the JTable default
  813.      * to using a DefaultListSelectionModel so that JTable works the same
  814.      * way as the JList. See setSelectionMode() in JList for details
  815.      * about the modes.
  816.      *
  817.      * @see JList#setSelectionMode
  818.      * @beaninfo
  819.      * description: The selection mode used by the row and column selection models.
  820.      *        enum: SINGLE_SELECTION            ListSelectionModel.SINGLE_SELECTION
  821.      *              SINGLE_INTERVAL_SELECTION   ListSelectionModel.SINGLE_INTERVAL_SELECTION
  822.      *              MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
  823.      */
  824.     public void setSelectionMode(int selectionMode) {
  825.         clearSelection();
  826.         getSelectionModel().setSelectionMode(selectionMode);
  827.         getColumnModel().getSelectionModel().setSelectionMode(selectionMode);
  828.     }
  829.  
  830.     /**
  831.      * Sets whether the rows in this model can be selected.
  832.      *
  833.      * @see #getRowSelectionAllowed()
  834.      * @beaninfo
  835.      * description: If true, an entire row is selected for each selected cell.
  836.      */
  837.     public void setRowSelectionAllowed(boolean flag) {
  838.         clearSelection();
  839.         rowSelectionAllowed = flag;
  840.     }
  841.  
  842.     /**
  843.      * Returns true if rows can be selected.
  844.      *
  845.      * @return true if rows can be selected
  846.      * @see #setRowSelectionAllowed()
  847.      */
  848.     public boolean getRowSelectionAllowed() {
  849.         return rowSelectionAllowed;
  850.     }
  851.  
  852.     /**
  853.      * Sets whether the columns in this model can be selected.
  854.      *
  855.      * @see #getColumnSelectionAllowed()
  856.      * @beaninfo
  857.      * description: If true, an entire column is selected for each selected cell.
  858.      */
  859.     public void setColumnSelectionAllowed(boolean flag) {
  860.         clearSelection();
  861.         columnModel.setColumnSelectionAllowed(flag);
  862.     }
  863.  
  864.     /**
  865.      * Returns true if columns can be selected.
  866.      *
  867.      * @return true if columns can be selected.
  868.      * @see #setColumnSelectionAllowed
  869.      */
  870.     public boolean getColumnSelectionAllowed() {
  871.         return columnModel.getColumnSelectionAllowed();
  872.     }
  873.  
  874.     /**
  875.      * Sets whether this table allows both a column selection and a
  876.      * row selection to exist at the same time. When set, this results
  877.      * in a facility to select a rectangular region of cells in the display.
  878.      * This flag over-rides the row and column selection
  879.      * modes ensuring that cell selection is possible whenever this flag is set.
  880.  
  881.      * @see #getCellSelectionEnabled
  882.      * @beaninfo
  883.      * description: Select a rectangular region of cells rather than rows or columns.
  884.      */
  885.     public void setCellSelectionEnabled(boolean flag) {
  886.         clearSelection();
  887.         cellSelectionEnabled = flag;
  888.     }
  889.  
  890.     /**
  891.      * Returns true if simultaneous row and column selections are allowed
  892.      *
  893.      * @return true if simultaneous row and column selections are allowed
  894.      * @see #setCellSelectionEnabled
  895.      */
  896.     public boolean getCellSelectionEnabled() {
  897.         return cellSelectionEnabled;
  898.     }
  899.  
  900.     /**
  901.      *  If a column is selected, then this selects all columns.  Similarly,
  902.      *  if a row is selected, then, this selects all rows.  If both a column
  903.      *  and a row are selected at the time this method is invoked, then
  904.      *  all columns and rows are selected.
  905.      */
  906.     public void selectAll() {
  907.         if (getSelectedRowCount() > 0) {
  908.             // select all rows
  909.             int count = getRowCount();
  910.             if (count > 0)
  911.                 setRowSelectionInterval(0, count);
  912.         }
  913.  
  914.         if (getSelectedColumnCount() > 0) {
  915.             int count = getColumnCount();
  916.             if (count > 0)
  917.                 setColumnSelectionInterval(0, count);
  918.         }
  919.     }
  920.  
  921.     /**
  922.      * Deselects all selected columns and rows.  If empty selection is not
  923.      * allowed, then it leaves the first row selected.
  924.      */
  925.     public void clearSelection() {
  926.         columnModel.getSelectionModel().clearSelection();
  927.         selectionModel.clearSelection();
  928.     }
  929.  
  930.     /**
  931.      * Selects the rows from <i>index0</i> to <i>index1</i> inclusive.
  932.      *
  933.      * @param   index0 one end of the interval.
  934.      * @param   index1 other end of the interval
  935.      */
  936.     public void setRowSelectionInterval(int index0, int index1) {
  937.         selectionModel.setSelectionInterval(index0, index1);
  938.     }
  939.  
  940.     /**
  941.      * Selects the columns from <i>index0</i> to <i>index1</i> inclusive.
  942.      *
  943.      * @param   index0 one end of the interval.
  944.      * @param   index1 other end of the interval
  945.      */
  946.     public void setColumnSelectionInterval(int index0, int index1) {
  947.         columnModel.getSelectionModel().setSelectionInterval(index0, index1);
  948.     }
  949.  
  950.     /**
  951.      * Adds the rows from <i>index0</i> to <i>index0</i> inclusive to
  952.      * the current selection.
  953.      *
  954.      * @param   index0 one end of the interval.
  955.      * @param   index1 other end of the interval
  956.      */
  957.     public void addRowSelectionInterval(int index0, int index1) {
  958.         selectionModel.addSelectionInterval(index0, index1);
  959.     }
  960.  
  961.     /**
  962.      * Adds the columns from <i>index0</i> to <i>index0</i> inclusive to
  963.      * the current selection.
  964.      *
  965.      * @param   index0 one end of the interval.
  966.      * @param   index1 other end of the interval
  967.      */
  968.     public void addColumnSelectionInterval(int index0, int index1) {
  969.         columnModel.getSelectionModel().addSelectionInterval(index0, index1);
  970.     }
  971.  
  972.     /**
  973.      * Deselects the rows from <i>index0</i> to <i>index0</i> inclusive.
  974.      *
  975.      * @param   index0 one end of the interval.
  976.      * @param   index1 other end of the interval
  977.      */
  978.     public void removeRowSelectionInterval(int index0, int index1) {
  979.         selectionModel.removeSelectionInterval(index0, index1);
  980.     }
  981.  
  982.     /**
  983.      * Deselects the columns from <i>index0</i> to <i>index0</i> inclusive.
  984.      *
  985.      * @param   index0 one end of the interval.
  986.      * @param   index1 other end of the interval
  987.      */
  988.     public void removeColumnSelectionInterval(int index0, int index1) {
  989.         columnModel.getSelectionModel().removeSelectionInterval(index0, index1);
  990.     }
  991.  
  992.     /**
  993.      * Returns the index of the last row selected or added to the selection.
  994.      *
  995.      * @return the index of the last row selected or added to the selection,
  996.      *         (lead selection) or -1 if no row is selected.
  997.      * @see #getSelectedRows()
  998.      */
  999.     public int getSelectedRow() {
  1000.         if (selectionModel != null) {
  1001.             return selectionModel.getAnchorSelectionIndex();
  1002.         }
  1003.         return -1;
  1004.     }
  1005.  
  1006.     /**
  1007.      * Returns the index of the last column selected or added to the selection.
  1008.      *
  1009.      * @return the index of the last column selected or added to the selection,
  1010.      *         (lead selection) or -1 if no column is selected.
  1011.      * @see #getSelectedColumns()
  1012.      */
  1013.     public int getSelectedColumn() {
  1014.         return columnModel.getSelectionModel().getAnchorSelectionIndex();
  1015.     }
  1016.  
  1017.     /**
  1018.      * Returns the indices of all selected rows.
  1019.      *
  1020.      * @return an array of ints containing the indices of all selected rows,
  1021.      *         or an empty array if no row is selected.
  1022.      * @see #getSelectedRow()
  1023.      */
  1024.     public int[] getSelectedRows() {
  1025.         if (selectionModel != null) {
  1026.             int iMin = selectionModel.getMinSelectionIndex();
  1027.             int iMax = selectionModel.getMaxSelectionIndex();
  1028.  
  1029.             if ((iMin == -1) || (iMax == -1)) {
  1030.                 return new int[0];
  1031.             }
  1032.  
  1033.             int[] rvTmp = new int[1+ (iMax - iMin)];
  1034.             int n = 0;
  1035.             for(int i = iMin; i <= iMax; i++) {
  1036.                 if (selectionModel.isSelectedIndex(i)) {
  1037.                     rvTmp[n++] = i;
  1038.                 }
  1039.             }
  1040.             int[] rv = new int[n];
  1041.             System.arraycopy(rvTmp, 0, rv, 0, n);
  1042.             return rv;
  1043.         }
  1044.         return  new int[0];
  1045.     }
  1046.  
  1047.     /**
  1048.      * Returns the indices of all selected columns.
  1049.      *
  1050.      * @return an array of ints containing the indices of all selected columns,
  1051.      *         or an empty array if no column is selected.
  1052.      * @see #getSelectedColumn()
  1053.      */
  1054.     public int[] getSelectedColumns() {
  1055.         return columnModel.getSelectedColumns();
  1056.     }
  1057.  
  1058.     /**
  1059.      * Returns the number of selected rows.
  1060.      *
  1061.      * @return the number of selected rows, 0 if no columns are selected
  1062.      */
  1063.     public int getSelectedRowCount() {
  1064.         if (selectionModel != null) {
  1065.             int iMin = selectionModel.getMinSelectionIndex();
  1066.             int iMax = selectionModel.getMaxSelectionIndex();
  1067.             int count = 0;
  1068.  
  1069.             for(int i = iMin; i <= iMax; i++) {
  1070.                 if (selectionModel.isSelectedIndex(i)) {
  1071.                     count++;
  1072.                 }
  1073.             }
  1074.             return count;
  1075.         }
  1076.         return 0;
  1077.     }
  1078.  
  1079.     /**
  1080.      * Returns the number of selected columns.
  1081.      *
  1082.      * @return the number of selected columns, 0 if no columns are selected
  1083.      */
  1084.     public int getSelectedColumnCount() {
  1085.         return columnModel.getSelectedColumnCount();
  1086.     }
  1087.  
  1088.     /**
  1089.      * Returns true if the row at the specified index is selected
  1090.      *
  1091.      * @return true if the row at index <I>row</I> is selected, where 0 is the
  1092.      *              first row
  1093.      * @exception IllegalArgumentException      if <I>row</I> is not in the
  1094.      *                                          valid range
  1095.      */
  1096.     public boolean isRowSelected(int row) {
  1097.         if (selectionModel != null)
  1098.             return selectionModel.isSelectedIndex(row);
  1099.         return false;
  1100.     }
  1101.  
  1102.     /**
  1103.      * Returns true if the column at the specified index is selected
  1104.      *
  1105.      * @return true if the column at index <I>column</I> is selected, where
  1106.      *              0 is the first column
  1107.      * @exception IllegalArgumentException      if <I>column</I> is not in the
  1108.      *                                          valid range
  1109.      */
  1110.     public boolean isColumnSelected(int column) {
  1111.         return columnModel.getSelectionModel().isSelectedIndex(column);
  1112.     }
  1113.  
  1114.     /**
  1115.      * Returns true if the cell at the specified position is selected.
  1116.      *
  1117.      * @return true if the cell at index <I>(row, column)</I> is selected,
  1118.      *              where the first row and first column are at index 0
  1119.      * @exception IllegalArgumentException      if <I>row</I> or <I>column</I>
  1120.      *                                          are not in the valid range
  1121.      */
  1122.     public boolean isCellSelected(int row, int column) {
  1123.         if (cellSelectionEnabled)
  1124.             return isRowSelected(row) && isColumnSelected(column);
  1125.         else
  1126.             return (getRowSelectionAllowed() && isRowSelected(row)) ||
  1127.                    (getColumnSelectionAllowed() && isColumnSelected(column));
  1128.     }
  1129.  
  1130.     /**
  1131.      * Returns the foreground color for selected cells.
  1132.      *
  1133.      * @return the Color object for the foreground property
  1134.      * @see #setSelectionForeground
  1135.      * @see #setSelectionBackground
  1136.      */
  1137.     public Color getSelectionForeground() {
  1138.         return selectionForeground;
  1139.     }
  1140.  
  1141.     /**
  1142.      * Set the foreground color for selected cells.  Cell renderers
  1143.      * can use this color to render text and graphics for selected
  1144.      * cells.
  1145.      * <p>
  1146.      * The default value of this property is defined by the look
  1147.      * and feel implementation.
  1148.      * <p>
  1149.      * This is a JavaBeans bound property.
  1150.      *
  1151.      * @param selectionForeground  the Color to use in the foreground
  1152.      *                             for selected list items
  1153.      * @see #getSelectionForeground
  1154.      * @see #setSelectionBackground
  1155.      * @see #setForeground
  1156.      * @see #setBackground
  1157.      * @see #setFont
  1158.      * @beaninfo
  1159.      *       bound: true
  1160.      * description: A default foreground color for selected cells.
  1161.      */
  1162.     public void setSelectionForeground(Color selectionForeground) {
  1163.         Color oldValue = this.selectionForeground;
  1164.         this.selectionForeground = selectionForeground;
  1165.         firePropertyChange("selectionForeground", oldValue, selectionForeground);
  1166.     }
  1167.  
  1168.     /**
  1169.      * Returns the background color for selected cells.
  1170.      *
  1171.      * @return the Color used for the background of selected list items
  1172.      * @see #setSelectionBackground
  1173.      * @see #setSelectionForeground
  1174.      */
  1175.     public Color getSelectionBackground() {
  1176.         return selectionBackground;
  1177.     }
  1178.  
  1179.     /**
  1180.      * Set the background color for selected cells.  Cell renderers
  1181.      * can use this color to the fill selected cells.
  1182.      * <p>
  1183.      * The default value of this property is defined by the look
  1184.      * and feel implementation.
  1185.      * <p>
  1186.      * This is a JavaBeans bound property.
  1187.      *
  1188.      * @param selectionBackground  the Color to use for the background
  1189.      *                             of selected cells
  1190.      * @see #getSelectionBackground
  1191.      * @see #setSelectionForeground
  1192.      * @see #setForeground
  1193.      * @see #setBackground
  1194.      * @see #setFont
  1195.      * @beaninfo
  1196.      *       bound: true
  1197.      * description: A default background color for selected cells.
  1198.      */
  1199.     public void setSelectionBackground(Color selectionBackground) {
  1200.         Color oldValue = this.selectionBackground;
  1201.         this.selectionBackground = selectionBackground;
  1202.         firePropertyChange("selectionBackground", oldValue, selectionBackground);
  1203.     }
  1204.  
  1205.     /**
  1206.      * Returns the <B>TableColumn</B> object for the column in the table
  1207.      * whose identifier is equal to <I>identifier</I>, when compared using
  1208.      * <I>equals()</I>.
  1209.      *
  1210.      * @return  the TableColumn object with matching identifier
  1211.      * @exception IllegalArgumentException      if <I>identifier</I> is null or no TableColumn has this identifier
  1212.      *
  1213.      * @param   identifier                      the identifier object
  1214.      */
  1215.     public TableColumn getColumn(Object identifier) {
  1216.         TableColumnModel cm = getColumnModel();
  1217.         int columnIndex = cm.getColumnIndex(identifier);
  1218.         return cm.getColumn(columnIndex);
  1219.     }
  1220.  
  1221. //
  1222. // Informally implement the TableModel interface.
  1223. //
  1224.  
  1225.     /**
  1226.      * Return the index of the column in the model whose data is being displayed in
  1227.      * the column <I>viewColumnIndex</I> in the display. Returns <I>viewColumnIndex</I>
  1228.      * unchanged when <I>viewColumnIndex</I> is less than zero.
  1229.      *
  1230.      * @see #convertColumnIndexToView
  1231.      */
  1232.     public int convertColumnIndexToModel(int viewColumnIndex) {
  1233.         if (viewColumnIndex < 0) {
  1234.             return viewColumnIndex;
  1235.         }
  1236.         return getColumnModel().getColumn(viewColumnIndex).getModelIndex();
  1237.     }
  1238.  
  1239.     /**
  1240.      * Return the index of the column in the view which is displaying the
  1241.      * data from the column <I>modelColumnIndex</I> in the model. Returns
  1242.      * -1 if this column is not being displayed. Returns <I>modelColumnIndex</I>
  1243.      * unchanged when <I>modelColumnIndex</I> is less than zero.
  1244.      *
  1245.      * @see #convertColumnIndexToModel
  1246.      */
  1247.     public int convertColumnIndexToView(int modelColumnIndex) {
  1248.         if (modelColumnIndex < 0) {
  1249.             return modelColumnIndex;
  1250.         }
  1251.         TableColumnModel cm = getColumnModel();
  1252.         for (int column = 0; column < getColumnCount(); column++) {
  1253.             if (cm.getColumn(column).getModelIndex() == modelColumnIndex) {
  1254.                 return column;
  1255.             }
  1256.         }
  1257.         return -1;
  1258.     }
  1259.  
  1260.     /**
  1261.      * Returns the number of rows in the table.
  1262.      *
  1263.      * @see #getColumnCount()
  1264.      */
  1265.     public int getRowCount() {
  1266.         return getModel().getRowCount();
  1267.     }
  1268.  
  1269.     /**
  1270.      * Returns the number of columns in the column model, note this may
  1271.      * be different to the number of columns in the table model.
  1272.      *
  1273.      * @return  the number of columns in the table
  1274.      * @see #getRowCount()
  1275.      */
  1276.     public int getColumnCount() {
  1277.         return getColumnModel().getColumnCount();
  1278.     }
  1279.  
  1280.     /**
  1281.      * Returns the name of the column at the specified view position.
  1282.      *
  1283.      * @return the name of the column at position <I>column</I> in the view
  1284.      *         where the first column is column 0.
  1285.      */
  1286.     public String getColumnName(int column) {
  1287.         return getModel().getColumnName(convertColumnIndexToModel(column));
  1288.     }
  1289.  
  1290.     /**
  1291.      * Returns the type of the column at the specified view position.
  1292.      *
  1293.      * @return the type of the column at position <I>column</I> in the view
  1294.      *         where the first column is column 0.
  1295.      */
  1296.     public Class getColumnClass(int column) {
  1297.         return getModel().getColumnClass(convertColumnIndexToModel(column));
  1298.     }
  1299.  
  1300.     /**
  1301.      * Returns the cell value at <I>row</I> and <I>column</I>.
  1302.      * <p>
  1303.      * <b>NOTE</b>: The column is specified in the table view's display
  1304.      *              order, and not in the TableModel's column order.  This is
  1305.      *              an important distinction because as the user rearranges
  1306.      *              the columns in the table, what is at column 2 changes.
  1307.      *              Meanwhile the user's actions never affect the model's
  1308.      *              column ordering.
  1309.      *
  1310.      * @param   row             the row whose value is to be looked up
  1311.      * @param   column          the column whose value is to be looked up
  1312.      * @return  the Object at the specified cell
  1313.      */
  1314.     public Object getValueAt(int row, int column) {
  1315.         return getModel().getValueAt(row, convertColumnIndexToModel(column));
  1316.     }
  1317.  
  1318.     /**
  1319.      * Sets the value for the cell at <I>row</I> and <I>column</I>.
  1320.      * <I>aValue</I> is the new value.
  1321.      *
  1322.      * @param   aValue          the new value
  1323.      * @param   row             the row whose value is to be changed
  1324.      * @param   column          the column whose value is to be changed
  1325.      * @see #getValueAt()
  1326.      */
  1327.     public void setValueAt(Object aValue, int row, int column) {
  1328.         getModel().setValueAt(aValue, row, convertColumnIndexToModel(column));
  1329.     }
  1330.  
  1331.     /**
  1332.      * Returns true if the cell at <I>row</I> and <I>column</I>
  1333.      * is editable.  Otherwise, setValueAt() on the cell will not change
  1334.      * the value of that cell.
  1335.      *
  1336.      * @param   row      the row whose value is to be looked up
  1337.      * @param   column   the column whose value is to be looked up
  1338.      * @return  true if the cell is editable.
  1339.      * @see #setValueAt()
  1340.      */
  1341.     public boolean isCellEditable(int row, int column) {
  1342.         return getModel().isCellEditable(row, convertColumnIndexToModel(column));
  1343.     }
  1344. //
  1345. // Adding and removing columns in the view
  1346. //
  1347.  
  1348.     /**
  1349.      *  Appends <I>aColumn</I> to the end of the array of columns held by
  1350.      *  the JTable's column model.
  1351.      *  If the header value of <I>aColumn</I> is <I>null</I>,
  1352.      *  sets the header value of <I>aColumn</I> to the name
  1353.      *  returned by <code>getModel().getColumnName()</code>.
  1354.      *  <p>
  1355.      *  To add a column to the JTable to display the <I>modelColumn</I>'th column of
  1356.      *  data in the model, with a given <I>width</I>,
  1357.      *  <I>cellRenderer</I> and <I>cellEditor</I> you can use:
  1358.      *  <pre>
  1359.      *
  1360.      *      addColumn(new TableColumn(modelColumn, width, cellRenderer, cellEditor));
  1361.      *
  1362.      *  </pre>
  1363.      *  [All of the other constructors in the TableColumn can be used in place of
  1364.      *  this one.] The model column is stored inside the TableColumn and is used during
  1365.      *  rendering and editing to locate the appropriate data values in the
  1366.      *  model. The model column does not change when columns are reordered
  1367.      *  in the view.
  1368.      *
  1369.      *  @param  aColumn         The <B>TableColumn</B> to be added
  1370.      *  @see    #removeColumn
  1371.      */
  1372.     public void addColumn(TableColumn aColumn) {
  1373.         int modelColumn = aColumn.getModelIndex();
  1374.         String columnName = getModel().getColumnName(modelColumn);
  1375.         if (aColumn.getHeaderValue() == null) {
  1376.             aColumn.setHeaderValue(columnName);
  1377.         }
  1378.         getColumnModel().addColumn(aColumn);
  1379.     }
  1380.  
  1381.     /**
  1382.      *  Removes <I>aColumn</I> from the JTable's array of columns.
  1383.      *  Note: this method does not remove the column of data from the
  1384.      *  model it just removes the TableColumn that was displaying it.
  1385.      *
  1386.      *  @param  aColumn         The <B>TableColumn</B> to be removed
  1387.      *  @see    #addColumn
  1388.      */
  1389.     public void removeColumn(TableColumn aColumn) {
  1390.         getColumnModel().removeColumn(aColumn);
  1391.     }
  1392.  
  1393.     /**
  1394.      * Moves the column <I>column</I> to the position currently occupied by the
  1395.      * column <I>targetColumn</I>.  The old column at <I>targetColumn</I> is
  1396.      * shifted left or right to make room.
  1397.      *
  1398.      * @param   column                  the index of column to be moved
  1399.      * @param   targetColumn            the new index of the column
  1400.      */
  1401.     public void moveColumn(int column, int targetColumn) {
  1402.         getColumnModel().moveColumn(column, targetColumn);
  1403.     }
  1404.  
  1405. //
  1406. // Cover methods for various models and helper methods
  1407. //
  1408.  
  1409.     /**
  1410.      * Returns the index of the column that <I>point</I> lies in, or -1 if it
  1411.      * lies outside the receiver's bounds.
  1412.      *
  1413.      * @return  the index of the column that <I>point</I> lies in, or -1 if it
  1414.      *          lies outside the receiver's bounds
  1415.      * @see     #rowAtPoint
  1416.      */
  1417.     public int columnAtPoint(Point point) {
  1418.         return getColumnModel().getColumnIndexAtX(point.x);
  1419.     }
  1420.  
  1421.     /**
  1422.      * Returns the index of the row that <I>point</I> lies in, or -1 if is
  1423.      * not in the range [0, getRowCount()-1].
  1424.      *
  1425.      * @return  the index of the row that <I>point</I> lies in, or -1 if it
  1426.      *          is not in the range [0, getRowCount()-1]
  1427.      * @see     #columnAtPoint()
  1428.      */
  1429.     public int rowAtPoint(Point point) {
  1430.         int y = point.y;
  1431.  
  1432.  //       if (y < 0 || y >= getBounds().height) {
  1433.  //           return -1;
  1434.  //       }
  1435.  
  1436.         int rowHeight = getRowHeight();
  1437.         int rowSpacing = getIntercellSpacing().height;
  1438.         int totalRowHeight = rowHeight + rowSpacing;
  1439.         int result = y/totalRowHeight;
  1440.         if (result < 0) {
  1441.             return -1;
  1442.         }
  1443.         else if (result >= getRowCount()) {
  1444.             return -1;
  1445.         }
  1446.         else {
  1447.             return result;
  1448.         }
  1449.     }
  1450.  
  1451.     /**
  1452.      * Returns a rectangle locating the cell that lies at the intersection of
  1453.      * <I>row</I> and <I>column</I>.   If <I>includeSpacing</I> is true then
  1454.      * the value returned includes the intercellSpacing margin.  If it is false,
  1455.      * then the returned rect is inset by half of intercellSpacing.
  1456.      * (This is the true frame of the cell)
  1457.      *
  1458.      * @param   row                             the row to compute
  1459.      * @param   column                          the column to compute
  1460.      * @param   includeSpacing                  if true, the rect returned will
  1461.      *                                          include the correct
  1462.      *                                          intercellSpacing
  1463.      * @return  the rectangle containing the cell at index
  1464.      *          <I>row</I>,<I>column</I>
  1465.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1466.      *                                          are not in the valid range.
  1467.      */
  1468.     public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
  1469.         int index = 0;
  1470.         Rectangle cellFrame;
  1471.         int columnMargin = getColumnModel().getColumnMargin();
  1472.         Enumeration enumeration = getColumnModel().getColumns();
  1473.         TableColumn aColumn;
  1474.  
  1475.         cellFrame = new Rectangle();
  1476.         cellFrame.height = getRowHeight() + rowMargin;
  1477.         cellFrame.y = row * cellFrame.height;
  1478.  
  1479.         while (enumeration.hasMoreElements()) {
  1480.             aColumn = (TableColumn)enumeration.nextElement();
  1481.             cellFrame.width = aColumn.getWidth() + columnMargin;
  1482.  
  1483.             if (index == column)
  1484.                 break;
  1485.  
  1486.             cellFrame.x += cellFrame.width;
  1487.             index++;
  1488.         }
  1489.  
  1490.         if (!includeSpacing) {
  1491.             Dimension spacing = getIntercellSpacing();
  1492.             // This is not the same as grow(), it rounds differently.
  1493.             cellFrame.setBounds(cellFrame.x +      spacing.width/2,
  1494.                                 cellFrame.y +      spacing.height/2,
  1495.                                 cellFrame.width -  spacing.width,
  1496.                                 cellFrame.height - spacing.height);
  1497.         }
  1498.         return cellFrame;
  1499.     }
  1500.  
  1501.     /**
  1502.      * This method will resize one or more columns of the table
  1503.      * so that the sum width of all columns will equal to the
  1504.      * width of the table.  If <I>lastColumnOnly</I> is true, then
  1505.      * it will try to resize the last column only to make it fit,
  1506.      * but if it runs into either the minimum size limit of the column
  1507.      * or maximum size limit, then it will change the next to last column also,
  1508.      * etc.  If <I>lastColumnOnly</I> is false, then it will spread the
  1509.      * size delta proportionately to all the columns, while respecting
  1510.      * each column's max and min size limits.  Also, notifications of each
  1511.      * column width change will be sent out as they are resized.  <p>
  1512.      *
  1513.      * Note: It is possible that even after this method is called,
  1514.      *   the total width of the columns is still not be equal to the width
  1515.      *   of the table.  eg. A table with a single column, the column has a
  1516.      *   minimum width of 20, and the tableView has a width of 10.  And there
  1517.      *   is nothing I can do about that.
  1518.      *
  1519.      * @param lastColumnOnly    Try to change the last column only if true
  1520.      * @see TableColumn#setWidth()
  1521.      */
  1522.     public void sizeColumnsToFit(boolean lastColumnOnly) {
  1523.         int intercellWidth = getColumnModel().getColumnMargin();
  1524.         int frameWidth = getWidth();
  1525.         int totalColumnWidth = 0;
  1526.         TableColumn aColumn;
  1527.         int index = 0;
  1528.         int[] columnWidths = new int[this.getColumnCount()];
  1529.         int[] columnMaxWidths = new int[this.getColumnCount()];
  1530.         int[] columnMinWidths = new int[this.getColumnCount()];
  1531.         int maxColumnDelta;
  1532.  
  1533.         // Fetch all the column width related info and put them in my int arrays
  1534.         Enumeration enumeration = getColumnModel().getColumns();
  1535.         while (enumeration.hasMoreElements()) {
  1536.             aColumn = (TableColumn)enumeration.nextElement();
  1537.             columnWidths[index] = aColumn.getWidth();
  1538.             columnMaxWidths[index] = aColumn.getMaxWidth();
  1539.             columnMinWidths[index] = aColumn.getMinWidth();
  1540.             totalColumnWidth += aColumn.getWidth() + intercellWidth;
  1541.             index++;
  1542.         }
  1543.  
  1544.         // What's the amount of space we must grow or shrink by
  1545.         int delta = frameWidth - totalColumnWidth;
  1546.  
  1547.         if ((-1 <= delta) && (delta <= 1))
  1548.             return;                     // Too small to worry about
  1549.  
  1550.         // Ok, we can now adjust the values in my columnWidths[] array to reflect
  1551.         // the new desired width.
  1552.         if (lastColumnOnly) {
  1553.             // The basic idea if lastColumnOnly is true is we start with
  1554.             // the last column adjust the width up or down.  If we hit
  1555.             // a max or min limit than we take the reminder and apply that
  1556.             // to the next to last column.  Repeat as needed.
  1557.             for (index = this.getColumnCount() - 1; index >= 0; index--) {
  1558.                 if (delta > 0) {
  1559.                     // We are growing the column
  1560.                     maxColumnDelta = columnMaxWidths[index] - columnWidths[index];
  1561.                 }
  1562.                 else {
  1563.                     // Shrinking.  Note the maxColumnDelta is going to be negative.
  1564.                     maxColumnDelta = columnMinWidths[index] - columnWidths[index];
  1565.                 }
  1566.  
  1567.                 if (Math.abs(maxColumnDelta) >= Math.abs(delta)) {
  1568.                     columnWidths[index] += delta;
  1569.                     break;
  1570.                 }
  1571.                 else {
  1572.                     columnWidths[index] += maxColumnDelta;
  1573.                     delta -= maxColumnDelta;
  1574.                 }
  1575.             }
  1576.         }
  1577.         else {
  1578.             // We have to spread the delta across all the columns.  To do this
  1579.             // simply and safely, we calculate a percentage value for each
  1580.             // iteration across all the columns.
  1581.  
  1582.             float[] percentShare = new float[this.getColumnCount()];
  1583.             boolean stillHaveRoom = true;
  1584.  
  1585.             // Lets compute the percentShare of the delta that each column
  1586.             // should take up, before we change any columns.
  1587.             // Note: the sum of all the percentages in the array should be 100
  1588.             for (index = 0; index < this.getColumnCount(); index++) {
  1589.                 percentShare[index] = ((float)(columnWidths[index]+intercellWidth) /
  1590.                                        ((float)totalColumnWidth));
  1591.             }
  1592.  
  1593.  
  1594.             // Now we will iterate 1 or more times to distribute the delta,
  1595.             // stopping when delta reaches zero. Unless none of the columns
  1596.             // can change any more because they have all hit their bound limits.
  1597.             // In which case, we also stop.
  1598.             while ((delta != 0) && stillHaveRoom) {
  1599.                 int deltaRemainder = delta;
  1600.                 stillHaveRoom = false;
  1601.  
  1602.                 for (index = 0; index < this.getColumnCount(); index++) {
  1603.                     int shareDelta = (int)Math.ceil((float)delta * percentShare[index]);
  1604.  
  1605.                     // Have to check if deltaRemainder is zero here, if it
  1606.                     // is then we break.  This is needed because we are
  1607.                     // computing the shareDelta using ints which can lead
  1608.                     // to some funny cases with small deltas. eg. a table
  1609.                     // with 6 equal sized columns, and the delta is 2.
  1610.                     // Leading to each column's share being 0.33.  If I round
  1611.                     // down then every column's shareDelta is 0, and the
  1612.                     // loop will never end.  So what I have choose to do
  1613.                     // is take the ceiling.  In the example above, then
  1614.                     // the first column gets 1, and the second also gets
  1615.                     // 1, bring the deltaRemainder to 0, and we should
  1616.                     // stop.
  1617.                     if (deltaRemainder == 0) {
  1618.                         break;
  1619.                     }
  1620.                     else if (Math.abs(deltaRemainder) < Math.abs(shareDelta)) {
  1621.                         // Here we are making sure we don't go over our
  1622.                         // delta because of the ceiling. eg. we have a delta
  1623.                         // of 27.  The 3 column's share computes to 10.2, 10.2,
  1624.                         // and 6.6.  When rounded up becomes 11, 11, 7, which
  1625.                         // adds up to 29.  This check will make the last column's
  1626.                         // share equal to 5.
  1627.                         shareDelta = deltaRemainder;
  1628.                     }
  1629.  
  1630.                     if (shareDelta > 0) {
  1631.                         // We are growing the column
  1632.                         maxColumnDelta = columnMaxWidths[index] - columnWidths[index];
  1633.                     }
  1634.                     else if (shareDelta < 0) {
  1635.                         // Shrinking.  Note the maxColumnDelta is going to be negative.
  1636.                         maxColumnDelta = columnMinWidths[index] - columnWidths[index];
  1637.                     }
  1638.                     else {
  1639.                         // My share is zero, so do nothing.
  1640.                         continue;
  1641.                     }
  1642.  
  1643.                     if (Math.abs(maxColumnDelta) >= Math.abs(shareDelta)) {
  1644.                         stillHaveRoom = true;
  1645.                         columnWidths[index] += shareDelta;
  1646.                         deltaRemainder -= shareDelta;
  1647.                     }
  1648.                     else if (maxColumnDelta != 0) {
  1649.                         columnWidths[index] += maxColumnDelta;
  1650.                         deltaRemainder -= maxColumnDelta;
  1651.  
  1652.                         // I've hit my limits, so I'm going to mark this
  1653.                         // by changing my percentShare to zero
  1654.                         percentShare[index] = 0;
  1655.                     }
  1656.                 }
  1657.  
  1658.                 // Update local vars for next loop iteration
  1659.                 delta = deltaRemainder;         // It is important that delta not
  1660.                                                 // change in the for loop above
  1661.  
  1662.                 if (delta != 0) {
  1663.                     // We have to loop again because one or more columns
  1664.                     // couldn't take their full share of the delta.  And because
  1665.                     // those columns can't take any more in the next iteration,
  1666.                     // their percentShare number has been set to zero.  Now the
  1667.                     // sum total of all the percentShares is less than 100%.
  1668.                     // So we are going to adjust the percent shares so their sum
  1669.                     // total is once again 100%.  Otherwise, the loop will take
  1670.                     // a long time to end, and we'll just get closer and closer
  1671.                     // in many iterations before reaching some where near zero.
  1672.  
  1673.                     float adjustment, percentLeft = 0;
  1674.                     for (index = 0; index < this.getColumnCount(); index++) {
  1675.                         percentLeft += percentShare[index];
  1676.                     }
  1677.                     adjustment = 100 / percentLeft;
  1678.                     for (index = 0; index < this.getColumnCount(); index++) {
  1679.                         percentShare[index] *= adjustment;
  1680.                     }
  1681.                 }
  1682.             }
  1683.         }
  1684.  
  1685.         // Now we really set the widths based on the final value of the array
  1686.         index = 0;
  1687.         enumeration = getColumnModel().getColumns();
  1688.         while (enumeration.hasMoreElements()) {
  1689.             aColumn = (TableColumn)enumeration.nextElement();
  1690.             aColumn.setWidth(columnWidths[index]);
  1691.             index++;
  1692.         }
  1693.     }
  1694.  
  1695.     /**
  1696.      * Overrides JComponent's setToolTipText method to allow use of the
  1697.      * renderer's tips (if the renderer has text set).
  1698.      * <p>
  1699.      * NOTE: For JTable to properly display tooltips of its renderers
  1700.      *       JTable must be a registered component with the ToolTipManager.
  1701.      *       This is done automatically in initializeLocalVars(), but
  1702.      *       if at a later point JTable is told setToolTipText(null)
  1703.      *       it will unregister the table component, and no tips from
  1704.      *       renderers will display anymore.
  1705.      *
  1706.      * @see JComponent#getToolTipText
  1707.      */
  1708.     public String getToolTipText(MouseEvent event) {
  1709.         String tip = null;
  1710.         Point p = event.getPoint();
  1711.  
  1712.         // Locate the renderer under the event location
  1713.         int hitColumnIndex = columnAtPoint(p);
  1714.         int hitRowIndex = rowAtPoint(p);
  1715.  
  1716.         if ((hitColumnIndex != -1) && (hitRowIndex != -1)) {
  1717.             TableColumn aColumn = getColumnModel().getColumn(hitColumnIndex);
  1718.             TableCellRenderer renderer = aColumn.getCellRenderer();
  1719.             if (renderer == null) {
  1720.                 Class columnClass = getColumnClass(hitColumnIndex);
  1721.                 renderer = getDefaultRenderer(columnClass);
  1722.             }
  1723.             Component component = renderer.getTableCellRendererComponent(
  1724.                               this, null, false, false,
  1725.                               hitRowIndex, hitColumnIndex);
  1726.  
  1727.             // Now have to see if the component is a JComponent before
  1728.             // getting the tip
  1729.             if (component instanceof JComponent) {
  1730.                 // Convert the event to the renderer's coordinate system
  1731.                 MouseEvent newEvent;
  1732.                 Rectangle cellRect = getCellRect(hitRowIndex, hitColumnIndex, false);
  1733.  
  1734.                 p.translate(-cellRect.x, -cellRect.y);
  1735.                 newEvent = new MouseEvent(component, event.getID(),
  1736.                                           event.getWhen(), event.getModifiers(),
  1737.                                           p.x, p.y, event.getClickCount(),
  1738.                                           event.isPopupTrigger());
  1739.  
  1740.                 tip = ((JComponent)component).getToolTipText(newEvent);
  1741.             }
  1742.         }
  1743.  
  1744.         // No tip from the renderer get our own tip
  1745.         if (tip == null)
  1746.             tip = getToolTipText();
  1747.  
  1748.         return tip;
  1749.     }
  1750.  
  1751. //
  1752. // Editing Support
  1753. //
  1754.  
  1755.     /**
  1756.      * Programmatically starts editing the cell at <I>row</I> and
  1757.      * <I>column</I>, if the cell is editable.
  1758.      *
  1759.      * @param   row                             the row to be edited
  1760.      * @param   column                          the column to be edited
  1761.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1762.      *                                          are not in the valid range
  1763.      * @return  false if for any reason the cell cannot be edited.
  1764.      */
  1765.     public boolean editCellAt(int row, int column) {
  1766.         return editCellAt(row, column, null);
  1767.     }
  1768.  
  1769.     /**
  1770.      * Programmatically starts editing the cell at <I>row</I> and
  1771.      * <I>column</I>, if the cell is editable.
  1772.      * To prevent the JTable from editing a particular table, column or
  1773.      * cell value, return false from the isCellEditable() method in the
  1774.      * TableModel interface.
  1775.      *
  1776.      * @param   row                             the row to be edited
  1777.      * @param   column                          the column to be edited
  1778.      * @param   e                               event to pass into
  1779.      *                                          shouldSelectCell
  1780.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1781.      *                                          are not in the valid range
  1782.      * @return  false if for any reason the cell cannot be edited.
  1783.      */
  1784.     public boolean editCellAt(int row, int column, EventObject e){
  1785.         if (!isCellEditable(row, column))
  1786.             return false;
  1787.  
  1788.         if (isEditing()) {
  1789.             // Try to stop the current editor
  1790.             if (cellEditor != null) {
  1791.                 boolean stopped = cellEditor.stopCellEditing();
  1792.                 if (!stopped)
  1793.                     return false;       // The current editor not resigning
  1794.             }
  1795.         }
  1796.  
  1797.         TableColumn tableColumn = getColumnModel().getColumn(column);
  1798.         TableCellEditor editor = tableColumn.getCellEditor();
  1799.         if (editor == null) {
  1800.             editor = getDefaultEditor(getColumnClass(column));
  1801.         }
  1802.  
  1803.         if (editor != null) {
  1804.             // prepare editor - size it then added it to the table
  1805.             editorComp = prepareEditor(editor, row, column);
  1806.  
  1807.             if (editor.isCellEditable(e)) {
  1808.                 editorComp.setBounds(getCellRect(row, column, false));// PENDING(philip)
  1809.                 this.add(editorComp);
  1810.                 editorComp.validate();
  1811.  
  1812.                 // PENDING: this could convert event at this point!
  1813.                 boolean shouldSelect = editor.shouldSelectCell(e);
  1814.  
  1815.                 setCellEditor(editor);
  1816.                 setEditingRow(row);
  1817.                 setEditingColumn(column);
  1818.                 editor.addCellEditorListener(this);
  1819.  
  1820.                 repaint();
  1821.                 return true;
  1822.             }
  1823.         }
  1824.         return false;
  1825.     }
  1826.  
  1827.     /**
  1828.      * Returns  true is the table is editing a cell.
  1829.      *
  1830.      * @return  true is the table is editing a cell
  1831.      * @see     #editingColumn()
  1832.      * @see     #editingRow()
  1833.      */
  1834.     public boolean isEditing() {
  1835.         return (cellEditor == null)? false : true;
  1836.     }
  1837.  
  1838.     /**
  1839.      * If the receiver is currently editing this will return the Component
  1840.      * that was returned from the CellEditor.
  1841.      *
  1842.      * @return  Component handling editing session
  1843.      */
  1844.     public Component getEditorComponent() {
  1845.         return editorComp;
  1846.     }
  1847.  
  1848.     /**
  1849.      * This returns the index of the editing column.
  1850.      *
  1851.      * @return  the index of the column being edited
  1852.      * @see #editingRow()
  1853.      */
  1854.     public int getEditingColumn() {
  1855.         return editingColumn;
  1856.     }
  1857.  
  1858.     /**
  1859.      * Returns the index of the editing row.
  1860.      *
  1861.      * @return  the index of the row being edited
  1862.      * @see #editingColumn()
  1863.      */
  1864.     public int getEditingRow() {
  1865.         return editingRow;
  1866.     }
  1867.  
  1868. //
  1869. // Managing TableUI
  1870. //
  1871.  
  1872.     /**
  1873.      * Returns the L&F object that renders this component.
  1874.      *
  1875.      * @return the TableUI object that renders this component
  1876.      */
  1877.     public TableUI getUI() {
  1878.         return (TableUI)ui;
  1879.     }
  1880.  
  1881.     /**
  1882.      * Sets the L&F object that renders this component.
  1883.      *
  1884.      * @param ui  the TableUI L&F object
  1885.      * @see UIDefaults#getUI
  1886.      */
  1887.     public void setUI(TableUI ui) {
  1888.         if (this.ui != ui) {
  1889.             super.setUI(ui);
  1890.             repaint();
  1891.         }
  1892.     }
  1893.  
  1894.     private void updateSubComponentUI(Object componentShell) {
  1895.         if (componentShell == null) {
  1896.             return;
  1897.         }
  1898.         Component component = null;
  1899.         if (componentShell instanceof Component) {
  1900.             component = (Component)componentShell;
  1901.         }
  1902.         if (componentShell instanceof DefaultCellEditor) {
  1903.             component = ((DefaultCellEditor)componentShell).getComponent();
  1904.         }
  1905.  
  1906.         if (component != null && component instanceof JComponent) {
  1907.             ((JComponent)component).updateUI();
  1908.         }
  1909.     }
  1910.  
  1911.     /**
  1912.      * Notification from the UIManager that the L&F has changed.
  1913.      * Replaces the current UI object with the latest version from the
  1914.      * UIManager.
  1915.      *
  1916.      * @see JComponent#updateUI
  1917.      */
  1918.     public void updateUI() {
  1919.         // Update the UIs of the cell renderers, cell editors and header renderers.
  1920.         TableColumnModel cm = getColumnModel();
  1921.         for(int column = 0; column < cm.getColumnCount(); column++) {
  1922.             TableColumn aColumn = cm.getColumn(column);
  1923.            // updateSubComponentUI(aColumn.getCellRenderer());
  1924.             updateSubComponentUI(aColumn.getCellEditor());
  1925.            // updateSubComponentUI(aColumn.getHeaderRenderer());
  1926.         }
  1927.  
  1928.         // Update the UIs of all the default renderers.
  1929.         /*
  1930.         Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
  1931.         while (defaultRenderers.hasMoreElements()) {
  1932.             updateSubComponentUI(defaultRenderers.nextElement());
  1933.         }
  1934.         */
  1935.  
  1936.         // Update the UIs of all the default editors.
  1937.         Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
  1938.         while (defaultEditors.hasMoreElements()) {
  1939.             updateSubComponentUI(defaultEditors.nextElement());
  1940.         }
  1941.  
  1942.         setUI((TableUI)UIManager.getUI(this));
  1943.         resizeAndRepaint();
  1944.         invalidate();//PENDING
  1945.     }
  1946.  
  1947.     /**
  1948.      * Returns the name of the L&F class that renders this component.
  1949.      *
  1950.      * @return "TableUI"
  1951.      * @see JComponent#getUIClassID
  1952.      * @see UIDefaults#getUI
  1953.      */
  1954.     public String getUIClassID() {
  1955.         return "TableUI";
  1956.     }
  1957.  
  1958.  
  1959. //
  1960. // Managing models
  1961. //
  1962.  
  1963.     /**
  1964.      * Sets the data model for this table to <I>newModel</I> and registers
  1965.      * with for listner notifications from the new data model.
  1966.      *
  1967.      * @param   newModel        the new data source for this table
  1968.      * @exception IllegalArgumentException      if <I>newModel</I> is null
  1969.      * @see     #getModel()
  1970.      * @beaninfo
  1971.      * description: The model that is the source of the data for this view.
  1972.      */
  1973.     public void setModel(TableModel newModel) {
  1974.         TableModel oldModel = dataModel;
  1975.  
  1976.         if (newModel == null)
  1977.             throw new IllegalArgumentException("Cannot set a null TableModel");
  1978.  
  1979.         if (newModel != oldModel) {
  1980.             if (oldModel != null)
  1981.                 oldModel.removeTableModelListener(this);
  1982.             dataModel = newModel;
  1983.             newModel.addTableModelListener(this);
  1984.             // If this method is called from the JTable constructor,
  1985.             // the column model will be null. In this case we can't use
  1986.             // the usual methods to update the internal state. In all other
  1987.             // cases, use the usual tableChanged() method to reconfigure
  1988.             // the JTable for the new model.
  1989.             if (getColumnModel() != null) {
  1990.                 tableChanged(new TableModelEvent(dataModel, TableModelEvent.HEADER_ROW));
  1991.             }
  1992.         }
  1993.     }
  1994.  
  1995.     /**
  1996.      * Returns the <B>TableModel</B> that provides the data displayed by
  1997.      * the receiver.
  1998.      *
  1999.      * @return  the object that provides the data displayed by the receiver
  2000.      * @see     #setModel()
  2001.      */
  2002.     public TableModel getModel() {
  2003.         return dataModel;
  2004.     }
  2005.  
  2006.     /**
  2007.      * Sets the column model for this table to <I>newModel</I> and registers
  2008.      * with for listner notifications from the new column model. Also sets
  2009.      * the column model of the JTableHeader to <I>newModel</I>.
  2010.      *
  2011.      * @param   newModel        the new data source for this table
  2012.      * @exception IllegalArgumentException      if <I>newModel</I> is null
  2013.      * @see     #getColumnModel()
  2014.      * @beaninfo
  2015.      * description: The object governing the way columns appear in the view.
  2016.      */
  2017.     public void setColumnModel(TableColumnModel newModel) {
  2018.         if (newModel == null) {
  2019.             throw new IllegalArgumentException("Cannot set a null ColumnModel");
  2020.         }
  2021.  
  2022.         TableColumnModel oldModel = columnModel;
  2023.         if (newModel != oldModel) {
  2024.             if (oldModel != null)
  2025.                 oldModel.removeColumnModelListener(this);
  2026.  
  2027.             columnModel = newModel;
  2028.             newModel.addColumnModelListener(this);
  2029.  
  2030.  
  2031.             // Set the column model of the header as well.
  2032.             if (tableHeader != null) {
  2033.                 tableHeader.setColumnModel(newModel);
  2034.             }
  2035.  
  2036.             resizeAndRepaint();
  2037.         }
  2038.     }
  2039.  
  2040.     /**
  2041.      * Returns the <B>TableColumnModel</B> that contains all column inforamtion
  2042.      * of this table.
  2043.      *
  2044.      * @return  the object that provides the column state of the table
  2045.      * @see     #setColumnModel()
  2046.      */
  2047.     public TableColumnModel getColumnModel() {
  2048.         return columnModel;
  2049.     }
  2050.  
  2051.     /**
  2052.      * Sets the row selection model for this table to <I>newModel</I>
  2053.      * and registers with for listner notifications from the new selection model.
  2054.      * If <I>newModel</I> is null, it means the rows in this table are not
  2055.      * selectable.
  2056.      *
  2057.      * @param   newModel        the new selection model
  2058.      * @see     #getSelectionModel()
  2059.      * @beaninfo
  2060.      * description: The selection model for rows.
  2061.      */
  2062.     public void setSelectionModel(ListSelectionModel newModel) {
  2063.         ListSelectionModel oldModel = selectionModel;
  2064.  
  2065.         if (newModel != oldModel) {
  2066.             if (oldModel != null) {
  2067.                 oldModel.removeListSelectionListener(this);
  2068.             }
  2069.  
  2070.             selectionModel = newModel;
  2071.  
  2072.             if (newModel != null) {
  2073.                 newModel.addListSelectionListener(this);
  2074.             }
  2075.             repaint();
  2076.         }
  2077.     }
  2078.  
  2079.     /**
  2080.      * Returns the <B>ListSelectionModel</B> that is used to maintain row
  2081.      * selection state.
  2082.      *
  2083.      * @return  the object that provides row selection state.  Or <B>null</B>
  2084.      *          if row selection is not allowed.
  2085.      * @see     #setSelectionModel()
  2086.      */
  2087.     public ListSelectionModel getSelectionModel() {
  2088.         return selectionModel;
  2089.     }
  2090.  
  2091. //
  2092. // Implementing TableModelListener interface
  2093. //
  2094.  
  2095.     /**
  2096.      * The TableModelEvent should be constructed in the co-ordinate system
  2097.      * of the model, the appropriate mapping to the view co-ordinate system
  2098.      * is performed by the JTable when it recieves the event.
  2099.      */
  2100.     public void tableChanged(TableModelEvent e) {
  2101.         if (e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW) {
  2102.             // The whole thing changed
  2103.             clearSelection();
  2104.  
  2105.             if (getAutoCreateColumnsFromModel())
  2106.                 createDefaultColumnsFromModel();
  2107.  
  2108.             resizeAndRepaint();
  2109.             if (tableHeader != null) {
  2110.                 tableHeader.resizeAndRepaint();
  2111.             }
  2112.             return;
  2113.         }
  2114.  
  2115.         if (e.getType() == TableModelEvent.INSERT) {
  2116.             tableRowsInserted(e);
  2117.             return;
  2118.         }
  2119.  
  2120.         if (e.getType() == TableModelEvent.DELETE) {
  2121.             tableRowsDeleted(e);
  2122.             return;
  2123.         }
  2124.  
  2125.         int modelColumn = e.getColumn();
  2126.         int start = e.getFirstRow();
  2127.         int end = e.getLastRow();
  2128.  
  2129.         if (start == TableModelEvent.HEADER_ROW) {
  2130.             start = 0;
  2131.             end = Integer.MAX_VALUE;
  2132.         }
  2133.  
  2134.         int rowHeight = getRowHeight() + rowMargin;
  2135.         Rectangle dirtyRegion;
  2136.         if (modelColumn == TableModelEvent.ALL_COLUMNS) {
  2137.             // 1 or more rows changed
  2138.             dirtyRegion = new Rectangle(0, start * rowHeight,
  2139.                                         getColumnModel().getTotalColumnWidth(), 0);
  2140.         }
  2141.         else {
  2142.             // A cell or column of cells has changed.
  2143.             // Unlike the rest of the methods in the JTable, the TableModelEvent
  2144.             // uses the co-ordinate system of the model instead of the view.
  2145.             // This is the only place in the JTable where this "reverse mapping"
  2146.             // is used.
  2147.             int column = convertColumnIndexToView(modelColumn);
  2148.             dirtyRegion = getCellRect(start, column, false);
  2149.         }
  2150.  
  2151.         // Now adjust the height of the dirty region according to the value of "end".
  2152.         // Check for Integer.MAX_VALUE as this will cause an overflow.
  2153.         if (end != Integer.MAX_VALUE) {
  2154.             dirtyRegion.height = (end-start+1)*rowHeight;
  2155.             repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2156.         }
  2157.         // In fact, if the end is Integer.MAX_VALUE we need to revalidate anyway
  2158.         // because the scrollbar may need repainting.
  2159.         else {
  2160.             resizeAndRepaint();
  2161.         }
  2162.     }
  2163.  
  2164.     /*
  2165.      * Invoked when rows have been inserted into the table.
  2166.      *
  2167.      * @param e the TableModelEvent encapsulating the insertion
  2168.      */
  2169.     private void tableRowsInserted(TableModelEvent e) {
  2170.         int start = e.getFirstRow();
  2171.         if (start < 0)
  2172.             start = 0;
  2173.  
  2174.         // 1 or more rows added, so I have to repaint from the first
  2175.         // new row to the end of the table.  (Everything shifts down)
  2176.         int rowHeight = getRowHeight() + rowMargin;
  2177.         Rectangle drawRect = new Rectangle(0, start * rowHeight,
  2178.                                         getColumnModel().getTotalColumnWidth(),
  2179.                                            (getRowCount()-start) * rowHeight);
  2180.  
  2181.         // Adjust the selection to account for the new rows
  2182.         if (selectionModel != null) {
  2183.             int end = e.getLastRow();
  2184.             if (end < 0)
  2185.                 end = getRowCount()-1;
  2186.             int length = end - start + 1;
  2187.  
  2188.             selectionModel.insertIndexInterval(start, length, true);
  2189.         }
  2190.         revalidate();
  2191.         repaint(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
  2192.     }
  2193.  
  2194.     /*
  2195.      * Invoked when rows have been removed from the table.
  2196.      *
  2197.      * @param e the TableModelEvent encapsulating the deletion
  2198.      */
  2199.     private void tableRowsDeleted(TableModelEvent e) {
  2200.         int start = e.getFirstRow();
  2201.         if (start < 0)
  2202.             start = 0;
  2203.  
  2204.         // 1 or more rows added, so I have to repaint from the first
  2205.         // new row to the end of the table.  (Everything shifts down)
  2206.         int rowHeight = getRowHeight() + rowMargin;
  2207.         Rectangle drawRect = new Rectangle(0, start * rowHeight,
  2208.                                         getColumnModel().getTotalColumnWidth(),
  2209.                                            (getRowCount()-start) * rowHeight);
  2210.  
  2211.         // Adjust the selection to account for the new rows
  2212.         if (selectionModel != null) {
  2213.             int end = e.getLastRow();
  2214.             if (end < 0)
  2215.                 end = getRowCount()-1;
  2216.  
  2217.             selectionModel.removeIndexInterval(start, end);
  2218.         }
  2219.         revalidate();
  2220.         repaint(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
  2221.     }
  2222.  
  2223. //
  2224. // Implementing TableColumnModelListener interface
  2225. //
  2226.  
  2227.     /**
  2228.      * Tells listeners that a column was added to the model.
  2229.      *
  2230.      * @see TableColumnModelListener
  2231.      */
  2232.     public void columnAdded(TableColumnModelEvent e) {
  2233.         // If I'm currently editing, then I should stop editing
  2234.         if (isEditing()) {
  2235.             removeEditor();
  2236.         }
  2237.         resizeAndRepaint();
  2238.     }
  2239.  
  2240.     /**
  2241.      * Tells listeners that a column was removed from the model.
  2242.      *
  2243.      * @see TableColumnModelListener
  2244.      */
  2245.     public void columnRemoved(TableColumnModelEvent e) {
  2246.         // If I'm currently editing, then I should stop editing
  2247.         if (isEditing()) {
  2248.             removeEditor();
  2249.         }
  2250.         resizeAndRepaint();
  2251.     }
  2252.  
  2253.     /**
  2254.      * Tells listeners that a column was repositioned.
  2255.      *
  2256.      * @see TableColumnModelListener
  2257.      */
  2258.     public void columnMoved(TableColumnModelEvent e) {
  2259.         // If I'm currently editing, then I should stop editing
  2260.         if (isEditing()) {
  2261.             removeEditor();
  2262.         }
  2263.         repaint();
  2264.     }
  2265.  
  2266.     /**
  2267.      * Tells listeners that a column was moved due to a margin change.
  2268.      *
  2269.      * @see TableColumnModelListener
  2270.      */
  2271.     public void columnMarginChanged(ChangeEvent e) {
  2272.         // If I'm currently editing, then I should stop editing
  2273.         if (isEditing()) {
  2274.             removeEditor();
  2275.         }
  2276.         resizeAndRepaint();
  2277.     }
  2278.  
  2279.     /**
  2280.      * Tells listeners that the selection model of the
  2281.      * TableColumnModel changed.
  2282.      *
  2283.      * @see TableColumnModelListener
  2284.      */
  2285.     public void columnSelectionChanged(ListSelectionEvent e) {
  2286.         // If I'm currently editing, then I should stop editing
  2287.         if (isEditing()) {
  2288.             removeEditor();
  2289.         }
  2290.         int firstIndex = e.getFirstIndex();
  2291.         int lastIndex = e.getLastIndex();
  2292.         if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
  2293.             repaint();
  2294.         }
  2295.         Rectangle firstColumnRect = getCellRect(0, firstIndex, false);
  2296.         Rectangle lastColumnRect = getCellRect(getRowCount(), lastIndex, false);
  2297.         Rectangle dirtyRegion = firstColumnRect.union(lastColumnRect);
  2298.         // This marks this entire column as dirty but the painting system will
  2299.         // intersect this with the clip rect of the viewport and redraw only
  2300.         // the visible cells.
  2301.         repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2302.     }
  2303.  
  2304. //
  2305. // Implementing ListSelectionListener interface
  2306. //
  2307.  
  2308.     /**
  2309.      * Tells listeners that the selection changed.
  2310.      *
  2311.      * @see ListSelectionListener
  2312.      */
  2313.     public void valueChanged(ListSelectionEvent e) {
  2314.         int firstIndex = e.getFirstIndex();
  2315.         int lastIndex = e.getLastIndex();
  2316.         if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
  2317.             repaint();
  2318.         }
  2319.         Rectangle firstRowRect = getCellRect(firstIndex, 0, false);
  2320.         Rectangle lastRowRect = getCellRect(lastIndex, getColumnCount(), false);
  2321.         Rectangle dirtyRegion = firstRowRect.union(lastRowRect);
  2322.         // This marks this entire row as dirty but the painting system will
  2323.         // intersect this with the clip rect of the viewport and redraw only
  2324.         // the visible cells.
  2325.         repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2326.     }
  2327.  
  2328. //
  2329. // Implementing the CellEditorListener interface
  2330. //
  2331.  
  2332.     /**
  2333.      * Invoked when editing is finished. The changes are saved, the
  2334.      * editor object is discarded, and the cell is rendered once again.
  2335.      *
  2336.      * @see CellEditorListener
  2337.      */
  2338.     public void editingStopped(ChangeEvent e) {
  2339.         // Take in the new value
  2340.         TableCellEditor editor = getCellEditor();
  2341.         if (editor != null) {
  2342.             Object value = editor.getCellEditorValue();
  2343.             setValueAt(value, editingRow, editingColumn);
  2344.  
  2345.             removeEditor();
  2346.         }
  2347.     }
  2348.  
  2349.     /**
  2350.      * Invoked when editing is canceled. The editor object is discarded
  2351.      * and the cell is rendered once again.
  2352.      *
  2353.      * @see CellEditorListener
  2354.      */
  2355.     public void editingCanceled(ChangeEvent e) {
  2356.         removeEditor();
  2357.     }
  2358.  
  2359. //
  2360. // Implementing the Scrollable interface
  2361. //
  2362.  
  2363.     /**
  2364.      * Sets the preferred size of the viewport for this table.
  2365.      *
  2366.      * @param size  a Dimension object specifying the preferredSize of a
  2367.      *              JViewport whose view is this table
  2368.      * @see Scrollable#getPreferredScrollableViewportSize
  2369.      * @beaninfo
  2370.      * description: The preferred size of the viewport.
  2371.      */
  2372.     public void setPreferredScrollableViewportSize(Dimension size) {
  2373.         preferredViewportSize = size;
  2374.     }
  2375.  
  2376.     /**
  2377.      * Returns the preferred size of the viewport for this table.
  2378.      *
  2379.      * @return a Dimension object containing the preferredSize of the JViewport
  2380.      *         which displays this table
  2381.      * @see Scrollable#getPreferredScrollableViewportSize
  2382.      */
  2383.     public Dimension getPreferredScrollableViewportSize() {
  2384.         return preferredViewportSize;
  2385.     }
  2386.  
  2387.     /**
  2388.      * Returns the scroll increment that completely exposes one new row
  2389.      * or column (depending on the orientation).
  2390.      * <p>
  2391.      * This method is called each time the user requests a unit scroll.
  2392.      *
  2393.      * @param visibleRect The view area visible within the viewport
  2394.      * @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
  2395.      * @param direction Less than zero to scroll up/left, greater than zero for down/right.
  2396.      * @return The "unit" increment for scrolling in the specified direction
  2397.      * @see Scrollable#getScrollableUnitIncrement
  2398.      */
  2399.     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
  2400.                                           int direction) {
  2401.         // PENDING(alan): do something smarter
  2402.         if (orientation == SwingConstants.HORIZONTAL) {
  2403.             return 1;
  2404.         }
  2405.         return rowHeight;
  2406.     }
  2407.  
  2408.     /**
  2409.      * Returns The visibleRect.height or visibleRect.width, depending on the
  2410.      * table's orientation.
  2411.      *
  2412.      * @return The visibleRect.height or visibleRect.width per the orientation.
  2413.      * @see Scrollable#getScrollableBlockIncrement
  2414.      */
  2415.     public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation,
  2416.                                            int direction) {
  2417.         return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
  2418.             visibleRect.width;
  2419.     }
  2420.  
  2421.     /**
  2422.      * Returns false to indicate that the width of the viewport does not
  2423.      * determine the width of the table.
  2424.      *
  2425.      * @return false
  2426.      * @see Scrollable#getScrollableTracksViewportWidth
  2427.      */
  2428.     public boolean getScrollableTracksViewportWidth() {
  2429.         return false;
  2430.     }
  2431.  
  2432.     /**
  2433.      * Returns false to indicate that the height of the viewport does not
  2434.      * determine the height of the table.
  2435.      *
  2436.      * @return false
  2437.      * @see Scrollable#getScrollableTracksViewportHeight
  2438.      */
  2439.     public boolean getScrollableTracksViewportHeight() {
  2440.         return false;
  2441.     }
  2442.  
  2443. //
  2444. // Protected Methods
  2445. //
  2446.  
  2447.     private class CheckBoxRenderer extends JCheckBox implements TableCellRenderer
  2448.     {
  2449.         public Component getTableCellRendererComponent(JTable table, Object value,
  2450.                          boolean isSelected, boolean hasFocus, int row, int column) {
  2451.             setSelected((value != null && ((Boolean)value).booleanValue()));
  2452.             return this;
  2453.         }
  2454.     }
  2455.  
  2456.     protected void createDefaultRenderers() {
  2457.         defaultRenderersByColumnClass = new Hashtable();
  2458.  
  2459.         // Objects
  2460.         DefaultTableCellRenderer label = new DefaultTableCellRenderer();
  2461.         setDefaultRenderer(Object.class, label);
  2462.  
  2463.         // Numbers
  2464.         DefaultTableCellRenderer rightAlignedLabel = new DefaultTableCellRenderer();
  2465.         rightAlignedLabel.setHorizontalAlignment(JLabel.RIGHT);
  2466.         setDefaultRenderer(Number.class, rightAlignedLabel);
  2467.  
  2468.         // Icons
  2469.         DefaultTableCellRenderer centeredLabel = new DefaultTableCellRenderer() {
  2470.             public void setValue(Object value) { setIcon((Icon)value); }
  2471.         };
  2472.         centeredLabel.setHorizontalAlignment(JLabel.CENTER);
  2473.         setDefaultRenderer(ImageIcon.class, centeredLabel);
  2474.  
  2475.         // Booleans
  2476. /*      DefaultTableCellRenderer booleanRenderer = new DefaultTableCellRenderer() {
  2477.             Icon trueIcon = UIManager.getIcon("CheckBox.icon");
  2478.             public void setValue(Object value) {
  2479.                 setIcon((value != null && ((Boolean)value).booleanValue()) ? trueIcon : null);
  2480.             }
  2481.         };
  2482.         booleanRenderer.setHorizontalAlignment(JLabel.CENTER);
  2483.         setDefaultRenderer(Boolean.class, booleanRenderer);
  2484. */
  2485.         CheckBoxRenderer booleanRenderer = new CheckBoxRenderer();
  2486.         booleanRenderer.setHorizontalAlignment(JLabel.CENTER);
  2487.         setDefaultRenderer(Boolean.class, booleanRenderer);
  2488.     }
  2489.  
  2490.     /**
  2491.      * Creates default cell editors for Objects, numbers, and boolean values.
  2492.      */
  2493.     protected void createDefaultEditors() {
  2494.         defaultEditorsByColumnClass = new Hashtable();
  2495.  
  2496.         // Objects
  2497.         JTextField textField = new JTextField();
  2498.         textField.setBorder(new LineBorder(Color.black));
  2499.         setDefaultEditor(Object.class, new DefaultCellEditor(textField));
  2500.  
  2501.         // Numbers
  2502.         JTextField rightAlignedTextField = new JTextField();
  2503.         rightAlignedTextField.setHorizontalAlignment(JTextField.RIGHT);
  2504.         rightAlignedTextField.setBorder(new LineBorder(Color.black));
  2505.         setDefaultEditor(Number.class, new DefaultCellEditor(rightAlignedTextField));
  2506.  
  2507.         // Booleans
  2508.         JCheckBox centeredCheckBox = new JCheckBox();
  2509.         centeredCheckBox.setHorizontalAlignment(JCheckBox.CENTER);
  2510.         setDefaultEditor(Boolean.class, new DefaultCellEditor(centeredCheckBox));
  2511.     }
  2512.  
  2513.     /**
  2514.      * Initializes table properties to their default values.
  2515.      */
  2516.     protected void initializeLocalVars() {
  2517.         createDefaultRenderers();
  2518.         createDefaultEditors();
  2519.  
  2520.         setTableHeader(createDefaultTableHeader());
  2521.  
  2522.     //     setBackground(Color.white);  // sdw
  2523.     //      setGridColor(Color.gray);   // sdw
  2524.         setShowGrid(true);
  2525.         setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
  2526.         setRowHeight(16);
  2527.         setIntercellSpacing(new Dimension(1,1));
  2528.         setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
  2529.         setColumnSelectionAllowed(false);
  2530.         setRowSelectionAllowed(true);
  2531.         setCellSelectionEnabled(false);
  2532.         setAutoCreateColumnsFromModel(true);
  2533.         cellEditor = null;
  2534.         editingColumn = editingRow = -1;
  2535.         preferredViewportSize = new Dimension(450,400);
  2536.  
  2537.         // I'm registered to do tool tips so we can draw tips for the
  2538.         // renderers
  2539.         ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
  2540.         toolTipManager.registerComponent(this);
  2541.  
  2542.         setAutoscrolls(true);
  2543.         tableHeader.setAutoscrolls(true);
  2544.     }
  2545.  
  2546.     /**
  2547.      * Returns the default table model object which is
  2548.      * a DefaultTableModel.  Subclass can override this
  2549.      * method to return a different table model object.
  2550.      *
  2551.      * @return the default table model object
  2552.      */
  2553.     protected TableModel createDefaultDataModel() {
  2554.         return new DefaultTableModel();
  2555.     }
  2556.  
  2557.     /**
  2558.      * Returns the default column model object which is
  2559.      * a DefaultTableColumnModel.  Subclass can override this
  2560.      * method to return a different column model object
  2561.      *
  2562.      * @return the default column model object
  2563.      */
  2564.     protected TableColumnModel createDefaultColumnModel() {
  2565.         return new DefaultTableColumnModel();
  2566.     }
  2567.  
  2568.     /**
  2569.      * Returns the default selection model object which is
  2570.      * a DefaultListSelectionModel.  Subclass can override this
  2571.      * method to return a different selection model object.
  2572.      *
  2573.      * @return the default selection model object
  2574.      */
  2575.     protected ListSelectionModel createDefaultSelectionModel() {
  2576.         DefaultListSelectionModel m = new DefaultListSelectionModel();
  2577.         // By turning this off we get notified of the minimal range of rows
  2578.         // that need to be drawn when the selection changes. This improves
  2579.         // redrawing performance considerably during mouseDragged.
  2580.         m.setLeadAnchorNotificationEnabled(false);
  2581.         return m;
  2582.     }
  2583.  
  2584.     /**
  2585.      * Returns the default table header object which is
  2586.      * a JTableHeader.  Subclass can override this
  2587.      * method to return a different table header object
  2588.      *
  2589.      * @return the default table header object
  2590.      */
  2591.     protected JTableHeader createDefaultTableHeader() {
  2592.         return new JTableHeader(columnModel);
  2593.     }
  2594.  
  2595.     /**
  2596.      * Properly sizes the receiver and its header view, and marks it as
  2597.      * needing display. Also resets cursor rectangles for the header view
  2598.      * and line scroll amounts for the <B>JScrollPane</B>.
  2599.      */
  2600.     protected void resizeAndRepaint() {
  2601.         revalidate();
  2602.         repaint();
  2603.     }
  2604.  
  2605.     /**
  2606.      * Return the cellEditor.
  2607.      *
  2608.      * @return the TableCellEditor that does the editing
  2609.      * @see #cellEditor
  2610.      */
  2611.     public TableCellEditor getCellEditor() {
  2612.         return cellEditor;
  2613.     }
  2614.  
  2615.     /**
  2616.      * Set the cellEditor variable.
  2617.      *
  2618.      * @param anEditor  the TableCellEditor that does the editing
  2619.      * @see #cellEditor
  2620.      */
  2621.     public void setCellEditor(TableCellEditor anEditor) {
  2622.         cellEditor = anEditor;
  2623.     }
  2624.  
  2625.     /**
  2626.      * Set the editingColumn variable.
  2627.      *
  2628.      * @see #editingColumn
  2629.      */
  2630.     public void setEditingColumn(int aColumn) {
  2631.         editingColumn = aColumn;
  2632.     }
  2633.  
  2634.     /**
  2635.      * Set the editingRow variable.
  2636.      *
  2637.      * @see #editingRow
  2638.      */
  2639.     public void setEditingRow(int aRow) {
  2640.         editingRow = aRow;
  2641.     }
  2642.  
  2643.     /**
  2644.      * Returns true to indicate that this component paints every pixel
  2645.      * in its range. (In other words, it does not have a transparent
  2646.      * background or foreground.)
  2647.      *
  2648.      * @return true
  2649.      * @see JComponent#isOpaque
  2650.      */
  2651.     public boolean isOpaque() {
  2652.         return true;
  2653.     }
  2654.  
  2655.     /**
  2656.      * Sets up the specified editor using the value at the specified cell.
  2657.      *
  2658.      * @param editor  the TableCellEditor to set up
  2659.      * @param row     the row of the cell to edit, where 0 is the first
  2660.      * @param column  the column of the cell to edit, where 0 is the first
  2661.      */
  2662.     public Component prepareEditor(TableCellEditor editor,
  2663.                                    int row, int column) {
  2664.         Object value = getValueAt(row, column);
  2665.  
  2666.         TableColumn tableColumn = getColumnModel().getColumn(column);
  2667.         boolean isSelected = isCellSelected(row, column);
  2668.         Component comp = editor.getTableCellEditorComponent(this, value, isSelected,
  2669.                                                   row, column);
  2670.         if((comp != null) && (comp.getFont() == null)) {
  2671.             comp.setFont(getFont());
  2672.         }
  2673.         return comp;
  2674.     }
  2675.  
  2676.     /**
  2677.      * Discard the editor object and return the real estate it used to
  2678.      * cell rendering.
  2679.      */
  2680.     public void removeEditor() {
  2681.         TableCellEditor editor = getCellEditor();
  2682.         if(editor != null) {
  2683.             editor.removeCellEditorListener(this);
  2684.  
  2685.             // PENDING(alan): This is a temp work around for a JComboBox bug
  2686.             if (editorComp instanceof JComboBox) {
  2687.                 ((JComboBox)editorComp).hidePopup();
  2688.             }
  2689.  
  2690.             remove(editorComp);
  2691.             Rectangle cellRect = getCellRect(editingRow, editingColumn, false);
  2692.             repaint(cellRect.x, cellRect.y,
  2693.                     cellRect.width, cellRect.height);
  2694.  
  2695.             if (!(editorComp instanceof JComponent) ||
  2696.                  ((JComponent)editorComp).hasFocus()) {
  2697.                 requestFocus();
  2698.             }
  2699.  
  2700.             setCellEditor(null);
  2701.             setEditingColumn(-1);
  2702.             setEditingRow(-1);
  2703.             editorComp = null;
  2704.         }
  2705.     }
  2706.  
  2707. //
  2708. // Serialization
  2709. //
  2710.  
  2711.     private void writeObject(ObjectOutputStream s) throws IOException {
  2712.         s.defaultWriteObject();
  2713.     }
  2714.  
  2715.  
  2716.     private void readObject(ObjectInputStream s)
  2717.         throws IOException, ClassNotFoundException
  2718.     {
  2719.         s.defaultReadObject();
  2720.         createDefaultRenderers();
  2721.         createDefaultEditors();
  2722.     }
  2723.  
  2724. /////////////////
  2725. // Accessibility support
  2726. ////////////////
  2727.  
  2728.     /**
  2729.      * Get the AccessibleContext associated with this JComponent
  2730.      *
  2731.      * @return the AccessibleContext of this JComponent
  2732.      */
  2733.     public AccessibleContext getAccessibleContext() {
  2734.         if (accessibleContext == null) {
  2735.             accessibleContext = new AccessibleJTable();
  2736.         }
  2737.         return accessibleContext;
  2738.     }
  2739.  
  2740.     //
  2741.     // *** should also implement AccessibleSelction?
  2742.     // *** and what's up with keyboard navigation/manipulation?
  2743.     //
  2744.     /**
  2745.      * The class used to obtain the accessible role for this object.
  2746.      * <p>
  2747.      * Warning: serialized objects of this class will not be compatible with
  2748.      * future swing releases.  The current serialization support is appropriate
  2749.      * for short term storage or RMI between Swing1.0 applications.  It will
  2750.      * not be possible to load serialized Swing1.0 objects with future releases
  2751.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  2752.      * baseline for the serialized form of Swing objects.
  2753.      */
  2754.     protected class AccessibleJTable extends AccessibleJComponent {
  2755.  
  2756.         /**
  2757.          * Get the role of this object.
  2758.          *
  2759.          * @return an instance of AccessibleRole describing the role of the
  2760.          * object
  2761.          * @see AccessibleRole
  2762.          */
  2763.         public AccessibleRole getAccessibleRole() {
  2764.             return AccessibleRole.TABLE;
  2765.         }
  2766.  
  2767.         /**
  2768.          * Returns the Accessible child, if one exists, contained at the local
  2769.          * coordinate Point.
  2770.          *
  2771.          * @param p The point defining the top-left corner of the Accessible,
  2772.          * given in the coordinate space of the object's parent.
  2773.          * @return the Accessible, if it exists, at the specified location;
  2774.          * else null
  2775.          */
  2776.         public Accessible getAccessibleAt(Point p) {
  2777.             int column = columnAtPoint(p);
  2778.             int row = rowAtPoint(p);
  2779.  
  2780.             if ((column != -1) && (row != -1)) {
  2781.                 TableColumn aColumn = getColumnModel().getColumn(column);
  2782.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  2783.                 if (renderer == null) {
  2784.                     Class columnClass = getColumnClass(column);
  2785.                     renderer = getDefaultRenderer(columnClass);
  2786.                 }
  2787.                 Component component = renderer.getTableCellRendererComponent(
  2788.                                   JTable.this, null, false, false,
  2789.                                   row, column);
  2790.                 return new AccessibleJTableCell(JTable.this, row, column,
  2791.                       getAccessibleIndexAt(row, column));
  2792.             }
  2793.             return null;
  2794.         }
  2795.  
  2796.         /**
  2797.          * Returns the number of accessible children in the object.  If all
  2798.          * of the children of this object implement Accessible, than this
  2799.          * method should return the number of children of this object.
  2800.          *
  2801.          * @return the number of accessible children in the object.
  2802.          */
  2803.         public int getAccessibleChildrenCount() {
  2804.             return (JTable.this.getColumnCount() * JTable.this.getRowCount());
  2805.         }
  2806.  
  2807.         /**
  2808.          * Return the nth Accessible child of the object.
  2809.          *
  2810.          * @param i zero-based index of child
  2811.          * @return the nth Accessible child of the object
  2812.          */
  2813.         public Accessible getAccessibleChild(int i) {
  2814.             if (i < 0 || i >= getAccessibleChildrenCount()) {
  2815.                 return null;
  2816.             } else {
  2817.                 // children increase across, and then down, for tables
  2818.                 // (arbitrary decision)
  2819.                 int column = getAccessibleColumnAtIndex(i);
  2820.                 int row = getAccessibleRowAtIndex(i);
  2821.  
  2822.                 TableColumn aColumn = getColumnModel().getColumn(column);
  2823.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  2824.                 if (renderer == null) {
  2825.                     Class columnClass = getColumnClass(column);
  2826.                     renderer = getDefaultRenderer(columnClass);
  2827.                 }
  2828.                 Component component = renderer.getTableCellRendererComponent(
  2829.                                   JTable.this, null, false, false,
  2830.                                   row, column);
  2831.                 return new AccessibleJTableCell(JTable.this, row, column,
  2832.                       getAccessibleIndexAt(row, column));
  2833.             }
  2834.         }
  2835.  
  2836. //        /**
  2837. //         * Get the AccessibleTable associated with this object if one
  2838. //         * exists.  Otherwise return null.
  2839. //         */
  2840. //        public AccessibleTable getAccessibleTable() {
  2841. //            return this;
  2842. //        }
  2843.  
  2844.  
  2845.     // AccessibleTable methods
  2846.  
  2847.         /*
  2848.          * Returns the total number of rows in the table
  2849.          *
  2850.          * @return the total number of rows in the table
  2851.          */
  2852.         private int getAccessibleRowCount() {
  2853.             return JTable.this.getRowCount();
  2854.         }
  2855.  
  2856.         /*
  2857.          * Returns the total number of columns in the table
  2858.          *
  2859.          * @return the total number of columns in the table
  2860.          */
  2861.         private int getAccessibleColumnCount() {
  2862.             return JTable.this.getColumnCount();
  2863.         }
  2864.  
  2865.         /*
  2866.          * Returns the row at a given index into the table
  2867.          *
  2868.          * @param i zero-based index into the table
  2869.          * @return the row at a given index
  2870.          */
  2871.         private int getAccessibleRowAtIndex(int i) {
  2872.             return (i / getAccessibleColumnCount());
  2873.         }
  2874.  
  2875.         /*
  2876.          * Returns the column at a given index into the table
  2877.          *
  2878.          * @param i zero-based index into the table
  2879.          * @return the column at a given index
  2880.          */
  2881.         private int getAccessibleColumnAtIndex(int i) {
  2882.             return (i % getAccessibleColumnCount());
  2883.         }
  2884.  
  2885.         /*
  2886.          * Returns the index at a given (row, column) in the table
  2887.          *
  2888.          * @param r zero-based row of the table
  2889.          * @param c zero-based column of the table
  2890.          * @return the index into the table
  2891.          */
  2892.         private int getAccessibleIndexAt(int r, int c) {
  2893.             return ((r * getAccessibleColumnCount()) + c);
  2894.         }
  2895.  
  2896.         /*
  2897.          * Returns the Accessible at a given (row, column) in the table
  2898.          *
  2899.          * @param r zero-based row of the table
  2900.          * @param c zero-based column of the table
  2901.          * @return the Accessible at the specified (row, column)
  2902.          */
  2903.         private Accessible getAccessibleAt(int r, int c) {
  2904.             return getAccessibleChild((r * getAccessibleColumnCount()) + c);
  2905.         }
  2906.  
  2907.         /*
  2908.          * Return the Accessible representing the row header, if
  2909.          * there is one (may be null).
  2910.          *
  2911.          * @param row zero-based row of the table
  2912.          * @return the Accessible header of the row
  2913.          */
  2914.         private Accessible getAccessibleRowHeader(int row) {
  2915.             return null;
  2916.         }
  2917.  
  2918.         /*
  2919.          * Return the Accessible representing the column header, if
  2920.          * there is one (may be null)
  2921.          *
  2922.          * @param column zero-based column of the table
  2923.          * @return the Accessible header of the column
  2924.          */
  2925.         private Accessible getAccessibleColumnHeader(int column) {
  2926.             JTableHeader header = JTable.this.getTableHeader();
  2927.             AccessibleContext ac = header.getAccessibleContext();
  2928.             if (ac != null) {
  2929.                 return ac.getAccessibleChild(column);
  2930.             } else {
  2931.                 return null;
  2932.             }
  2933.         }
  2934.  
  2935.  
  2936.         /**
  2937.          * The class used to obtain the AccessibleRole for a cell.
  2938.          */
  2939.         protected class AccessibleJTableCell extends AccessibleContext
  2940.             implements Accessible, AccessibleComponent {
  2941.  
  2942.             private JTable parent;
  2943.             private int row;
  2944.             private int column;
  2945.             private int index;
  2946.  
  2947.             /**
  2948.              *  Constructs an AccessiblJTableHeaaderEntry
  2949.              */
  2950.             public AccessibleJTableCell(JTable t, int r, int c, int i) {
  2951.                 parent = t;
  2952.                 row = r;
  2953.                 column = c;
  2954.                 index = i;
  2955.                 this.setAccessibleParent(parent);
  2956.             }
  2957.  
  2958.             /**
  2959.              * Get the AccessibleContext associated with this
  2960.              *
  2961.              * @return the AccessibleContext of this JComponent
  2962.              */
  2963.             public AccessibleContext getAccessibleContext() {
  2964.                 return this;
  2965.             }
  2966.  
  2967.             private AccessibleContext getCurrentAccessibleContext() {
  2968.                 TableColumn aColumn = getColumnModel().getColumn(column);
  2969.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  2970.                 if (renderer == null) {
  2971.                     Class columnClass = getColumnClass(column);
  2972.                     renderer = getDefaultRenderer(columnClass);
  2973.                 }
  2974.                 Component component = renderer.getTableCellRendererComponent(
  2975.                                   JTable.this, null, false, false,
  2976.                                   row, column);
  2977.                 if (component instanceof Accessible) {
  2978.                     return ((Accessible) component).getAccessibleContext();
  2979.                 } else {
  2980.                     return null;
  2981.                 }
  2982.             }
  2983.  
  2984.             private Component getCurrentComponent() {
  2985.                 TableColumn aColumn = getColumnModel().getColumn(column);
  2986.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  2987.                 if (renderer == null) {
  2988.                     Class columnClass = getColumnClass(column);
  2989.                     renderer = getDefaultRenderer(columnClass);
  2990.                 }
  2991.                 return renderer.getTableCellRendererComponent(
  2992.                                   JTable.this, null, false, false,
  2993.                                   row, column);
  2994.             }
  2995.  
  2996.         // AccessibleContext methods
  2997.  
  2998.             /**
  2999.              * Get the accessible name of this object.
  3000.              *
  3001.              * @return the localized name of the object; null if this
  3002.              * object does not have a name
  3003.              */
  3004.             public String getAccessibleName() {
  3005.                 AccessibleContext ac = getCurrentAccessibleContext();
  3006.                 if (ac != null) {
  3007.                     String name = ac.getAccessibleName();
  3008.                     if ((name != null) && (name != "")) {
  3009.                         return ac.getAccessibleName();
  3010.                     }
  3011.                 }
  3012.                 if ((accessibleName != null) && (accessibleName != "")) {
  3013.                     return accessibleName;
  3014.                 } else {
  3015.                     return parent.getValueAt(row, column).toString();
  3016.                 }
  3017.             }
  3018.  
  3019.             /**
  3020.              * Set the localized accessible name of this object.
  3021.              *
  3022.              * @param s the new localized name of the object.
  3023.              */
  3024.             public void setAccessibleName(String s) {
  3025.                 AccessibleContext ac = getCurrentAccessibleContext();
  3026.                 if (ac != null) {
  3027.                     ac.setAccessibleName(s);
  3028.                 } else {
  3029.                     super.setAccessibleName(s);
  3030.                 }
  3031.             }
  3032.  
  3033.             //
  3034.             // *** should check toolip text for desc. (needs MouseEvent)
  3035.             //
  3036.             /**
  3037.              * Get the accessible description of this object.
  3038.              *
  3039.              * @return the localized description of the object; null if
  3040.              * this object does not have a description
  3041.              */
  3042.             public String getAccessibleDescription() {
  3043.                 AccessibleContext ac = getCurrentAccessibleContext();
  3044.                 if (ac != null) {
  3045.                     return ac.getAccessibleDescription();
  3046.                 } else {
  3047.                     return super.getAccessibleDescription();
  3048.                 }
  3049.             }
  3050.  
  3051.             /**
  3052.              * Set the accessible description of this object.
  3053.              *
  3054.              * @param s the new localized description of the object
  3055.              */
  3056.             public void setAccessibleDescription(String s) {
  3057.                 AccessibleContext ac = getCurrentAccessibleContext();
  3058.                 if (ac != null) {
  3059.                     ac.setAccessibleDescription(s);
  3060.                 } else {
  3061.                     super.setAccessibleDescription(s);
  3062.                 }
  3063.             }
  3064.  
  3065.             /**
  3066.              * Get the role of this object.
  3067.              *
  3068.              * @return an instance of AccessibleRole describing the role of the object
  3069.              * @see AccessibleRole
  3070.              */
  3071.             public AccessibleRole getAccessibleRole() {
  3072.                 AccessibleContext ac = getCurrentAccessibleContext();
  3073.                 if (ac != null) {
  3074.                     return ac.getAccessibleRole();
  3075.                 } else {
  3076.                     return AccessibleRole.UNKNOWN;
  3077.                 }
  3078.             }
  3079.  
  3080.             /**
  3081.              * Get the state set of this object.
  3082.              *
  3083.              * @return an instance of AccessibleStateSet containing the
  3084.              * current state set of the object
  3085.              * @see AccessibleState
  3086.              */
  3087.             public AccessibleStateSet getAccessibleStateSet() {
  3088.                 AccessibleContext ac = getCurrentAccessibleContext();
  3089.                 if (ac != null) {
  3090.                     return ac.getAccessibleStateSet();
  3091.                 } else {
  3092.                     return new AccessibleStateSet();  // must be non null?
  3093.                 }
  3094.             }
  3095.  
  3096.             /**
  3097.              * Get the Accessible parent of this object.
  3098.              *
  3099.              * @return the Accessible parent of this object; null if this
  3100.              * object does not have an Accessible parent
  3101.              */
  3102.             public Accessible getAccessibleParent() {
  3103.                 return parent;
  3104.             }
  3105.  
  3106.             /**
  3107.              * Get the index of this object in its accessible parent.
  3108.              *
  3109.              * @return the index of this object in its parent; -1 if this
  3110.              * object does not have an accessible parent.
  3111.              * @see #getAccessibleParent
  3112.              */
  3113.             public int getAccessibleIndexInParent() {
  3114.                 return index;
  3115.             }
  3116.  
  3117.             /**
  3118.              * Returns the number of accessible children in the object.
  3119.              *
  3120.              * @return the number of accessible children in the object.
  3121.              */
  3122.             public int getAccessibleChildrenCount() {
  3123.                 AccessibleContext ac = getCurrentAccessibleContext();
  3124.                 if (ac != null) {
  3125.                     return ac.getAccessibleChildrenCount();
  3126.                 } else {
  3127.                     return 0;
  3128.                 }
  3129.             }
  3130.  
  3131.             /**
  3132.              * Return the specified Accessible child of the object.
  3133.              *
  3134.              * @param i zero-based index of child
  3135.              * @return the Accessible child of the object
  3136.              */
  3137.             public Accessible getAccessibleChild(int i) {
  3138.                 AccessibleContext ac = getCurrentAccessibleContext();
  3139.                 if (ac != null) {
  3140.                     Accessible accessibleChild = ac.getAccessibleChild(i);
  3141.                     ac.setAccessibleParent(this);
  3142.                     return accessibleChild;
  3143.                 } else {
  3144.                     return null;
  3145.                 }
  3146.             }
  3147.  
  3148.             /**
  3149.              * Gets the locale of the component. If the component does not have a
  3150.              * locale, then the locale of its parent is returned.
  3151.              *
  3152.              * @return This component's locale. If this component does not have a locale, the locale of its parent is returned.
  3153.              * @exception IllegalComponentStateException
  3154.              * If the Component does not have its own locale and has not yet been added to a containment hierarchy such that the locale can be
  3155.              * determined from the containing parent.
  3156.              * @see setLocale
  3157.              */
  3158.             public Locale getLocale() {
  3159.                 AccessibleContext ac = getCurrentAccessibleContext();
  3160.                 if (ac != null) {
  3161.                     return ac.getLocale();
  3162.                 } else {
  3163.                     return null;
  3164.                 }
  3165.             }
  3166.  
  3167.             /**
  3168.              * Add a PropertyChangeListener to the listener list.
  3169.              * The listener is registered for all properties.
  3170.              *
  3171.              * @param listener  The PropertyChangeListener to be added
  3172.              */
  3173.             public void addPropertyChangeListener(PropertyChangeListener l) {
  3174.                 AccessibleContext ac = getCurrentAccessibleContext();
  3175.                 if (ac != null) {
  3176.                     ac.addPropertyChangeListener(l);
  3177.                 } else {
  3178.                     super.addPropertyChangeListener(l);
  3179.                 }
  3180.             }
  3181.  
  3182.             /**
  3183.              * Remove a PropertyChangeListener from the listener list.
  3184.              * This removes a PropertyChangeListener that was registered
  3185.              * for all properties.
  3186.              *
  3187.              * @param listener  The PropertyChangeListener to be removed
  3188.              */
  3189.             public void removePropertyChangeListener(PropertyChangeListener l) {
  3190.                 AccessibleContext ac = getCurrentAccessibleContext();
  3191.                 if (ac != null) {
  3192.                     ac.removePropertyChangeListener(l);
  3193.                 } else {
  3194.                     super.removePropertyChangeListener(l);
  3195.                 }
  3196.             }
  3197.  
  3198.             /**
  3199.              * Get the AccessibleAction associated with this object if one
  3200.              * exists.  Otherwise return null.
  3201.              *
  3202.              * @return the AccessibleAction, or null
  3203.              */
  3204.             public AccessibleAction getAccessibleAction() {
  3205.                 return getCurrentAccessibleContext().getAccessibleAction();
  3206.             }
  3207.  
  3208.             /**
  3209.              * Get the AccessibleComponent associated with this object if one
  3210.              * exists.  Otherwise return null.
  3211.              *
  3212.              * @return the AccessibleComponent, or null
  3213.              */
  3214.             public AccessibleComponent getAccessibleComponent() {
  3215.                 return this; // to override getBounds()
  3216.             }
  3217.  
  3218.             /**
  3219.              * Get the AccessibleSelection associated with this object if one
  3220.              * exists.  Otherwise return null.
  3221.              *
  3222.              * @return the AccessibleSelection, or null
  3223.              */
  3224.             public AccessibleSelection getAccessibleSelection() {
  3225.                 return getCurrentAccessibleContext().getAccessibleSelection();
  3226.             }
  3227.  
  3228.             /**
  3229.              * Get the AccessibleText associated with this object if one
  3230.              * exists.  Otherwise return null.
  3231.              *
  3232.              * @return the AccessibleText, or null
  3233.              */
  3234.             public AccessibleText getAccessibleText() {
  3235.                 return getCurrentAccessibleContext().getAccessibleText();
  3236.             }
  3237.  
  3238.             /**
  3239.              * Get the AccessibleValue associated with this object if one
  3240.              * exists.  Otherwise return null.
  3241.              *
  3242.              * @return the AccessibleValue, or null
  3243.              */
  3244.             public AccessibleValue getAccessibleValue() {
  3245.                 return getCurrentAccessibleContext().getAccessibleValue();
  3246.             }
  3247.  
  3248.  
  3249.         // AccessibleComponent methods
  3250.  
  3251.             /**
  3252.              * Get the background color of this object.
  3253.              *
  3254.              * @return the background color, if supported, of the object;
  3255.              * otherwise, null
  3256.              */
  3257.             public Color getBackground() {
  3258.                 AccessibleContext ac = getCurrentAccessibleContext();
  3259.                 if (ac instanceof AccessibleComponent) {
  3260.                     return ((AccessibleComponent) ac).getBackground();
  3261.                 } else {
  3262.                     Component c = getCurrentComponent();
  3263.                     if (c != null) {
  3264.                         return c.getBackground();
  3265.                     } else {
  3266.                         return null;
  3267.                     }
  3268.                 }
  3269.             }
  3270.  
  3271.             /**
  3272.              * Set the background color of this object.
  3273.              *
  3274.              * @param c the new Color for the background
  3275.              */
  3276.             public void setBackground(Color c) {
  3277.                 AccessibleContext ac = getCurrentAccessibleContext();
  3278.                 if (ac instanceof AccessibleComponent) {
  3279.                     ((AccessibleComponent) ac).setBackground(c);
  3280.                 } else {
  3281.                     Component cp = getCurrentComponent();
  3282.                     if (cp != null) {
  3283.                         cp.setBackground(c);
  3284.                     }
  3285.                 }
  3286.             }
  3287.  
  3288.             /**
  3289.              * Get the foreground color of this object.
  3290.              *
  3291.              * @return the foreground color, if supported, of the object;
  3292.              * otherwise, null
  3293.              */
  3294.             public Color getForeground() {
  3295.                 AccessibleContext ac = getCurrentAccessibleContext();
  3296.                 if (ac instanceof AccessibleComponent) {
  3297.                     return ((AccessibleComponent) ac).getForeground();
  3298.                 } else {
  3299.                     Component c = getCurrentComponent();
  3300.                     if (c != null) {
  3301.                         return c.getForeground();
  3302.                     } else {
  3303.                         return null;
  3304.                     }
  3305.                 }
  3306.             }
  3307.  
  3308.             /**
  3309.              * Set the foreground color of this object.
  3310.              *
  3311.              * @param c the new Color for the foreground
  3312.              */
  3313.             public void setForeground(Color c) {
  3314.                 AccessibleContext ac = getCurrentAccessibleContext();
  3315.                 if (ac instanceof AccessibleComponent) {
  3316.                     ((AccessibleComponent) ac).setForeground(c);
  3317.                 } else {
  3318.                     Component cp = getCurrentComponent();
  3319.                     if (cp != null) {
  3320.                         cp.setForeground(c);
  3321.                     }
  3322.                 }
  3323.             }
  3324.  
  3325.             /**
  3326.              * Get the Cursor of this object.
  3327.              *
  3328.              * @return the Cursor, if supported, of the object; otherwise, null
  3329.              */
  3330.             public Cursor getCursor() {
  3331.                 AccessibleContext ac = getCurrentAccessibleContext();
  3332.                 if (ac instanceof AccessibleComponent) {
  3333.                     return ((AccessibleComponent) ac).getCursor();
  3334.                 } else {
  3335.                     Component c = getCurrentComponent();
  3336.                     if (c != null) {
  3337.                         return c.getCursor();
  3338.                     } else {
  3339.                         Accessible ap = getAccessibleParent();
  3340.                         if (ap instanceof AccessibleComponent) {
  3341.                             return ((AccessibleComponent) ap).getCursor();
  3342.                         } else {
  3343.                             return null;
  3344.                         }
  3345.                     }
  3346.                 }
  3347.             }
  3348.  
  3349.             /**
  3350.              * Set the Cursor of this object.
  3351.              *
  3352.              * @param c the new Cursor for the object
  3353.              */
  3354.             public void setCursor(Cursor c) {
  3355.                 AccessibleContext ac = getCurrentAccessibleContext();
  3356.                 if (ac instanceof AccessibleComponent) {
  3357.                     ((AccessibleComponent) ac).setCursor(c);
  3358.                 } else {
  3359.                     Component cp = getCurrentComponent();
  3360.                     if (cp != null) {
  3361.                         cp.setCursor(c);
  3362.                     }
  3363.                 }
  3364.             }
  3365.  
  3366.             /**
  3367.              * Get the Font of this object.
  3368.              *
  3369.              * @return the Font,if supported, for the object; otherwise, null
  3370.              */
  3371.             public Font getFont() {
  3372.                 AccessibleContext ac = getCurrentAccessibleContext();
  3373.                 if (ac instanceof AccessibleComponent) {
  3374.                     return ((AccessibleComponent) ac).getFont();
  3375.                 } else {
  3376.                     Component c = getCurrentComponent();
  3377.                     if (c != null) {
  3378.                         return c.getFont();
  3379.                     } else {
  3380.                         return null;
  3381.                     }
  3382.                 }
  3383.             }
  3384.  
  3385.             /**
  3386.              * Set the Font of this object.
  3387.              *
  3388.              * @param f the new Font for the object
  3389.              */
  3390.             public void setFont(Font f) {
  3391.                 AccessibleContext ac = getCurrentAccessibleContext();
  3392.                 if (ac instanceof AccessibleComponent) {
  3393.                     ((AccessibleComponent) ac).setFont(f);
  3394.                 } else {
  3395.                     Component c = getCurrentComponent();
  3396.                     if (c != null) {
  3397.                         c.setFont(f);
  3398.                     }
  3399.                 }
  3400.             }
  3401.  
  3402.             /**
  3403.              * Get the FontMetrics of this object.
  3404.              *
  3405.              * @param f the Font
  3406.              * @return the FontMetrics, if supported, the object; otherwise, null
  3407.              * @see getFont
  3408.              */
  3409.             public FontMetrics getFontMetrics(Font f) {
  3410.                 AccessibleContext ac = getCurrentAccessibleContext();
  3411.                 if (ac instanceof AccessibleComponent) {
  3412.                     return ((AccessibleComponent) ac).getFontMetrics(f);
  3413.                 } else {
  3414.                     Component c = getCurrentComponent();
  3415.                     if (c != null) {
  3416.                         return c.getFontMetrics(f);
  3417.                     } else {
  3418.                         return null;
  3419.                     }
  3420.                 }
  3421.             }
  3422.  
  3423.             /**
  3424.              * Determine if the object is enabled.
  3425.              *
  3426.              * @return true if object is enabled; otherwise, false
  3427.              */
  3428.             public boolean isEnabled() {
  3429.                 AccessibleContext ac = getCurrentAccessibleContext();
  3430.                 if (ac instanceof AccessibleComponent) {
  3431.                     return ((AccessibleComponent) ac).isEnabled();
  3432.                 } else {
  3433.                     Component c = getCurrentComponent();
  3434.                     if (c != null) {
  3435.                         return c.isEnabled();
  3436.                     } else {
  3437.                         return false;
  3438.                     }
  3439.                 }
  3440.             }
  3441.  
  3442.             /**
  3443.              * Set the enabled state of the object.
  3444.              *
  3445.              * @param b if true, enables this object; otherwise, disables it
  3446.              */
  3447.             public void setEnabled(boolean b) {
  3448.                 AccessibleContext ac = getCurrentAccessibleContext();
  3449.                 if (ac instanceof AccessibleComponent) {
  3450.                     ((AccessibleComponent) ac).setEnabled(b);
  3451.                 } else {
  3452.                     Component c = getCurrentComponent();
  3453.                     if (c != null) {
  3454.                         c.setEnabled(b);
  3455.                     }
  3456.                 }
  3457.             }
  3458.  
  3459.             /**
  3460.              * Determine if the object is visible.  Note: this means that the
  3461.              * object intends to be visible; however, it may not in fact be
  3462.              * showing on the screen because one of the objects that this object
  3463.              * is contained by is not visible.  To determine if an object is
  3464.              * showing on the screen, use isShowing().
  3465.              *
  3466.              * @return true if object is visible; otherwise, false
  3467.              */
  3468.             public boolean isVisible() {
  3469.                 AccessibleContext ac = getCurrentAccessibleContext();
  3470.                 if (ac instanceof AccessibleComponent) {
  3471.                     return ((AccessibleComponent) ac).isVisible();
  3472.                 } else {
  3473.                     Component c = getCurrentComponent();
  3474.                     if (c != null) {
  3475.                         return c.isVisible();
  3476.                     } else {
  3477.                         return false;
  3478.                     }
  3479.                 }
  3480.             }
  3481.  
  3482.             /**
  3483.              * Set the visible state of the object.
  3484.              *
  3485.              * @param b if true, shows this object; otherwise, hides it
  3486.              */
  3487.             public void setVisible(boolean b) {
  3488.                 AccessibleContext ac = getCurrentAccessibleContext();
  3489.                 if (ac instanceof AccessibleComponent) {
  3490.                     ((AccessibleComponent) ac).setVisible(b);
  3491.                 } else {
  3492.                     Component c = getCurrentComponent();
  3493.                     if (c != null) {
  3494.                         c.setVisible(b);
  3495.                     }
  3496.                 }
  3497.             }
  3498.  
  3499.             /**
  3500.              * Determine if the object is showing.  This is determined by checking
  3501.              * the visibility of the object and ancestors of the object.  Note: this
  3502.              * will return true even if the object is obscured by another (for example,
  3503.              * it happens to be underneath a menu that was pulled down).
  3504.              *
  3505.              * @return true if object is showing; otherwise, false
  3506.              */
  3507.             public boolean isShowing() {
  3508.                 AccessibleContext ac = getCurrentAccessibleContext();
  3509.                 if (ac instanceof AccessibleComponent) {
  3510.                     return ((AccessibleComponent) ac).isShowing();
  3511.                 } else {
  3512.                     Component c = getCurrentComponent();
  3513.                     if (c != null) {
  3514.                         return c.isShowing();
  3515.                     } else {
  3516.                         return false;
  3517.                     }
  3518.                 }
  3519.             }
  3520.  
  3521.             /**
  3522.              * Checks whether the specified point is within this object's bounds,
  3523.              * where the point's x and y coordinates are defined to be relative to the
  3524.              * coordinate system of the object.
  3525.              *
  3526.              * @param p the Point relative to the coordinate system of the object
  3527.              * @return true if object contains Point; otherwise false
  3528.              */
  3529.             public boolean contains(Point p) {
  3530.                 AccessibleContext ac = getCurrentAccessibleContext();
  3531.                 if (ac instanceof AccessibleComponent) {
  3532.                     Rectangle r = ((AccessibleComponent) ac).getBounds();
  3533.                     return r.contains(p);
  3534.                 } else {
  3535.                     Component c = getCurrentComponent();
  3536.                     if (c != null) {
  3537.                         Rectangle r = c.getBounds();
  3538.                         return r.contains(p);
  3539.                     } else {
  3540.                         return getBounds().contains(p);
  3541.                     }
  3542.                 }
  3543.             }
  3544.  
  3545.             /**
  3546.              * Returns the location of the object on the screen.
  3547.              *
  3548.              * @return location of object on screen -- can be null if this object
  3549.              * is not on the screen
  3550.              */
  3551.             public Point getLocationOnScreen() {
  3552.                 if (parent != null) {
  3553.                     Point parentLocation = parent.getLocationOnScreen();
  3554.                     Point componentLocation = getLocation();
  3555.                     componentLocation.translate(parentLocation.x, parentLocation.y);
  3556.                     return componentLocation;
  3557.                 } else {
  3558.                     return null;
  3559.                 }
  3560.             }
  3561.  
  3562.             /**
  3563.              * Gets the location of the object relative to the parent in the form
  3564.              * of a point specifying the object's top-left corner in the screen's
  3565.              * coordinate space.
  3566.              *
  3567.              * @return An instance of Point representing the top-left corner of the
  3568.              * objects's bounds in the coordinate space of the screen; null if
  3569.              * this object or its parent are not on the screen
  3570.              */
  3571.             public Point getLocation() {
  3572.                 if (parent != null) {
  3573.                     Rectangle r = parent.getCellRect(row, column, false);
  3574.                     if (r != null) {
  3575.                         return r.getLocation();
  3576.                     }
  3577.                 }
  3578.                 return null;
  3579.             }
  3580.  
  3581.             /**
  3582.              * Sets the location of the object relative to the parent.
  3583.              */
  3584.             public void setLocation(Point p) {
  3585. //              if ((parent != null)  && (parent.contains(p))) {
  3586. //                  ensureIndexIsVisible(indexInParent);
  3587. //              }
  3588.             }
  3589.  
  3590.             public Rectangle getBounds() {
  3591.                 if (parent != null) {
  3592.                     return parent.getCellRect(row, column, false);
  3593.                 } else {
  3594.                     return null;
  3595.                 }
  3596.             }
  3597.  
  3598.             public void setBounds(Rectangle r) {
  3599.                 AccessibleContext ac = getCurrentAccessibleContext();
  3600.                 if (ac instanceof AccessibleComponent) {
  3601.                     ((AccessibleComponent) ac).setBounds(r);
  3602.                 } else {
  3603.                     Component c = getCurrentComponent();
  3604.                     if (c != null) {
  3605.                         c.setBounds(r);
  3606.                     }
  3607.                 }
  3608.             }
  3609.  
  3610.             public Dimension getSize() {
  3611.                 if (parent != null) {
  3612.                     Rectangle r = parent.getCellRect(row, column, false);
  3613.                     if (r != null) {
  3614.                         return r.getSize();
  3615.                     }
  3616.                 }
  3617.                 return null;
  3618.             }
  3619.  
  3620.             public void setSize (Dimension d) {
  3621.                 AccessibleContext ac = getCurrentAccessibleContext();
  3622.                 if (ac instanceof AccessibleComponent) {
  3623.                     ((AccessibleComponent) ac).setSize(d);
  3624.                 } else {
  3625.                     Component c = getCurrentComponent();
  3626.                     if (c != null) {
  3627.                         c.setSize(d);
  3628.                     }
  3629.                 }
  3630.             }
  3631.  
  3632.             public Accessible getAccessibleAt(Point p) {
  3633.                 AccessibleContext ac = getCurrentAccessibleContext();
  3634.                 if (ac instanceof AccessibleComponent) {
  3635.                     return ((AccessibleComponent) ac).getAccessibleAt(p);
  3636.                 } else {
  3637.                     return null;
  3638.                 }
  3639.             }
  3640.  
  3641.             public boolean isFocusTraversable() {
  3642.                 AccessibleContext ac = getCurrentAccessibleContext();
  3643.                 if (ac instanceof AccessibleComponent) {
  3644.                     return ((AccessibleComponent) ac).isFocusTraversable();
  3645.                 } else {
  3646.                     Component c = getCurrentComponent();
  3647.                     if (c != null) {
  3648.                         return c.isFocusTraversable();
  3649.                     } else {
  3650.                         return false;
  3651.                     }
  3652.                 }
  3653.             }
  3654.  
  3655.             public void requestFocus() {
  3656.                 AccessibleContext ac = getCurrentAccessibleContext();
  3657.                 if (ac instanceof AccessibleComponent) {
  3658.                     ((AccessibleComponent) ac).requestFocus();
  3659.                 } else {
  3660.                     Component c = getCurrentComponent();
  3661.                     if (c != null) {
  3662.                         c.requestFocus();
  3663.                     }
  3664.                 }
  3665.             }
  3666.  
  3667.             public void addFocusListener(FocusListener l) {
  3668.                 AccessibleContext ac = getCurrentAccessibleContext();
  3669.                 if (ac instanceof AccessibleComponent) {
  3670.                     ((AccessibleComponent) ac).addFocusListener(l);
  3671.                 } else {
  3672.                     Component c = getCurrentComponent();
  3673.                     if (c != null) {
  3674.                         c.addFocusListener(l);
  3675.                     }
  3676.                 }
  3677.             }
  3678.  
  3679.             public void removeFocusListener(FocusListener l) {
  3680.                 AccessibleContext ac = getCurrentAccessibleContext();
  3681.                 if (ac instanceof AccessibleComponent) {
  3682.                     ((AccessibleComponent) ac).removeFocusListener(l);
  3683.                 } else {
  3684.                     Component c = getCurrentComponent();
  3685.                     if (c != null) {
  3686.                         c.removeFocusListener(l);
  3687.                     }
  3688.                 }
  3689.             }
  3690.  
  3691.         } // inner class AccessibleJTableCell
  3692.  
  3693.     }  // inner class AccessibleJTable
  3694.  
  3695. }  // End of Class JTable
  3696.