mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			5158 lines
		
	
	
		
			145 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			5158 lines
		
	
	
		
			145 KiB
		
	
	
	
		
			Java
		
	
	
	
/* JTable.java --
 | 
						|
   Copyright (C) 2002, 2004, 2005, 2006  Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
 | 
						|
package javax.swing;
 | 
						|
 | 
						|
import java.awt.Color;
 | 
						|
import java.awt.Component;
 | 
						|
import java.awt.Cursor;
 | 
						|
import java.awt.Dimension;
 | 
						|
import java.awt.Font;
 | 
						|
import java.awt.FontMetrics;
 | 
						|
import java.awt.Point;
 | 
						|
import java.awt.Rectangle;
 | 
						|
import java.awt.event.FocusListener;
 | 
						|
import java.beans.PropertyChangeEvent;
 | 
						|
import java.beans.PropertyChangeListener;
 | 
						|
import java.text.DateFormat;
 | 
						|
import java.text.NumberFormat;
 | 
						|
import java.util.Date;
 | 
						|
import java.util.EventObject;
 | 
						|
import java.util.Hashtable;
 | 
						|
import java.util.Locale;
 | 
						|
import java.util.Vector;
 | 
						|
 | 
						|
import javax.accessibility.Accessible;
 | 
						|
import javax.accessibility.AccessibleComponent;
 | 
						|
import javax.accessibility.AccessibleContext;
 | 
						|
import javax.accessibility.AccessibleExtendedTable;
 | 
						|
import javax.accessibility.AccessibleRole;
 | 
						|
import javax.accessibility.AccessibleSelection;
 | 
						|
import javax.accessibility.AccessibleState;
 | 
						|
import javax.accessibility.AccessibleStateSet;
 | 
						|
import javax.accessibility.AccessibleTable;
 | 
						|
import javax.accessibility.AccessibleTableModelChange;
 | 
						|
import javax.swing.event.CellEditorListener;
 | 
						|
import javax.swing.event.ChangeEvent;
 | 
						|
import javax.swing.event.ListSelectionEvent;
 | 
						|
import javax.swing.event.ListSelectionListener;
 | 
						|
import javax.swing.event.TableColumnModelEvent;
 | 
						|
import javax.swing.event.TableColumnModelListener;
 | 
						|
import javax.swing.event.TableModelEvent;
 | 
						|
import javax.swing.event.TableModelListener;
 | 
						|
import javax.swing.plaf.TableUI;
 | 
						|
import javax.swing.table.DefaultTableCellRenderer;
 | 
						|
import javax.swing.table.DefaultTableColumnModel;
 | 
						|
import javax.swing.table.DefaultTableModel;
 | 
						|
import javax.swing.table.JTableHeader;
 | 
						|
import javax.swing.table.TableCellEditor;
 | 
						|
import javax.swing.table.TableCellRenderer;
 | 
						|
import javax.swing.table.TableColumn;
 | 
						|
import javax.swing.table.TableColumnModel;
 | 
						|
import javax.swing.table.TableModel;
 | 
						|
 | 
						|
/**
 | 
						|
 * The table component, displaying information, organized in rows and columns.
 | 
						|
 * The table can be placed in the scroll bar and have the optional header
 | 
						|
 * that is always visible. Cell values may be editable after double clicking
 | 
						|
 * on the cell. Cell columns may have various data types, that are
 | 
						|
 * displayed and edited by the different renderers and editors. It is possible
 | 
						|
 * to set different column width. The columns are also resizeable by
 | 
						|
 * dragging the column boundary in the header.
 | 
						|
 */
 | 
						|
public class JTable
 | 
						|
  extends JComponent
 | 
						|
  implements TableModelListener, Scrollable, TableColumnModelListener,
 | 
						|
             ListSelectionListener, CellEditorListener, Accessible
 | 
						|
{
 | 
						|
  /**
 | 
						|
   * Provides accessibility support for <code>JTable</code>.
 | 
						|
   *
 | 
						|
   * @author Roman Kennke (kennke@aicas.com)
 | 
						|
   */
 | 
						|
  protected class AccessibleJTable
 | 
						|
    extends AccessibleJComponent
 | 
						|
    implements AccessibleSelection, ListSelectionListener, TableModelListener,
 | 
						|
    TableColumnModelListener, CellEditorListener, PropertyChangeListener,
 | 
						|
    AccessibleExtendedTable
 | 
						|
  {
 | 
						|
 | 
						|
    /**
 | 
						|
     * Provides accessibility support for table cells.
 | 
						|
     *
 | 
						|
     * @author Roman Kennke (kennke@aicas.com)
 | 
						|
     */
 | 
						|
    protected class AccessibleJTableCell
 | 
						|
      extends AccessibleContext
 | 
						|
      implements Accessible, AccessibleComponent
 | 
						|
    {
 | 
						|
 | 
						|
      /**
 | 
						|
       * The table of this cell.
 | 
						|
       */
 | 
						|
      private JTable table;
 | 
						|
 | 
						|
      /**
 | 
						|
       * The row index of this cell.
 | 
						|
       */
 | 
						|
      private int row;
 | 
						|
 | 
						|
      /**
 | 
						|
       * The column index of this cell.
 | 
						|
       */
 | 
						|
      private int column;
 | 
						|
 | 
						|
      /**
 | 
						|
       * The index of this cell inside the AccessibleJTable parent.
 | 
						|
       */
 | 
						|
      private int index;
 | 
						|
 | 
						|
      /**
 | 
						|
       * Creates a new <code>AccessibleJTableCell</code>.
 | 
						|
       *
 | 
						|
       * @param t the table
 | 
						|
       * @param r the row
 | 
						|
       * @param c the column
 | 
						|
       * @param i the index of this cell inside the accessible table parent
 | 
						|
       */
 | 
						|
      public AccessibleJTableCell(JTable t, int r, int c, int i)
 | 
						|
      {
 | 
						|
        table = t;
 | 
						|
        row = r;
 | 
						|
        column = c;
 | 
						|
        index = i;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the accessible row for the table cell.
 | 
						|
       *
 | 
						|
       * @return the accessible row for the table cell
 | 
						|
       */
 | 
						|
      public AccessibleRole getAccessibleRole()
 | 
						|
      {
 | 
						|
        // TODO: What is the role of the table cell?
 | 
						|
        // Seems like the RI returns UNKNOWN here for 'normal' cells, might
 | 
						|
        // be different for special renderers though (not tested yet).
 | 
						|
        return AccessibleRole.UNKNOWN;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the accessible state set of this accessible table cell.
 | 
						|
       *
 | 
						|
       * @return the accessible state set of this accessible table cell
 | 
						|
       */
 | 
						|
      public AccessibleStateSet getAccessibleStateSet()
 | 
						|
      {
 | 
						|
        AccessibleStateSet state = new AccessibleStateSet();
 | 
						|
 | 
						|
        // Figure out the SHOWING state.
 | 
						|
        Rectangle visibleRect = getVisibleRect();
 | 
						|
        Rectangle cellRect = getCellRect(row, column, false);
 | 
						|
        if (visibleRect.intersects(cellRect))
 | 
						|
          state.add(AccessibleState.SHOWING);
 | 
						|
 | 
						|
        // Figure out SELECTED state.
 | 
						|
        if (isCellSelected(row, column))
 | 
						|
          state.add(AccessibleState.SELECTED);
 | 
						|
 | 
						|
        // Figure out ACTIVE state.
 | 
						|
        if (row == getSelectedRow() && column == getSelectedColumn())
 | 
						|
          state.add(AccessibleState.ACTIVE);
 | 
						|
 | 
						|
        // TRANSIENT seems to be always set in the RI.
 | 
						|
        state.add(AccessibleState.TRANSIENT);
 | 
						|
 | 
						|
        // TODO: Any other state to handle here?
 | 
						|
        return state;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the index of this cell in the parent object.
 | 
						|
       *
 | 
						|
       * @return the index of this cell in the parent object
 | 
						|
       */
 | 
						|
      public int getAccessibleIndexInParent()
 | 
						|
      {
 | 
						|
        return index;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the number of children of this object. Table cells cannot have
 | 
						|
       * children, so we return <code>0</code> here.
 | 
						|
       *
 | 
						|
       * @return <code>0</code>
 | 
						|
       */
 | 
						|
      public int getAccessibleChildrenCount()
 | 
						|
      {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the accessible child at index <code>i</code>. Table cells
 | 
						|
       * don't have children, so we return <code>null</code> here.
 | 
						|
       *
 | 
						|
       * @return <code>null</code>
 | 
						|
       */
 | 
						|
      public Accessible getAccessibleChild(int i)
 | 
						|
      {
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the locale setting for this accessible table cell.
 | 
						|
       *
 | 
						|
       * @return the locale setting for this accessible table cell
 | 
						|
       */
 | 
						|
      public Locale getLocale()
 | 
						|
      {
 | 
						|
        // TODO: For now, we return english here. This must be fixed as soon
 | 
						|
        // as we have a localized Swing.
 | 
						|
        return Locale.ENGLISH;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the accessible context of this table cell. Since accessible
 | 
						|
       * table cells are their own accessible context, we return
 | 
						|
       * <code>this</code>.
 | 
						|
       *
 | 
						|
       * @return the accessible context of this table cell
 | 
						|
       */
 | 
						|
      public AccessibleContext getAccessibleContext()
 | 
						|
      {
 | 
						|
        return this;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the background color of this cell.
 | 
						|
       *
 | 
						|
       * @return the background color of this cell
 | 
						|
       */
 | 
						|
      public Color getBackground()
 | 
						|
      {
 | 
						|
        return table.getBackground();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Sets the background of the cell. Since table cells cannot have
 | 
						|
       * individual background colors, this method does nothing. Set the
 | 
						|
       * background directly on the table instead.
 | 
						|
       *
 | 
						|
       * @param color not used
 | 
						|
       */
 | 
						|
      public void setBackground(Color color)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the foreground color of the table cell.
 | 
						|
       *
 | 
						|
       * @return the foreground color of the table cell
 | 
						|
       */
 | 
						|
      public Color getForeground()
 | 
						|
      {
 | 
						|
        return table.getForeground();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Sets the foreground of the cell. Since table cells cannot have
 | 
						|
       * individual foreground colors, this method does nothing. Set the
 | 
						|
       * foreground directly on the table instead.
 | 
						|
       *
 | 
						|
       * @param color not used
 | 
						|
       */
 | 
						|
      public void setForeground(Color color)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the cursor for this table cell.
 | 
						|
       *
 | 
						|
       * @return the cursor for this table cell
 | 
						|
       */
 | 
						|
      public Cursor getCursor()
 | 
						|
      {
 | 
						|
        return table.getCursor();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Sets the cursor of the cell. Since table cells cannot have
 | 
						|
       * individual cursors, this method does nothing. Set the
 | 
						|
       * cursor directly on the table instead.
 | 
						|
       *
 | 
						|
       * @param cursor not used
 | 
						|
       */
 | 
						|
      public void setCursor(Cursor cursor)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the font of the table cell.
 | 
						|
       *
 | 
						|
       * @return the font of the table cell
 | 
						|
       */
 | 
						|
      public Font getFont()
 | 
						|
      {
 | 
						|
        return table.getFont();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Sets the font of the cell. Since table cells cannot have
 | 
						|
       * individual fonts, this method does nothing. Set the
 | 
						|
       * font directly on the table instead.
 | 
						|
       *
 | 
						|
       * @param font not used
 | 
						|
       */
 | 
						|
      public void setFont(Font font)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the font metrics for a specified font.
 | 
						|
       *
 | 
						|
       * @param font the font for which we return the metrics
 | 
						|
       *
 | 
						|
       * @return the font metrics for a specified font
 | 
						|
       */
 | 
						|
      public FontMetrics getFontMetrics(Font font)
 | 
						|
      {
 | 
						|
        return table.getFontMetrics(font);
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns <code>true</code> if this table cell is enabled,
 | 
						|
       * <code>false</code> otherwise.
 | 
						|
       *
 | 
						|
       * @return <code>true</code> if this table cell is enabled,
 | 
						|
       *         <code>false</code> otherwise
 | 
						|
       */
 | 
						|
      public boolean isEnabled()
 | 
						|
      {
 | 
						|
        return table.isEnabled();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Table cells cannot be disabled or enabled individually, so this method
 | 
						|
       * does nothing. Set the enabled flag on the table itself.
 | 
						|
       *
 | 
						|
       * @param b not used here
 | 
						|
       */
 | 
						|
      public void setEnabled(boolean b)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns <code>true</code> if this cell is visible, <code>false</code>
 | 
						|
       * otherwise.
 | 
						|
       *
 | 
						|
       * @return <code>true</code> if this cell is visible, <code>false</code>
 | 
						|
       *         otherwise
 | 
						|
       */
 | 
						|
      public boolean isVisible()
 | 
						|
      {
 | 
						|
        return table.isVisible();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * The visibility cannot be set on individual table cells, so this method
 | 
						|
       * does nothing. Set the visibility on the table itself.
 | 
						|
       *
 | 
						|
       * @param b not used
 | 
						|
       */
 | 
						|
      public void setVisible(boolean b)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns <code>true</code> if this table cell is currently showing on
 | 
						|
       * screen.
 | 
						|
       *
 | 
						|
       * @return <code>true</code> if this table cell is currently showing on
 | 
						|
       *         screen
 | 
						|
       */
 | 
						|
      public boolean isShowing()
 | 
						|
      {
 | 
						|
        return table.isShowing();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns <code>true</code> if this table cell contains the location
 | 
						|
       * at <code>point</code>, <code>false</code> otherwise.
 | 
						|
       * <code>point</code> is interpreted as relative to the coordinate system
 | 
						|
       * of the table cell.
 | 
						|
       *
 | 
						|
       * @return <code>true</code> if this table cell contains the location
 | 
						|
       *         at <code>point</code>, <code>false</code> otherwise
 | 
						|
       */
 | 
						|
      public boolean contains(Point point)
 | 
						|
      {
 | 
						|
        Rectangle cellRect = table.getCellRect(row, column, true);
 | 
						|
        cellRect.x = 0;
 | 
						|
        cellRect.y = 0;
 | 
						|
        return cellRect.contains(point);
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the screen location of the table cell.
 | 
						|
       *
 | 
						|
       * @return the screen location of the table cell
 | 
						|
       */
 | 
						|
      public Point getLocationOnScreen()
 | 
						|
      {
 | 
						|
        Point tableLoc = table.getLocationOnScreen();
 | 
						|
        Rectangle cellRect = table.getCellRect(row, column, true);
 | 
						|
        tableLoc.x += cellRect.x;
 | 
						|
        tableLoc.y += cellRect.y;
 | 
						|
        return tableLoc;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the location of this cell relative to the table's bounds.
 | 
						|
       *
 | 
						|
       * @return the location of this cell relative to the table's bounds
 | 
						|
       */
 | 
						|
      public Point getLocation()
 | 
						|
      {
 | 
						|
        Rectangle cellRect = table.getCellRect(row, column, true);
 | 
						|
        return new Point(cellRect.x, cellRect.y);
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * The location of the table cells cannot be manipulated directly, so
 | 
						|
       * this method does nothing.
 | 
						|
       *
 | 
						|
       * @param point not used
 | 
						|
       */
 | 
						|
      public void setLocation(Point point)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the bounds of the cell relative to its table.
 | 
						|
       *
 | 
						|
       * @return the bounds of the cell relative to its table
 | 
						|
       */
 | 
						|
      public Rectangle getBounds()
 | 
						|
      {
 | 
						|
        return table.getCellRect(row, column, true);
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * The bounds of the table cells cannot be manipulated directly, so
 | 
						|
       * this method does nothing.
 | 
						|
       *
 | 
						|
       * @param rectangle not used
 | 
						|
       */
 | 
						|
      public void setBounds(Rectangle rectangle)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the size of the table cell.
 | 
						|
       *
 | 
						|
       * @return the size of the table cell
 | 
						|
       */
 | 
						|
      public Dimension getSize()
 | 
						|
      {
 | 
						|
        Rectangle cellRect = table.getCellRect(row, column, true);
 | 
						|
        return new Dimension(cellRect.width, cellRect.height);
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * The size cannot be set on table cells directly, so this method does
 | 
						|
       * nothing.
 | 
						|
       *
 | 
						|
       * @param dimension not used
 | 
						|
       */
 | 
						|
      public void setSize(Dimension dimension)
 | 
						|
      {
 | 
						|
        // This method does nothing. See API comments.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Table cells have no children, so we return <code>null</code> here.
 | 
						|
       *
 | 
						|
       * @return <code>null</code>
 | 
						|
       */
 | 
						|
      public Accessible getAccessibleAt(Point point)
 | 
						|
      {
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns <code>true</code> if this table cell is focus traversable,
 | 
						|
       * <code>false</code> otherwise.
 | 
						|
       *
 | 
						|
       * @return <code>true</code> if this table cell is focus traversable,
 | 
						|
       *         <code>false</code> otherwise
 | 
						|
       */
 | 
						|
      public boolean isFocusTraversable()
 | 
						|
      {
 | 
						|
        return table.isFocusable();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Requests that this table cell gets the keyboard focus.
 | 
						|
       */
 | 
						|
      public void requestFocus()
 | 
						|
      {
 | 
						|
        // We first set the selection models' lead selection to this cell.
 | 
						|
        table.getColumnModel().getSelectionModel()
 | 
						|
        .setLeadSelectionIndex(column);
 | 
						|
        table.getSelectionModel().setLeadSelectionIndex(row);
 | 
						|
        // Now we request that the table receives focus.
 | 
						|
        table.requestFocus();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Adds a focus listener to this cell. The focus listener is really
 | 
						|
       * added to the table, so there is no way to find out when an individual
 | 
						|
       * cell changes the focus.
 | 
						|
       *
 | 
						|
       * @param listener the focus listener to add
 | 
						|
       */
 | 
						|
      public void addFocusListener(FocusListener listener)
 | 
						|
      {
 | 
						|
        table.addFocusListener(listener);
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Removes a focus listener from the cell. The focus listener is really
 | 
						|
       * removed from the table.
 | 
						|
       *
 | 
						|
       * @param listener the listener to remove
 | 
						|
       */
 | 
						|
      public void removeFocusListener(FocusListener listener)
 | 
						|
      {
 | 
						|
        table.removeFocusListener(listener);
 | 
						|
      }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    protected class AccessibleJTableModelChange
 | 
						|
      implements AccessibleTableModelChange
 | 
						|
    {
 | 
						|
      protected int type;
 | 
						|
      protected int firstRow;
 | 
						|
      protected int lastRow;
 | 
						|
      protected int firstColumn;
 | 
						|
      protected int lastColumn;
 | 
						|
 | 
						|
      protected AccessibleJTableModelChange(int type, int firstRow,
 | 
						|
                                            int lastRow, int firstColumn,
 | 
						|
                                            int lastColumn)
 | 
						|
      {
 | 
						|
        this.type = type;
 | 
						|
        this.firstRow = firstRow;
 | 
						|
        this.lastRow = lastRow;
 | 
						|
        this.firstColumn = firstColumn;
 | 
						|
        this.lastColumn = lastColumn;
 | 
						|
      }
 | 
						|
 | 
						|
      public int getType()
 | 
						|
      {
 | 
						|
        return type;
 | 
						|
      }
 | 
						|
 | 
						|
      public int getFirstRow()
 | 
						|
      {
 | 
						|
        return firstRow;
 | 
						|
      }
 | 
						|
 | 
						|
      public int getLastRow()
 | 
						|
      {
 | 
						|
        return lastRow;
 | 
						|
      }
 | 
						|
 | 
						|
      public int getFirstColumn()
 | 
						|
      {
 | 
						|
        return firstColumn;
 | 
						|
      }
 | 
						|
 | 
						|
      public int getLastColumn()
 | 
						|
      {
 | 
						|
        return lastColumn;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The RI returns an instance with this name in
 | 
						|
     * {@link #getAccessibleColumnHeader()}, this makes sense, so we do the
 | 
						|
     * same.
 | 
						|
     */
 | 
						|
    private class AccessibleTableHeader
 | 
						|
      implements AccessibleTable
 | 
						|
    {
 | 
						|
 | 
						|
      /**
 | 
						|
       * The JTableHeader wrapped by this class.
 | 
						|
       */
 | 
						|
      private JTableHeader header;
 | 
						|
 | 
						|
      /**
 | 
						|
       * Creates a new instance.
 | 
						|
       *
 | 
						|
       * @param h the JTableHeader to wrap
 | 
						|
       */
 | 
						|
      private AccessibleTableHeader(JTableHeader h)
 | 
						|
      {
 | 
						|
        header = h;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the caption for the table header.
 | 
						|
       *
 | 
						|
       * @return the caption for the table header
 | 
						|
       */
 | 
						|
      public Accessible getAccessibleCaption()
 | 
						|
      {
 | 
						|
        // The RI seems to always return null here, so do we.
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Sets the caption for the table header.
 | 
						|
       *
 | 
						|
       * @param caption the caption to set
 | 
						|
       */
 | 
						|
      public void setAccessibleCaption(Accessible caption)
 | 
						|
      {
 | 
						|
        // This seems to be a no-op in the RI, so we do the same.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the caption for the table header.
 | 
						|
       *
 | 
						|
       * @return the caption for the table header
 | 
						|
       */
 | 
						|
      public Accessible getAccessibleSummary()
 | 
						|
      {
 | 
						|
        // The RI seems to always return null here, so do we.
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Sets the summary for the table header.
 | 
						|
       *
 | 
						|
       * @param summary the caption to set
 | 
						|
       */
 | 
						|
      public void setAccessibleSummary(Accessible summary)
 | 
						|
      {
 | 
						|
        // This seems to be a no-op in the RI, so we do the same.
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the number of rows, which is always 1 for the table header.
 | 
						|
       *
 | 
						|
       * @return the number of rows
 | 
						|
       */
 | 
						|
      public int getAccessibleRowCount()
 | 
						|
      {
 | 
						|
        return 1;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the number of columns in the table header.
 | 
						|
       *
 | 
						|
       * @return the number of columns in the table header
 | 
						|
       */
 | 
						|
      public int getAccessibleColumnCount()
 | 
						|
      {
 | 
						|
        return header.getColumnModel().getColumnCount();
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the accessible child at the specified row and column.
 | 
						|
       * The row number is ignored here, and we return an
 | 
						|
       * AccessibleJTableHeaderCell here with the renderer component as
 | 
						|
       * component.
 | 
						|
       *
 | 
						|
       * @param r the row number
 | 
						|
       * @param c the column number
 | 
						|
       *
 | 
						|
       * @return the accessible child at the specified row and column
 | 
						|
       */
 | 
						|
      public Accessible getAccessibleAt(int r, int c)
 | 
						|
      {
 | 
						|
        TableColumn column = header.getColumnModel().getColumn(c);
 | 
						|
        TableCellRenderer rend = column.getHeaderRenderer();
 | 
						|
        if (rend == null)
 | 
						|
          rend = header.getDefaultRenderer();
 | 
						|
        Component comp =
 | 
						|
          rend.getTableCellRendererComponent(header.getTable(),
 | 
						|
                                             column.getHeaderValue(), false,
 | 
						|
                                             false, -1, c);
 | 
						|
        return new AccessibleJTableHeaderCell(header, comp, r, c);
 | 
						|
      }
 | 
						|
 | 
						|
      public int getAccessibleRowExtentAt(int r, int c)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      public int getAccessibleColumnExtentAt(int r, int c)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      public AccessibleTable getAccessibleRowHeader()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setAccessibleRowHeader(AccessibleTable header)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public AccessibleTable getAccessibleColumnHeader()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setAccessibleColumnHeader(AccessibleTable header)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public Accessible getAccessibleRowDescription(int r)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setAccessibleRowDescription(int r, Accessible description)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public Accessible getAccessibleColumnDescription(int c)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setAccessibleColumnDescription(int c, Accessible description)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public boolean isAccessibleSelected(int r, int c)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      public boolean isAccessibleRowSelected(int r)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      public boolean isAccessibleColumnSelected(int c)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      public int[] getSelectedAccessibleRows()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public int[] getSelectedAccessibleColumns()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The RI returns an instance of such class for table header cells. This
 | 
						|
     * makes sense so I added this class. This still needs to be fully
 | 
						|
     * implemented, I just don't feel motivated enough to do so just now.
 | 
						|
     */
 | 
						|
    private class AccessibleJTableHeaderCell
 | 
						|
      extends AccessibleContext
 | 
						|
      implements Accessible, AccessibleComponent
 | 
						|
    {
 | 
						|
 | 
						|
      JTableHeader header;
 | 
						|
 | 
						|
      int columnIndex;
 | 
						|
 | 
						|
      /**
 | 
						|
       *
 | 
						|
       * @param h  the table header.
 | 
						|
       * @param comp
 | 
						|
       * @param r
 | 
						|
       * @param c  the column index.
 | 
						|
       */
 | 
						|
      private AccessibleJTableHeaderCell(JTableHeader h, Component comp, int r,
 | 
						|
                                         int c)
 | 
						|
      {
 | 
						|
        header = h;
 | 
						|
        columnIndex = c;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the header renderer.
 | 
						|
       *
 | 
						|
       * @return The header renderer.
 | 
						|
       */
 | 
						|
      Component getColumnHeaderRenderer()
 | 
						|
      {
 | 
						|
        TableColumn tc = header.getColumnModel().getColumn(columnIndex);
 | 
						|
        TableCellRenderer r = tc.getHeaderRenderer();
 | 
						|
        if (r == null)
 | 
						|
          r = header.getDefaultRenderer();
 | 
						|
        return r.getTableCellRendererComponent(header.getTable(),
 | 
						|
            tc.getHeaderValue(), false, false, -1, columnIndex);
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the accessible role for the table header cell.
 | 
						|
       *
 | 
						|
       * @return The accessible role.
 | 
						|
       */
 | 
						|
      public AccessibleRole getAccessibleRole()
 | 
						|
      {
 | 
						|
        Component renderer = getColumnHeaderRenderer();
 | 
						|
        if (renderer instanceof Accessible)
 | 
						|
          {
 | 
						|
            Accessible ac = (Accessible) renderer;
 | 
						|
            return ac.getAccessibleContext().getAccessibleRole();
 | 
						|
          }
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public AccessibleStateSet getAccessibleStateSet()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public int getAccessibleIndexInParent()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      public int getAccessibleChildrenCount()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
 | 
						|
      public Accessible getAccessibleChild(int i)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public Locale getLocale()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      /**
 | 
						|
       * Returns the accessible context.
 | 
						|
       *
 | 
						|
       * @return <code>this</code>.
 | 
						|
       */
 | 
						|
      public AccessibleContext getAccessibleContext()
 | 
						|
      {
 | 
						|
        return this;
 | 
						|
      }
 | 
						|
 | 
						|
      public Color getBackground()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setBackground(Color color)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public Color getForeground()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setForeground(Color color)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public Cursor getCursor()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setCursor(Cursor cursor)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public Font getFont()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setFont(Font font)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public FontMetrics getFontMetrics(Font font)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public boolean isEnabled()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setEnabled(boolean b)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public boolean isVisible()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setVisible(boolean b)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public boolean isShowing()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      public boolean contains(Point point)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      public Point getLocationOnScreen()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public Point getLocation()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setLocation(Point point)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public Rectangle getBounds()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setBounds(Rectangle rectangle)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public Dimension getSize()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public void setSize(Dimension dimension)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public Accessible getAccessibleAt(Point point)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
 | 
						|
      public boolean isFocusTraversable()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
 | 
						|
      public void requestFocus()
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public void addFocusListener(FocusListener listener)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      public void removeFocusListener(FocusListener listener)
 | 
						|
      {
 | 
						|
        // TODO Auto-generated method stub
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The last selected row. This is needed to track the selection in
 | 
						|
     * {@link #valueChanged(ListSelectionEvent)}.
 | 
						|
     */
 | 
						|
    private int lastSelectedRow;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The last selected column. This is needed to track the selection in
 | 
						|
     * {@link #valueChanged(ListSelectionEvent)}.
 | 
						|
     */
 | 
						|
    private int lastSelectedColumn;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The caption of the table.
 | 
						|
     */
 | 
						|
    private Accessible caption;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The summary of the table.
 | 
						|
     */
 | 
						|
    private Accessible summary;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Accessible descriptions for rows.
 | 
						|
     */
 | 
						|
    private Accessible[] rowDescriptions;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Accessible descriptions for columns.
 | 
						|
     */
 | 
						|
    private Accessible[] columnDescriptions;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a new <code>AccessibleJTable</code>.
 | 
						|
     *
 | 
						|
     * @since JDK1.5
 | 
						|
     */
 | 
						|
    protected AccessibleJTable()
 | 
						|
    {
 | 
						|
      getModel().addTableModelListener(this);
 | 
						|
      getSelectionModel().addListSelectionListener(this);
 | 
						|
      getColumnModel().addColumnModelListener(this);
 | 
						|
      lastSelectedRow = getSelectedRow();
 | 
						|
      lastSelectedColumn = getSelectedColumn();
 | 
						|
      TableCellEditor editor = getCellEditor();
 | 
						|
      if (editor != null)
 | 
						|
        editor.addCellEditorListener(this);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible role for the <code>JTable</code> component.
 | 
						|
     *
 | 
						|
     * @return {@link AccessibleRole#TABLE}.
 | 
						|
     */
 | 
						|
    public AccessibleRole getAccessibleRole()
 | 
						|
    {
 | 
						|
      return AccessibleRole.TABLE;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible table.
 | 
						|
     *
 | 
						|
     * @return <code>this</code>.
 | 
						|
     */
 | 
						|
    public AccessibleTable getAccessibleTable()
 | 
						|
    {
 | 
						|
      return this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the number of selected items in this table.
 | 
						|
     */
 | 
						|
    public int getAccessibleSelectionCount()
 | 
						|
    {
 | 
						|
      return getSelectedColumnCount();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the selected accessible object with the specified index
 | 
						|
     * <code>i</code>. This basically returns the i-th selected cell in the
 | 
						|
     * table when going though it row-wise, and inside the rows, column-wise.
 | 
						|
     *
 | 
						|
     * @param i the index of the selected object to find
 | 
						|
     *
 | 
						|
     * @return the selected accessible object with the specified index
 | 
						|
     *         <code>i</code>
 | 
						|
     */
 | 
						|
    public Accessible getAccessibleSelection(int i)
 | 
						|
    {
 | 
						|
      Accessible found = null;
 | 
						|
 | 
						|
      int[] selectedRows = getSelectedRows();
 | 
						|
      int[] selectedColumns = getSelectedColumns();
 | 
						|
      int numCols = getColumnCount();
 | 
						|
      int numRows = getRowCount();
 | 
						|
 | 
						|
      // We have to go through every selected row and column and count until we
 | 
						|
      // find the specified index. This is potentially inefficient, but I can't
 | 
						|
      // think of anything better atm.
 | 
						|
      if (getRowSelectionAllowed() && getColumnSelectionAllowed())
 | 
						|
        {
 | 
						|
          int current = -1;
 | 
						|
          int newIndex = current;
 | 
						|
          int lastSelectedRow = -1;
 | 
						|
          // Go through the selected rows array, don't forget the selected
 | 
						|
          // cells inside the not-selected rows' columns.
 | 
						|
          for (int j = 0; i < selectedRows.length; i++)
 | 
						|
            {
 | 
						|
              // Handle unselected rows between this selected and the last
 | 
						|
              // selected row, if any.
 | 
						|
              int selectedRow = selectedRows[j];
 | 
						|
              int r = -1;
 | 
						|
              int ci = -1;
 | 
						|
              for (r = lastSelectedRow + 1;
 | 
						|
                   r < selectedRow && current < i; r++)
 | 
						|
                {
 | 
						|
                  for (ci = 0; ci < selectedColumns.length && current < i;
 | 
						|
                       ci++)
 | 
						|
                    {
 | 
						|
                      current++;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
              if (current == i)
 | 
						|
                {
 | 
						|
                  // We found the cell in the above loops, now get out of here.
 | 
						|
                  found = getAccessibleChild(r * numCols
 | 
						|
                                             + selectedColumns[ci]);
 | 
						|
                  break;
 | 
						|
                }
 | 
						|
 | 
						|
              // If we're still here, handle the current selected row.
 | 
						|
              if (current < i && current + numCols >= i)
 | 
						|
                {
 | 
						|
                  // The cell must be in that row, which one is it?
 | 
						|
                  found = getAccessibleChild(r * numCols + (i - current));
 | 
						|
                  break;
 | 
						|
                }
 | 
						|
              current += numCols;
 | 
						|
            }
 | 
						|
          if (found == null)
 | 
						|
            {
 | 
						|
              // The cell can still be in the last couple of unselected rows.
 | 
						|
              int r = 0;
 | 
						|
              int ci = 0;
 | 
						|
              for (r = lastSelectedRow + 1;
 | 
						|
                   r < numRows && current < i; r++)
 | 
						|
                {
 | 
						|
                  for (ci = 0; ci < selectedColumns.length && current < i;
 | 
						|
                       ci++)
 | 
						|
                    {
 | 
						|
                      current++;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
              if (current == i)
 | 
						|
                {
 | 
						|
                  // We found the cell in the above loops, now get out of here.
 | 
						|
                  found = getAccessibleChild(r * numCols
 | 
						|
                                             + selectedColumns[ci]);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
      // One or more rows can be completely selected.
 | 
						|
      else if (getRowSelectionAllowed())
 | 
						|
        {
 | 
						|
          int c = i % numCols;
 | 
						|
          int r = selectedRows[i / numCols];
 | 
						|
          found = getAccessibleChild(r * numCols + c);
 | 
						|
        }
 | 
						|
      // One or more columns can be completely selected.
 | 
						|
      else if (getRowSelectionAllowed())
 | 
						|
        {
 | 
						|
          int numSelectedColumns = selectedColumns.length;
 | 
						|
          int c = selectedColumns[i % numSelectedColumns];
 | 
						|
          int r = i / numSelectedColumns;
 | 
						|
          found = getAccessibleChild(r * numCols + c);
 | 
						|
        }
 | 
						|
 | 
						|
      return found;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns <code>true</code> if the accessible child with the index
 | 
						|
     * <code>i</code> is selected, <code>false</code> otherwise.
 | 
						|
     *
 | 
						|
     * @param i the index of the accessible to check
 | 
						|
     *
 | 
						|
     * @return <code>true</code> if the accessible child with the index
 | 
						|
     *         <code>i</code> is selected, <code>false</code> otherwise
 | 
						|
     */
 | 
						|
    public boolean isAccessibleChildSelected(int i)
 | 
						|
    {
 | 
						|
      int r = getAccessibleRowAtIndex(i);
 | 
						|
      int c = getAccessibleColumnAtIndex(i);
 | 
						|
      return isCellSelected(r, c);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Adds the accessible child with the specified index <code>i</code> to the
 | 
						|
     * selection.
 | 
						|
     *
 | 
						|
     * @param i the index of the accessible child to add to the selection
 | 
						|
     */
 | 
						|
    public void addAccessibleSelection(int i)
 | 
						|
    {
 | 
						|
      int r = getAccessibleRowAtIndex(i);
 | 
						|
      int c = getAccessibleColumnAtIndex(i);
 | 
						|
      changeSelection(r, c, true, false);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Removes the accessible child with the specified index <code>i</code>
 | 
						|
     * from the current selection. This will only work on tables that have
 | 
						|
     * cell selection enabled (<code>rowSelectionAllowed == false &&
 | 
						|
     * columnSelectionAllowed == false</code>).
 | 
						|
     *
 | 
						|
     * @param i the index of the accessible to be removed from the selection
 | 
						|
     */
 | 
						|
    public void removeAccessibleSelection(int i)
 | 
						|
    {
 | 
						|
      if (! getRowSelectionAllowed() && ! getColumnSelectionAllowed())
 | 
						|
        {
 | 
						|
          int r = getAccessibleRowAtIndex(i);
 | 
						|
          int c = getAccessibleColumnAtIndex(i);
 | 
						|
          removeRowSelectionInterval(r, r);
 | 
						|
          removeColumnSelectionInterval(c, c);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Deselects all selected accessible children.
 | 
						|
     */
 | 
						|
    public void clearAccessibleSelection()
 | 
						|
    {
 | 
						|
      clearSelection();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Selects all accessible children that can be selected. This will only
 | 
						|
     * work on tables that support multiple selections and that have individual
 | 
						|
     * cell selection enabled.
 | 
						|
     */
 | 
						|
    public void selectAllAccessibleSelection()
 | 
						|
    {
 | 
						|
      selectAll();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Receives notification when the row selection changes and fires
 | 
						|
     * appropriate property change events.
 | 
						|
     *
 | 
						|
     * @param event the list selection event
 | 
						|
     */
 | 
						|
    public void valueChanged(ListSelectionEvent event)
 | 
						|
    {
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
 | 
						|
                         Boolean.FALSE, Boolean.TRUE);
 | 
						|
      int r = getSelectedRow();
 | 
						|
      int c = getSelectedColumn();
 | 
						|
      if (r != lastSelectedRow || c != lastSelectedColumn)
 | 
						|
        {
 | 
						|
          Accessible o = getAccessibleAt(lastSelectedRow,
 | 
						|
                                         lastSelectedColumn);
 | 
						|
          Accessible n = getAccessibleAt(r, c);
 | 
						|
          firePropertyChange(AccessibleContext
 | 
						|
                             .ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, o, n);
 | 
						|
          lastSelectedRow = r;
 | 
						|
          lastSelectedColumn = c;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Receives notification when the table model changes. Depending on the
 | 
						|
     * type of change, this method calls {@link #tableRowsInserted} or
 | 
						|
     * {@link #tableRowsDeleted}.
 | 
						|
     *
 | 
						|
     * @param event the table model event
 | 
						|
     */
 | 
						|
    public void tableChanged(TableModelEvent event)
 | 
						|
    {
 | 
						|
      switch (event.getType())
 | 
						|
        {
 | 
						|
        case TableModelEvent.INSERT:
 | 
						|
          tableRowsInserted(event);
 | 
						|
          break;
 | 
						|
        case TableModelEvent.DELETE:
 | 
						|
          tableRowsDeleted(event);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Receives notification when one or more rows have been inserted into the
 | 
						|
     * table and fires appropriate property change events.
 | 
						|
     *
 | 
						|
     * @param event the table model event
 | 
						|
     */
 | 
						|
    public void tableRowsInserted(TableModelEvent event)
 | 
						|
    {
 | 
						|
      handleRowChange(event);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Receives notification when one or more rows have been deleted from the
 | 
						|
     * table.
 | 
						|
     *
 | 
						|
     * @param event the table model event
 | 
						|
     */
 | 
						|
    public void tableRowsDeleted(TableModelEvent event)
 | 
						|
    {
 | 
						|
      handleRowChange(event);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Fires a PropertyChangeEvent for inserted or deleted rows.
 | 
						|
     *
 | 
						|
     * @param event the table model event
 | 
						|
     */
 | 
						|
    private void handleRowChange(TableModelEvent event)
 | 
						|
    {
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
 | 
						|
                         null, null);
 | 
						|
      int firstColumn = event.getColumn();
 | 
						|
      int lastColumn = event.getColumn();
 | 
						|
      if (firstColumn == TableModelEvent.ALL_COLUMNS)
 | 
						|
        {
 | 
						|
          firstColumn = 0;
 | 
						|
          lastColumn = getColumnCount() - 1;
 | 
						|
        }
 | 
						|
      AccessibleJTableModelChange change = new AccessibleJTableModelChange
 | 
						|
         (event.getType(), event.getFirstRow(), event.getLastRow(),
 | 
						|
          firstColumn, lastColumn);
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
 | 
						|
                         null, change);
 | 
						|
    }
 | 
						|
 | 
						|
    public void columnAdded(TableColumnModelEvent event)
 | 
						|
    {
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
 | 
						|
                         null, null);
 | 
						|
      handleColumnChange(AccessibleTableModelChange.INSERT,
 | 
						|
                         event.getFromIndex(), event.getToIndex());
 | 
						|
    }
 | 
						|
 | 
						|
    public void columnRemoved(TableColumnModelEvent event)
 | 
						|
    {
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
 | 
						|
                         null, null);
 | 
						|
      handleColumnChange(AccessibleTableModelChange.DELETE,
 | 
						|
                         event.getFromIndex(), event.getToIndex());
 | 
						|
    }
 | 
						|
 | 
						|
    public void columnMoved(TableColumnModelEvent event)
 | 
						|
    {
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
 | 
						|
                         null, null);
 | 
						|
      handleColumnChange(AccessibleTableModelChange.DELETE,
 | 
						|
                         event.getFromIndex(), event.getFromIndex());
 | 
						|
      handleColumnChange(AccessibleTableModelChange.INSERT,
 | 
						|
                         event.getFromIndex(), event.getToIndex());
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Fires a PropertyChangeEvent for inserted or deleted columns.
 | 
						|
     *
 | 
						|
     * @param type the type of change
 | 
						|
     * @param from the start of the change
 | 
						|
     * @param to the target of the change
 | 
						|
     */
 | 
						|
    private void handleColumnChange(int type, int from, int to)
 | 
						|
    {
 | 
						|
      AccessibleJTableModelChange change =
 | 
						|
        new AccessibleJTableModelChange(type, 0, 0, from, to);
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED,
 | 
						|
                         null, change);
 | 
						|
    }
 | 
						|
 | 
						|
    public void columnMarginChanged(ChangeEvent event)
 | 
						|
    {
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
 | 
						|
                         null, null);
 | 
						|
    }
 | 
						|
 | 
						|
    public void columnSelectionChanged(ListSelectionEvent event)
 | 
						|
    {
 | 
						|
      // AFAICS, nothing is done here.
 | 
						|
    }
 | 
						|
 | 
						|
    public void editingCanceled(ChangeEvent event)
 | 
						|
    {
 | 
						|
      // AFAICS, nothing is done here.
 | 
						|
    }
 | 
						|
 | 
						|
    public void editingStopped(ChangeEvent event)
 | 
						|
    {
 | 
						|
      firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
 | 
						|
                         null, null);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Receives notification when any of the JTable's properties changes. This
 | 
						|
     * is used to replace the listeners on the table's model, selection model,
 | 
						|
     * column model and cell editor.
 | 
						|
     *
 | 
						|
     * @param e the property change event
 | 
						|
     */
 | 
						|
    public void propertyChange(PropertyChangeEvent e)
 | 
						|
    {
 | 
						|
      String propName = e.getPropertyName();
 | 
						|
      if (propName.equals("tableModel"))
 | 
						|
        {
 | 
						|
          TableModel oldModel = (TableModel) e.getOldValue();
 | 
						|
          oldModel.removeTableModelListener(this);
 | 
						|
          TableModel newModel = (TableModel) e.getNewValue();
 | 
						|
          newModel.addTableModelListener(this);
 | 
						|
        }
 | 
						|
      else if (propName.equals("columnModel"))
 | 
						|
        {
 | 
						|
          TableColumnModel oldModel = (TableColumnModel) e.getOldValue();
 | 
						|
          oldModel.removeColumnModelListener(this);
 | 
						|
          TableColumnModel newModel = (TableColumnModel) e.getNewValue();
 | 
						|
          newModel.addColumnModelListener(this);
 | 
						|
        }
 | 
						|
      else if (propName.equals("selectionModel"))
 | 
						|
        {
 | 
						|
          ListSelectionModel oldModel = (ListSelectionModel) e.getOldValue();
 | 
						|
          oldModel.removeListSelectionListener(this);
 | 
						|
          ListSelectionModel newModel = (ListSelectionModel) e.getNewValue();
 | 
						|
          newModel.addListSelectionListener(this);
 | 
						|
        }
 | 
						|
      else if (propName.equals("cellEditor"))
 | 
						|
        {
 | 
						|
          CellEditor oldEd = (CellEditor) e.getOldValue();
 | 
						|
          oldEd.removeCellEditorListener(this);
 | 
						|
          CellEditor newEd = (CellEditor) e.getNewValue();
 | 
						|
          newEd.addCellEditorListener(this);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the row number of an accessible child (cell) with the specified
 | 
						|
     * index.
 | 
						|
     *
 | 
						|
     * @param index the index of the cell of which the row number is queried
 | 
						|
     *
 | 
						|
     * @return the row number of an accessible child (cell) with the specified
 | 
						|
     *         index
 | 
						|
     */
 | 
						|
    public int getAccessibleRow(int index)
 | 
						|
    {
 | 
						|
      return getAccessibleRowAtIndex(index);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the column number of an accessible child (cell) with the
 | 
						|
     * specified index.
 | 
						|
     *
 | 
						|
     * @param index the index of the cell of which the column number is queried
 | 
						|
     *
 | 
						|
     * @return the column number of an accessible child (cell) with the
 | 
						|
     *         specified index
 | 
						|
     */
 | 
						|
    public int getAccessibleColumn(int index)
 | 
						|
    {
 | 
						|
      return getAccessibleColumnAtIndex(index);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the index of the accessible child at the specified row and
 | 
						|
     * column.
 | 
						|
     *
 | 
						|
     * @param r the row number
 | 
						|
     * @param c the column number
 | 
						|
     *
 | 
						|
     * @return the index of the accessible child at the specified row and
 | 
						|
     *         column
 | 
						|
     */
 | 
						|
    public int getAccessibleIndex(int r, int c)
 | 
						|
    {
 | 
						|
      return getAccessibleIndexAt(r, c);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the caption of the table.
 | 
						|
     *
 | 
						|
     * @return the caption of the table
 | 
						|
     *
 | 
						|
     * @see #setAccessibleCaption(Accessible)
 | 
						|
     */
 | 
						|
    public Accessible getAccessibleCaption()
 | 
						|
    {
 | 
						|
      return caption;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the caption for the table.
 | 
						|
     *
 | 
						|
     * @param c the caption to set
 | 
						|
     */
 | 
						|
    public void setAccessibleCaption(Accessible c)
 | 
						|
    {
 | 
						|
      caption = c;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the summary for the table.
 | 
						|
     *
 | 
						|
     * @return the summary for the table
 | 
						|
     */
 | 
						|
    public Accessible getAccessibleSummary()
 | 
						|
    {
 | 
						|
      return summary;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the summary for the table.
 | 
						|
     *
 | 
						|
     * @param s the summary to set
 | 
						|
     */
 | 
						|
    public void setAccessibleSummary(Accessible s)
 | 
						|
    {
 | 
						|
      summary = s;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the number of rows in the table.
 | 
						|
     *
 | 
						|
     * @return the number of rows in the table
 | 
						|
     */
 | 
						|
    public int getAccessibleRowCount()
 | 
						|
    {
 | 
						|
      return getRowCount();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the number of columns in the table.
 | 
						|
     *
 | 
						|
     * @return the number of columns in the table
 | 
						|
     */
 | 
						|
    public int getAccessibleColumnCount()
 | 
						|
    {
 | 
						|
      return getColumnCount();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible child at the given index.
 | 
						|
     *
 | 
						|
     * @param index  the child index.
 | 
						|
     *
 | 
						|
     * @return The accessible child.
 | 
						|
     */
 | 
						|
    public Accessible getAccessibleChild(int index)
 | 
						|
    {
 | 
						|
      int r = getAccessibleRow(index);
 | 
						|
      int c = getAccessibleColumn(index);
 | 
						|
      return getAccessibleAt(r, c);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible child (table cell) at the specified row and
 | 
						|
     * column.
 | 
						|
     *
 | 
						|
     * @param r the row number
 | 
						|
     * @param c the column number
 | 
						|
     *
 | 
						|
     * @return the accessible child (table cell) at the specified row and
 | 
						|
     *         column
 | 
						|
     */
 | 
						|
    public Accessible getAccessibleAt(int r, int c)
 | 
						|
    {
 | 
						|
      TableCellRenderer cellRenderer = getCellRenderer(r, c);
 | 
						|
      Component renderer = cellRenderer.getTableCellRendererComponent(
 | 
						|
          JTable.this, getValueAt(r, c), isCellSelected(r, c), false, r, c);
 | 
						|
      if (renderer instanceof Accessible)
 | 
						|
        return (Accessible) renderer;
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the number of rows that the specified cell occupies. The
 | 
						|
     * standard table cells only occupy one row, so we return <code>1</code>
 | 
						|
     * here.
 | 
						|
     *
 | 
						|
     * @param r the row number
 | 
						|
     * @param c the column number
 | 
						|
     *
 | 
						|
     * @return the number of rows that the specified cell occupies
 | 
						|
     */
 | 
						|
    public int getAccessibleRowExtentAt(int r, int c)
 | 
						|
    {
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the number of columns that the specified cell occupies. The
 | 
						|
     * standard table cells only occupy one column, so we return <code>1</code>
 | 
						|
     * here.
 | 
						|
     *
 | 
						|
     * @param r the row number
 | 
						|
     * @param c the column number
 | 
						|
     *
 | 
						|
     * @return the number of rows that the specified cell occupies
 | 
						|
     */
 | 
						|
    public int getAccessibleColumnExtentAt(int r, int c)
 | 
						|
    {
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible row header.
 | 
						|
     *
 | 
						|
     * @return the accessible row header
 | 
						|
     */
 | 
						|
    public AccessibleTable getAccessibleRowHeader()
 | 
						|
    {
 | 
						|
      // The RI seems to always return null here, so do we.
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the accessible row header.
 | 
						|
     *
 | 
						|
     * @param header the header to set
 | 
						|
     */
 | 
						|
    public void setAccessibleRowHeader(AccessibleTable header)
 | 
						|
    {
 | 
						|
      // In the RI this seems to be a no-op.
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the column header.
 | 
						|
     *
 | 
						|
     * @return the column header, or <code>null</code> if there is no column
 | 
						|
     *         header
 | 
						|
     */
 | 
						|
    public AccessibleTable getAccessibleColumnHeader()
 | 
						|
    {
 | 
						|
      JTableHeader h = getTableHeader();
 | 
						|
      AccessibleTable header = null;
 | 
						|
      if (h != null)
 | 
						|
        header = new AccessibleTableHeader(h);
 | 
						|
      return header;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the accessible column header. The default implementation doesn't
 | 
						|
     * allow changing the header this way, so this is a no-op.
 | 
						|
     *
 | 
						|
     * @param header the accessible column header to set
 | 
						|
     */
 | 
						|
    public void setAccessibleColumnHeader(AccessibleTable header)
 | 
						|
    {
 | 
						|
      // The RI doesn't seem to do anything, so we also do nothing.
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible description for the row with the specified index,
 | 
						|
     * or <code>null</code> if no description has been set.
 | 
						|
     *
 | 
						|
     * @param r the row for which the description is queried
 | 
						|
     *
 | 
						|
     * @return the accessible description for the row with the specified index,
 | 
						|
     *         or <code>null</code> if no description has been set
 | 
						|
     */
 | 
						|
    public Accessible getAccessibleRowDescription(int r)
 | 
						|
    {
 | 
						|
      Accessible descr = null;
 | 
						|
      if (rowDescriptions != null)
 | 
						|
        descr = rowDescriptions[r];
 | 
						|
      return descr;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the accessible description for the row with the specified index.
 | 
						|
     *
 | 
						|
     * @param r the row number for which to set the description
 | 
						|
     * @param description the description to set
 | 
						|
     */
 | 
						|
    public void setAccessibleRowDescription(int r, Accessible description)
 | 
						|
    {
 | 
						|
      if (rowDescriptions == null)
 | 
						|
        rowDescriptions = new Accessible[getAccessibleRowCount()];
 | 
						|
      rowDescriptions[r] = description;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible description for the column with the specified
 | 
						|
     * index, or <code>null</code> if no description has been set.
 | 
						|
     *
 | 
						|
     * @param c the column for which the description is queried
 | 
						|
     *
 | 
						|
     * @return the accessible description for the column with the specified
 | 
						|
     *         index, or <code>null</code> if no description has been set
 | 
						|
     */
 | 
						|
    public Accessible getAccessibleColumnDescription(int c)
 | 
						|
    {
 | 
						|
      Accessible descr = null;
 | 
						|
      if (columnDescriptions != null)
 | 
						|
        descr = columnDescriptions[c];
 | 
						|
      return descr;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the accessible description for the column with the specified index.
 | 
						|
     *
 | 
						|
     * @param c the column number for which to set the description
 | 
						|
     * @param description the description to set
 | 
						|
     */
 | 
						|
    public void setAccessibleColumnDescription(int c, Accessible description)
 | 
						|
    {
 | 
						|
      if (columnDescriptions == null)
 | 
						|
        columnDescriptions = new Accessible[getAccessibleRowCount()];
 | 
						|
      columnDescriptions[c] = description;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns <code>true</code> if the accessible child at the specified
 | 
						|
     * row and column is selected, <code>false</code> otherwise.
 | 
						|
     *
 | 
						|
     * @param r the row number of the child
 | 
						|
     * @param c the column number of the child
 | 
						|
     *
 | 
						|
     * @return <code>true</code> if the accessible child at the specified
 | 
						|
     *         row and column is selected, <code>false</code> otherwise
 | 
						|
     */
 | 
						|
    public boolean isAccessibleSelected(int r, int c)
 | 
						|
    {
 | 
						|
      return isCellSelected(r, c);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns <code>true</code> if the row with the specified index is
 | 
						|
     * selected, <code>false</code> otherwise.
 | 
						|
     *
 | 
						|
     * @param r the row number
 | 
						|
     *
 | 
						|
     * @return <code>true</code> if the row with the specified index is
 | 
						|
     *        selected, <code>false</code> otherwise
 | 
						|
     */
 | 
						|
    public boolean isAccessibleRowSelected(int r)
 | 
						|
    {
 | 
						|
      return isRowSelected(r);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns <code>true</code> if the column with the specified index is
 | 
						|
     * selected, <code>false</code> otherwise.
 | 
						|
     *
 | 
						|
     * @param c the column number
 | 
						|
     *
 | 
						|
     * @return <code>true</code> if the column with the specified index is
 | 
						|
     *        selected, <code>false</code> otherwise
 | 
						|
     */
 | 
						|
    public boolean isAccessibleColumnSelected(int c)
 | 
						|
    {
 | 
						|
      return isColumnSelected(c);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the indices of all selected rows.
 | 
						|
     *
 | 
						|
     * @return the indices of all selected rows
 | 
						|
     */
 | 
						|
    public int[] getSelectedAccessibleRows()
 | 
						|
    {
 | 
						|
      return getSelectedRows();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the indices of all selected columns.
 | 
						|
     *
 | 
						|
     * @return the indices of all selected columns
 | 
						|
     */
 | 
						|
    public int[] getSelectedAccessibleColumns()
 | 
						|
    {
 | 
						|
      return getSelectedColumns();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible row at the specified index.
 | 
						|
     *
 | 
						|
     * @param index the index for which to query the row
 | 
						|
     *
 | 
						|
     * @return the row number at the specified table index
 | 
						|
     */
 | 
						|
    public int getAccessibleRowAtIndex(int index)
 | 
						|
    {
 | 
						|
      // TODO: Back this up by a Mauve test and update API docs accordingly.
 | 
						|
      return index / getColumnCount();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible column at the specified index.
 | 
						|
     *
 | 
						|
     * @param index the index for which to query the column
 | 
						|
     *
 | 
						|
     * @return the column number at the specified table index
 | 
						|
     */
 | 
						|
    public int getAccessibleColumnAtIndex(int index)
 | 
						|
    {
 | 
						|
      // TODO: Back this up by a Mauve test and update API docs accordingly.
 | 
						|
      return index % getColumnCount();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the accessible child index at the specified column and row.
 | 
						|
     *
 | 
						|
     * @param row the row
 | 
						|
     * @param column the column
 | 
						|
     *
 | 
						|
     * @return the index of the accessible child at the specified row and
 | 
						|
     *         column
 | 
						|
     */
 | 
						|
    public int getAccessibleIndexAt(int row, int column)
 | 
						|
    {
 | 
						|
      // TODO: Back this up by a Mauve test and update API docs accordingly.
 | 
						|
      return row * getColumnCount() + column;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  /**
 | 
						|
   * Handles property changes from the <code>TableColumn</code>s of this
 | 
						|
   * <code>JTable</code>.
 | 
						|
   *
 | 
						|
   * More specifically, this triggers a {@link #revalidate()} call if the
 | 
						|
   * preferredWidth of one of the observed columns changes.
 | 
						|
   */
 | 
						|
  class TableColumnPropertyChangeHandler implements PropertyChangeListener
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * Receives notification that a property of the observed TableColumns has
 | 
						|
     * changed.
 | 
						|
     *
 | 
						|
     * @param ev the property change event
 | 
						|
     */
 | 
						|
    public void propertyChange(PropertyChangeEvent ev)
 | 
						|
    {
 | 
						|
      if (ev.getPropertyName().equals("preferredWidth"))
 | 
						|
        {
 | 
						|
          JTableHeader header = getTableHeader();
 | 
						|
          if (header != null)
 | 
						|
            // Do nothing if the table is in the resizing mode.
 | 
						|
            if (header.getResizingColumn() == null)
 | 
						|
              {
 | 
						|
                TableColumn col = (TableColumn) ev.getSource();
 | 
						|
                header.setResizingColumn(col);
 | 
						|
                doLayout();
 | 
						|
                header.setResizingColumn(null);
 | 
						|
              }
 | 
						|
        }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * A cell renderer for boolean values.
 | 
						|
   */
 | 
						|
  private class BooleanCellRenderer
 | 
						|
    extends DefaultTableCellRenderer
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * The CheckBox that is used for rendering.
 | 
						|
     */
 | 
						|
    private final JCheckBox checkBox;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a new checkbox based boolean cell renderer. The checkbox is
 | 
						|
     * centered by default.
 | 
						|
     */
 | 
						|
    BooleanCellRenderer()
 | 
						|
    {
 | 
						|
       checkBox = new JCheckBox();
 | 
						|
       checkBox.setHorizontalAlignment(SwingConstants.CENTER);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the check box.
 | 
						|
     */
 | 
						|
    JCheckBox getCheckBox()
 | 
						|
    {
 | 
						|
      return checkBox;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the component that is used for rendering the value.
 | 
						|
     *
 | 
						|
     * @param table the JTable
 | 
						|
     * @param value the value of the object
 | 
						|
     * @param isSelected is the cell selected?
 | 
						|
     * @param hasFocus has the cell the focus?
 | 
						|
     * @param row the row to render
 | 
						|
     * @param column the cell to render
 | 
						|
     * @return this component (the default table cell renderer)
 | 
						|
     */
 | 
						|
    public Component getTableCellRendererComponent(JTable table, Object value,
 | 
						|
                                                   boolean isSelected,
 | 
						|
                                                   boolean hasFocus, int row,
 | 
						|
                                                   int column)
 | 
						|
    {
 | 
						|
      if (isSelected)
 | 
						|
        {
 | 
						|
          checkBox.setBackground(table.getSelectionBackground());
 | 
						|
          checkBox.setForeground(table.getSelectionForeground());
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          checkBox.setBackground(table.getBackground());
 | 
						|
          checkBox.setForeground(table.getForeground());
 | 
						|
        }
 | 
						|
 | 
						|
      if (hasFocus)
 | 
						|
        {
 | 
						|
          checkBox.setBorder(
 | 
						|
            UIManager.getBorder("Table.focusCellHighlightBorder"));
 | 
						|
          if (table.isCellEditable(row, column))
 | 
						|
            {
 | 
						|
              checkBox.setBackground(
 | 
						|
                UIManager.getColor("Table.focusCellBackground"));
 | 
						|
              checkBox.setForeground(
 | 
						|
                UIManager.getColor("Table.focusCellForeground"));
 | 
						|
            }
 | 
						|
        }
 | 
						|
      else
 | 
						|
        checkBox.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
 | 
						|
 | 
						|
      // Null is rendered as false.
 | 
						|
      if (value == null)
 | 
						|
        checkBox.setSelected(false);
 | 
						|
      else
 | 
						|
        {
 | 
						|
          Boolean boolValue = (Boolean) value;
 | 
						|
          checkBox.setSelected(boolValue.booleanValue());
 | 
						|
        }
 | 
						|
      return checkBox;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * A cell renderer for Date values.
 | 
						|
   */
 | 
						|
  private class DateCellRenderer
 | 
						|
    extends DefaultTableCellRenderer
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * Returns the component that is used for rendering the value.
 | 
						|
     *
 | 
						|
     * @param table the JTable
 | 
						|
     * @param value the value of the object
 | 
						|
     * @param isSelected is the cell selected?
 | 
						|
     * @param hasFocus has the cell the focus?
 | 
						|
     * @param row the row to render
 | 
						|
     * @param column the cell to render
 | 
						|
     *
 | 
						|
     * @return this component (the default table cell renderer)
 | 
						|
     */
 | 
						|
    public Component getTableCellRendererComponent(JTable table, Object value,
 | 
						|
                                                   boolean isSelected,
 | 
						|
                                                   boolean hasFocus, int row,
 | 
						|
                                                   int column)
 | 
						|
    {
 | 
						|
      super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
 | 
						|
                                          row, column);
 | 
						|
      if (value instanceof Date)
 | 
						|
        {
 | 
						|
          Date dateValue = (Date) value;
 | 
						|
          DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
 | 
						|
          setText(df.format(dateValue));
 | 
						|
        }
 | 
						|
      return this;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * A cell renderer for Double values.
 | 
						|
   */
 | 
						|
  private class DoubleCellRenderer
 | 
						|
    extends DefaultTableCellRenderer
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * Creates a new instance of NumberCellRenderer.
 | 
						|
     */
 | 
						|
    public DoubleCellRenderer()
 | 
						|
    {
 | 
						|
      setHorizontalAlignment(JLabel.RIGHT);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the component that is used for rendering the value.
 | 
						|
     *
 | 
						|
     * @param table the JTable
 | 
						|
     * @param value the value of the object
 | 
						|
     * @param isSelected is the cell selected?
 | 
						|
     * @param hasFocus has the cell the focus?
 | 
						|
     * @param row the row to render
 | 
						|
     * @param column the cell to render
 | 
						|
     *
 | 
						|
     * @return this component (the default table cell renderer)
 | 
						|
     */
 | 
						|
    public Component getTableCellRendererComponent(JTable table, Object value,
 | 
						|
                                                   boolean isSelected,
 | 
						|
                                                   boolean hasFocus, int row,
 | 
						|
                                                   int column)
 | 
						|
    {
 | 
						|
      super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
 | 
						|
                                          row, column);
 | 
						|
      if (value instanceof Double)
 | 
						|
        {
 | 
						|
          Double doubleValue = (Double) value;
 | 
						|
          NumberFormat nf = NumberFormat.getInstance();
 | 
						|
          setText(nf.format(doubleValue.doubleValue()));
 | 
						|
        }
 | 
						|
      return this;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * A cell renderer for Float values.
 | 
						|
   */
 | 
						|
  private class FloatCellRenderer
 | 
						|
    extends DefaultTableCellRenderer
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * Creates a new instance of NumberCellRenderer.
 | 
						|
     */
 | 
						|
    public FloatCellRenderer()
 | 
						|
    {
 | 
						|
      setHorizontalAlignment(JLabel.RIGHT);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the component that is used for rendering the value.
 | 
						|
     *
 | 
						|
     * @param table the JTable
 | 
						|
     * @param value the value of the object
 | 
						|
     * @param isSelected is the cell selected?
 | 
						|
     * @param hasFocus has the cell the focus?
 | 
						|
     * @param row the row to render
 | 
						|
     * @param column the cell to render
 | 
						|
     *
 | 
						|
     * @return this component (the default table cell renderer)
 | 
						|
     */
 | 
						|
    public Component getTableCellRendererComponent(JTable table, Object value,
 | 
						|
                                                   boolean isSelected,
 | 
						|
                                                   boolean hasFocus, int row,
 | 
						|
                                                   int column)
 | 
						|
    {
 | 
						|
      super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
 | 
						|
                                          row, column);
 | 
						|
      if (value instanceof Float)
 | 
						|
        {
 | 
						|
          Float floatValue = (Float) value;
 | 
						|
          NumberFormat nf = NumberFormat.getInstance();
 | 
						|
          setText(nf.format(floatValue.floatValue()));
 | 
						|
        }
 | 
						|
      return this;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * A cell renderer for Number values.
 | 
						|
   */
 | 
						|
  private class NumberCellRenderer
 | 
						|
    extends DefaultTableCellRenderer
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * Creates a new instance of NumberCellRenderer.
 | 
						|
     */
 | 
						|
    public NumberCellRenderer()
 | 
						|
    {
 | 
						|
      setHorizontalAlignment(JLabel.RIGHT);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * A cell renderer for Icon values.
 | 
						|
   */
 | 
						|
  private class IconCellRenderer
 | 
						|
    extends DefaultTableCellRenderer
 | 
						|
  {
 | 
						|
    IconCellRenderer()
 | 
						|
    {
 | 
						|
      setHorizontalAlignment(SwingConstants.CENTER);
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the component that is used for rendering the value.
 | 
						|
     *
 | 
						|
     * @param table the JTable
 | 
						|
     * @param value the value of the object
 | 
						|
     * @param isSelected is the cell selected?
 | 
						|
     * @param hasFocus has the cell the focus?
 | 
						|
     * @param row the row to render
 | 
						|
     * @param column the cell to render
 | 
						|
     *
 | 
						|
     * @return this component (the default table cell renderer)
 | 
						|
     */
 | 
						|
    public Component getTableCellRendererComponent(JTable table, Object value,
 | 
						|
                                                   boolean isSelected,
 | 
						|
                                                   boolean hasFocus, int row,
 | 
						|
                                                   int column)
 | 
						|
    {
 | 
						|
      super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
 | 
						|
                                          row, column);
 | 
						|
      if (value instanceof Icon)
 | 
						|
        {
 | 
						|
          Icon iconValue = (Icon) value;
 | 
						|
          setIcon(iconValue);
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          setIcon(null);
 | 
						|
        }
 | 
						|
      setText("");
 | 
						|
      return this;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
    /**
 | 
						|
     * The JTable text component (used in editing) always has the table
 | 
						|
     * as its parent. The scrollRectToVisible must be adjusted taking the
 | 
						|
     * relative component position.
 | 
						|
     *
 | 
						|
     * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
 | 
						|
     */
 | 
						|
    private class TableTextField extends JTextField
 | 
						|
    {
 | 
						|
      /**
 | 
						|
       * Create the text field without the border.
 | 
						|
       */
 | 
						|
      TableTextField()
 | 
						|
      {
 | 
						|
        setBorder(BorderFactory.createLineBorder(getGridColor(), 2));
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
  private static final long serialVersionUID = 3876025080382781659L;
 | 
						|
 | 
						|
  /**
 | 
						|
   * This table, for referring identically name methods from inner classes.
 | 
						|
   */
 | 
						|
  final JTable this_table = this;
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * When resizing columns, do not automatically change any columns. In this
 | 
						|
   * case the table should be enclosed in a {@link JScrollPane} in order to
 | 
						|
   * accomodate cases in which the table size exceeds its visible area.
 | 
						|
   */
 | 
						|
  public static final int AUTO_RESIZE_OFF = 0;
 | 
						|
 | 
						|
  /**
 | 
						|
   * When resizing column <code>i</code>, automatically change only the
 | 
						|
   * single column <code>i+1</code> to provide or absorb excess space
 | 
						|
   * requirements.
 | 
						|
   */
 | 
						|
  public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
 | 
						|
 | 
						|
  /**
 | 
						|
   * When resizing column <code>i</code> in a table of <code>n</code>
 | 
						|
   * columns, automatically change all columns in the range <code>[i+1,
 | 
						|
   * n)</code>, uniformly, to provide or absorb excess space requirements.
 | 
						|
   */
 | 
						|
  public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
 | 
						|
 | 
						|
  /**
 | 
						|
   * When resizing column <code>i</code> in a table of <code>n</code>
 | 
						|
   * columns, automatically change all columns in the range <code>[0,
 | 
						|
   * n)</code> (with the exception of column i) uniformly, to provide or
 | 
						|
   * absorb excess space requirements.
 | 
						|
   */
 | 
						|
  public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
 | 
						|
 | 
						|
  /**
 | 
						|
   * When resizing column <code>i</code> in a table of <code>n</code>
 | 
						|
   * columns, automatically change column <code>n-1</code> (the last column
 | 
						|
   * in the table) to provide or absorb excess space requirements.
 | 
						|
   */
 | 
						|
  public static final int AUTO_RESIZE_LAST_COLUMN = 3;
 | 
						|
 | 
						|
  /**
 | 
						|
   * A table mapping {@link java.lang.Class} objects to
 | 
						|
   * {@link TableCellEditor} objects. This table is consulted by the
 | 
						|
   * FIXME
 | 
						|
   */
 | 
						|
  protected Hashtable defaultEditorsByColumnClass = new Hashtable();
 | 
						|
 | 
						|
  /**
 | 
						|
   * A table mapping {@link java.lang.Class} objects to
 | 
						|
   * {@link TableCellEditor} objects. This table is consulted by the
 | 
						|
   * FIXME
 | 
						|
   */
 | 
						|
  protected Hashtable defaultRenderersByColumnClass = new Hashtable();
 | 
						|
 | 
						|
  /**
 | 
						|
   * The column that is edited, -1 if the table is not edited currently.
 | 
						|
   */
 | 
						|
  protected int editingColumn;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The row that is edited, -1 if the table is not edited currently.
 | 
						|
   */
 | 
						|
  protected int editingRow;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The component that is used for editing.
 | 
						|
   * <code>null</code> if the table is not editing currently.
 | 
						|
   *
 | 
						|
   */
 | 
						|
  protected transient Component editorComp;
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * Whether or not the table should automatically compute a matching
 | 
						|
   * {@link TableColumnModel} and assign it to the {@link #columnModel}
 | 
						|
   * property when the {@link #dataModel} property is changed.
 | 
						|
   *
 | 
						|
   * @see #setModel(TableModel)
 | 
						|
   * @see #createDefaultColumnsFromModel()
 | 
						|
   * @see #setColumnModel(TableColumnModel)
 | 
						|
   * @see #setAutoCreateColumnsFromModel(boolean)
 | 
						|
   * @see #getAutoCreateColumnsFromModel()
 | 
						|
   */
 | 
						|
  protected boolean autoCreateColumnsFromModel;
 | 
						|
 | 
						|
  /**
 | 
						|
   * A numeric code specifying the resizing behavior of the table. Must be
 | 
						|
   * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link
 | 
						|
   * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link
 | 
						|
   * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}.
 | 
						|
   *
 | 
						|
   * @see #doLayout()
 | 
						|
   * @see #setAutoResizeMode(int)
 | 
						|
   * @see #getAutoResizeMode()
 | 
						|
   */
 | 
						|
  protected int autoResizeMode;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The height in pixels of any row of the table. All rows in a table are
 | 
						|
   * of uniform height. This differs from column width, which varies on a
 | 
						|
   * per-column basis, and is stored in the individual columns of the
 | 
						|
   * {@link #columnModel}.
 | 
						|
   *
 | 
						|
   * @see #getRowHeight()
 | 
						|
   * @see #setRowHeight(int)
 | 
						|
   * @see TableColumn#getWidth()
 | 
						|
   * @see TableColumn#setWidth(int)
 | 
						|
   */
 | 
						|
  protected int rowHeight;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The height in pixels of the gap left between any two rows of the table.
 | 
						|
   *
 | 
						|
   * @see #setRowMargin(int)
 | 
						|
   * @see #getRowHeight()
 | 
						|
   * @see #getIntercellSpacing()
 | 
						|
   * @see #setIntercellSpacing(Dimension)
 | 
						|
   * @see TableColumnModel#getColumnMargin()
 | 
						|
   * @see TableColumnModel#setColumnMargin(int)
 | 
						|
   */
 | 
						|
  protected int rowMargin;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Whether or not the table should allow row selection. If the table
 | 
						|
   * allows both row <em>and</em> column selection, it is said to allow
 | 
						|
   * "cell selection". Previous versions of the JDK supported cell
 | 
						|
   * selection as an independent concept, but it is now represented solely
 | 
						|
   * in terms of simultaneous row and column selection.
 | 
						|
   *
 | 
						|
   * @see TableColumnModel#getColumnSelectionAllowed()
 | 
						|
   * @see #setRowSelectionAllowed(boolean)
 | 
						|
   * @see #getRowSelectionAllowed()
 | 
						|
   * @see #getCellSelectionEnabled()
 | 
						|
   * @see #setCellSelectionEnabled(boolean)
 | 
						|
   */
 | 
						|
  protected boolean rowSelectionAllowed;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Obsolete. Use {@link #rowSelectionAllowed}, {@link
 | 
						|
   * #getColumnSelectionAllowed}, or the combined methods {@link
 | 
						|
   * #getCellSelectionEnabled} and {@link #setCellSelectionEnabled(boolean)}.
 | 
						|
   */
 | 
						|
  protected boolean cellSelectionEnabled;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The model for data stored in the table. Confusingly, the published API
 | 
						|
   * requires that this field be called <code>dataModel</code>, despite its
 | 
						|
   * property name. The table listens to its model as a {@link
 | 
						|
   * TableModelListener}.
 | 
						|
   *
 | 
						|
   * @see #tableChanged(TableModelEvent)
 | 
						|
   * @see TableModel#addTableModelListener(TableModelListener)
 | 
						|
   */
 | 
						|
  protected TableModel dataModel;
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>A model of various aspects of the columns of the table, <em>not
 | 
						|
   * including</em> the data stored in them. The {@link TableColumnModel}
 | 
						|
   * is principally concerned with holding a set of {@link TableColumn}
 | 
						|
   * objects, each of which describes the display parameters of a column
 | 
						|
   * and the numeric index of the column from the data model which the
 | 
						|
   * column is presenting.</p>
 | 
						|
   *
 | 
						|
   * <p>The TableColumnModel also contains a {@link ListSelectionModel} which
 | 
						|
   * indicates which columns are currently selected. This selection model
 | 
						|
   * works in combination with the {@link #selectionModel} of the table
 | 
						|
   * itself to specify a <em>table selection</em>: a combination of row and
 | 
						|
   * column selections.</p>
 | 
						|
   *
 | 
						|
   * <p>Most application programmers do not need to work with this property
 | 
						|
   * at all: setting {@link #autoCreateColumnsFromModel} will construct the
 | 
						|
   * columnModel automatically, and the table acts as a facade for most of
 | 
						|
   * the interesting properties of the columnModel anyways.</p>
 | 
						|
   *
 | 
						|
   * @see #setColumnModel(TableColumnModel)
 | 
						|
   * @see #getColumnModel()
 | 
						|
   */
 | 
						|
  protected TableColumnModel columnModel;
 | 
						|
 | 
						|
  /**
 | 
						|
   * A model of the rows of this table which are currently selected. This
 | 
						|
   * model is used in combination with the column selection model held as a
 | 
						|
   * member of the {@link #columnModel} property, to represent the rows and
 | 
						|
   * columns (or both: cells) of the table which are currently selected.
 | 
						|
   *
 | 
						|
   * @see #rowSelectionAllowed
 | 
						|
   * @see #setSelectionModel(ListSelectionModel)
 | 
						|
   * @see #getSelectionModel()
 | 
						|
   * @see TableColumnModel#getSelectionModel()
 | 
						|
   * @see ListSelectionModel#addListSelectionListener(ListSelectionListener)
 | 
						|
   */
 | 
						|
  protected ListSelectionModel selectionModel;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The current cell editor.
 | 
						|
   */
 | 
						|
  protected TableCellEditor cellEditor;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Whether or not drag-and-drop is enabled on this table.
 | 
						|
   *
 | 
						|
   * @see #setDragEnabled(boolean)
 | 
						|
   * @see #getDragEnabled()
 | 
						|
   */
 | 
						|
  private boolean dragEnabled;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The color to paint the grid lines of the table, when either {@link
 | 
						|
   * #showHorizontalLines} or {@link #showVerticalLines} is set.
 | 
						|
   *
 | 
						|
   * @see #setGridColor(Color)
 | 
						|
   * @see #getGridColor()
 | 
						|
   */
 | 
						|
  protected Color gridColor;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The size this table would prefer its viewport assume, if it is
 | 
						|
   * contained in a {@link JScrollPane}.
 | 
						|
   *
 | 
						|
   * @see #setPreferredScrollableViewportSize(Dimension)
 | 
						|
   * @see #getPreferredScrollableViewportSize()
 | 
						|
   */
 | 
						|
  protected Dimension preferredViewportSize;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The color to paint the background of selected cells. Fires a property
 | 
						|
   * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY}
 | 
						|
   * when its value changes.
 | 
						|
   *
 | 
						|
   * @see #setSelectionBackground(Color)
 | 
						|
   * @see #getSelectionBackground()
 | 
						|
   */
 | 
						|
  protected Color selectionBackground;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The name carried in property change events when the {@link
 | 
						|
   * #selectionBackground} property changes.
 | 
						|
   */
 | 
						|
  private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY = "selectionBackground";
 | 
						|
 | 
						|
  /**
 | 
						|
   * The color to paint the foreground of selected cells. Fires a property
 | 
						|
   * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY}
 | 
						|
   * when its value changes.
 | 
						|
   *
 | 
						|
   * @see #setSelectionForeground(Color)
 | 
						|
   * @see #getSelectionForeground()
 | 
						|
   */
 | 
						|
  protected Color selectionForeground;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The name carried in property change events when the
 | 
						|
   * {@link #selectionForeground} property changes.
 | 
						|
   */
 | 
						|
  private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY = "selectionForeground";
 | 
						|
 | 
						|
  /**
 | 
						|
   * The showHorizontalLines property.
 | 
						|
   */
 | 
						|
  protected boolean showHorizontalLines;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The showVerticalLines property.
 | 
						|
   */
 | 
						|
  protected boolean showVerticalLines;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The tableHeader property.
 | 
						|
   */
 | 
						|
  protected JTableHeader tableHeader;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The property handler for this table's columns.
 | 
						|
   */
 | 
						|
  TableColumnPropertyChangeHandler tableColumnPropertyChangeHandler =
 | 
						|
    new TableColumnPropertyChangeHandler();
 | 
						|
 | 
						|
  /**
 | 
						|
   * Whether cell editors should receive keyboard focus when the table is
 | 
						|
   * activated.
 | 
						|
   */
 | 
						|
  private boolean surrendersFocusOnKeystroke = false;
 | 
						|
 | 
						|
  /**
 | 
						|
   * A Rectangle object to be reused in {@link #getCellRect}.
 | 
						|
   */
 | 
						|
  private Rectangle rectCache = new Rectangle();
 | 
						|
 | 
						|
  /**
 | 
						|
   * Indicates if the rowHeight property has been set by a client program or by
 | 
						|
   * the UI.
 | 
						|
   *
 | 
						|
   * @see #setUIProperty(String, Object)
 | 
						|
   * @see LookAndFeel#installProperty(JComponent, String, Object)
 | 
						|
   */
 | 
						|
  private boolean clientRowHeightSet = false;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Stores the sizes and positions of each row, when using non-uniform row
 | 
						|
   * heights. Initially the height of all rows is equal and stored in
 | 
						|
   * {link #rowHeight}. However, when an application calls
 | 
						|
   * {@link #setRowHeight(int,int)}, the table switches to non-uniform
 | 
						|
   * row height mode which stores the row heights in the SizeSequence
 | 
						|
   * object instead.
 | 
						|
   *
 | 
						|
   * @see #setRowHeight(int)
 | 
						|
   * @see #getRowHeight()
 | 
						|
   * @see #getRowHeight(int)
 | 
						|
   * @see #setRowHeight(int, int)
 | 
						|
   */
 | 
						|
  private SizeSequence rowHeights;
 | 
						|
 | 
						|
  /**
 | 
						|
   * This editor serves just a marker that the value must be simply changed to
 | 
						|
   * the opposite one instead of starting the editing session.
 | 
						|
   */
 | 
						|
  private transient TableCellEditor booleanInvertingEditor;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>JTable</code> instance.
 | 
						|
   */
 | 
						|
  public JTable ()
 | 
						|
  {
 | 
						|
    this(null, null, null);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>JTable</code> instance with the given number
 | 
						|
   * of rows and columns.
 | 
						|
   *
 | 
						|
   * @param numRows an <code>int</code> value
 | 
						|
   * @param numColumns an <code>int</code> value
 | 
						|
   */
 | 
						|
  public JTable (int numRows, int numColumns)
 | 
						|
  {
 | 
						|
    this(new DefaultTableModel(numRows, numColumns));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>JTable</code> instance, storing the given data
 | 
						|
   * array and heaving the given column names. To see the column names,
 | 
						|
   * you must place the JTable into the {@link JScrollPane}.
 | 
						|
   *
 | 
						|
   * @param data an <code>Object[][]</code> the table data
 | 
						|
   * @param columnNames an <code>Object[]</code> the column headers
 | 
						|
   */
 | 
						|
  public JTable(Object[][] data, Object[] columnNames)
 | 
						|
  {
 | 
						|
    this(new DefaultTableModel(data, columnNames));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>JTable</code> instance, using the given data model
 | 
						|
   * object that provides information about the table content. The table model
 | 
						|
   * object is asked for the table size, other features and also receives
 | 
						|
   * notifications in the case when the table has been edited by the user.
 | 
						|
   *
 | 
						|
   * @param model
 | 
						|
   *          the table model.
 | 
						|
   */
 | 
						|
  public JTable (TableModel model)
 | 
						|
  {
 | 
						|
    this(model, null, null);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>JTable</code> instance, using the given model object
 | 
						|
   * that provides information about the table content. The table data model
 | 
						|
   * object is asked for the table size, other features and also receives
 | 
						|
   * notifications in the case when the table has been edited by the user. The
 | 
						|
   * table column model provides more detailed control on the table column
 | 
						|
   * related features.
 | 
						|
   *
 | 
						|
   * @param dm
 | 
						|
   *          the table data mode
 | 
						|
   * @param cm
 | 
						|
   *          the table column model
 | 
						|
   */
 | 
						|
  public JTable (TableModel dm, TableColumnModel cm)
 | 
						|
  {
 | 
						|
    this(dm, cm, null);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>JTable</code> instance, providing data model,
 | 
						|
   * column model and list selection model. The list selection model
 | 
						|
   * manages the selections.
 | 
						|
   *
 | 
						|
   * @param dm data model (manages table data)
 | 
						|
   * @param cm column model (manages table columns)
 | 
						|
   * @param sm list selection model (manages table selections)
 | 
						|
   */
 | 
						|
  public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm)
 | 
						|
  {
 | 
						|
    boolean autoCreate = false;
 | 
						|
    TableColumnModel columnModel;
 | 
						|
    if (cm != null)
 | 
						|
        columnModel = cm;
 | 
						|
    else
 | 
						|
      {
 | 
						|
        columnModel = createDefaultColumnModel();
 | 
						|
        autoCreate = true;
 | 
						|
      }
 | 
						|
 | 
						|
    // Initialise the intercelar spacing before setting the column model to
 | 
						|
    // avoid firing unnecessary events.
 | 
						|
    // The initial incellar spacing is new Dimenstion(1,1).
 | 
						|
    rowMargin = 1;
 | 
						|
    columnModel.setColumnMargin(1);
 | 
						|
    setColumnModel(columnModel);
 | 
						|
 | 
						|
    setSelectionModel(sm == null ? createDefaultSelectionModel() : sm);
 | 
						|
    setModel(dm == null ? createDefaultDataModel() : dm);
 | 
						|
    setAutoCreateColumnsFromModel(autoCreate);
 | 
						|
    initializeLocalVars();
 | 
						|
 | 
						|
    // The following four lines properly set the lead selection indices.
 | 
						|
    // After this, the UI will handle the lead selection indices.
 | 
						|
    // FIXME: this should probably not be necessary, if the UI is installed
 | 
						|
    // before the TableModel is set then the UI will handle things on its
 | 
						|
    // own, but certain variables need to be set before the UI can be installed
 | 
						|
    // so we must get the correct order for all the method calls in this
 | 
						|
    // constructor.
 | 
						|
    // These four lines are not needed.  A Mauve test that shows this is
 | 
						|
    // gnu.testlet.javax.swing.JTable.constructors(linesNotNeeded).
 | 
						|
    // selectionModel.setAnchorSelectionIndex(-1);
 | 
						|
    // selectionModel.setLeadSelectionIndex(-1);
 | 
						|
    // columnModel.getSelectionModel().setAnchorSelectionIndex(-1);
 | 
						|
    // columnModel.getSelectionModel().setLeadSelectionIndex(-1);
 | 
						|
    updateUI();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>JTable</code> instance that uses data and column
 | 
						|
   * names, stored in {@link Vector}s.
 | 
						|
   *
 | 
						|
   * @param data the table data
 | 
						|
   * @param columnNames the table column names.
 | 
						|
   */
 | 
						|
  public JTable(Vector data, Vector columnNames)
 | 
						|
  {
 | 
						|
    this(new DefaultTableModel(data, columnNames));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Initialize local variables to default values.
 | 
						|
   */
 | 
						|
  protected void initializeLocalVars()
 | 
						|
  {
 | 
						|
    setTableHeader(createDefaultTableHeader());
 | 
						|
    if (autoCreateColumnsFromModel)
 | 
						|
      createDefaultColumnsFromModel();
 | 
						|
    this.columnModel.addColumnModelListener(this);
 | 
						|
 | 
						|
    this.autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS;
 | 
						|
    setRowHeight(16);
 | 
						|
    this.rowMargin = 1;
 | 
						|
    this.rowSelectionAllowed = true;
 | 
						|
 | 
						|
    // this.accessibleContext = new AccessibleJTable();
 | 
						|
    this.cellEditor = null;
 | 
						|
 | 
						|
    // COMPAT: Both Sun and IBM have drag enabled
 | 
						|
    this.dragEnabled = false;
 | 
						|
    this.preferredViewportSize = new Dimension(450,400);
 | 
						|
    this.showHorizontalLines = true;
 | 
						|
    this.showVerticalLines = true;
 | 
						|
    this.editingColumn = -1;
 | 
						|
    this.editingRow = -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Add the new table column. The table column class allows to specify column
 | 
						|
   * features more precisely, setting the preferred width, column data type
 | 
						|
   * (column class) and table headers.
 | 
						|
   *
 | 
						|
   * There is no need the add columns to the table if the default column
 | 
						|
   * handling is sufficient.
 | 
						|
   *
 | 
						|
   * @param column
 | 
						|
   *          the new column to add.
 | 
						|
   */
 | 
						|
  public void addColumn(TableColumn column)
 | 
						|
  {
 | 
						|
    if (column.getHeaderValue() == null)
 | 
						|
      {
 | 
						|
        String name = dataModel.getColumnName(column.getModelIndex());
 | 
						|
        column.setHeaderValue(name);
 | 
						|
      }
 | 
						|
 | 
						|
    columnModel.addColumn(column);
 | 
						|
    column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Create the default editors for this table. The default method creates
 | 
						|
   * the editor for Booleans.
 | 
						|
   *
 | 
						|
   * Other fields are edited as strings at the moment.
 | 
						|
   */
 | 
						|
  protected void createDefaultEditors()
 | 
						|
  {
 | 
						|
    JCheckBox box = new BooleanCellRenderer().getCheckBox();
 | 
						|
    box.setBorder(BorderFactory.createLineBorder(getGridColor(), 2));
 | 
						|
    box.setBorderPainted(true);
 | 
						|
    booleanInvertingEditor = new DefaultCellEditor(box);
 | 
						|
    setDefaultEditor(Boolean.class, booleanInvertingEditor);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Create the default renderers for this table. The default method creates
 | 
						|
   * renderers for Boolean, Number, Double, Date, Icon and ImageIcon.
 | 
						|
   *
 | 
						|
   */
 | 
						|
  protected void createDefaultRenderers()
 | 
						|
  {
 | 
						|
    setDefaultRenderer(Boolean.class, new BooleanCellRenderer());
 | 
						|
    setDefaultRenderer(Number.class, new NumberCellRenderer());
 | 
						|
    setDefaultRenderer(Double.class, new DoubleCellRenderer());
 | 
						|
    setDefaultRenderer(Double.class, new FloatCellRenderer());
 | 
						|
    setDefaultRenderer(Date.class, new DateCellRenderer());
 | 
						|
    setDefaultRenderer(Icon.class, new IconCellRenderer());
 | 
						|
    setDefaultRenderer(ImageIcon.class, new IconCellRenderer());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @deprecated 1.0.2, replaced by <code>new JScrollPane(JTable)</code>
 | 
						|
   */
 | 
						|
  public static JScrollPane createScrollPaneForTable(JTable table)
 | 
						|
  {
 | 
						|
    return new JScrollPane(table);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Create the default table column model that is used if the user-defined
 | 
						|
   * column model is not provided. The default method creates
 | 
						|
   * {@link DefaultTableColumnModel}.
 | 
						|
   *
 | 
						|
   * @return the created table column model.
 | 
						|
   */
 | 
						|
  protected TableColumnModel createDefaultColumnModel()
 | 
						|
  {
 | 
						|
    return new DefaultTableColumnModel();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Create the default table data model that is used if the user-defined
 | 
						|
   * data model is not provided. The default method creates
 | 
						|
   * {@link DefaultTableModel}.
 | 
						|
   *
 | 
						|
   * @return the created table data model.
 | 
						|
   */
 | 
						|
  protected TableModel createDefaultDataModel()
 | 
						|
  {
 | 
						|
    return new DefaultTableModel();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Create the default table selection model that is used if the user-defined
 | 
						|
   * selection model is not provided. The default method creates
 | 
						|
   * {@link DefaultListSelectionModel}.
 | 
						|
   *
 | 
						|
   * @return the created table data model.
 | 
						|
   */
 | 
						|
  protected ListSelectionModel createDefaultSelectionModel()
 | 
						|
  {
 | 
						|
    return new DefaultListSelectionModel();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Create the default table header, if the user - defined table header is not
 | 
						|
   * provided.
 | 
						|
   *
 | 
						|
   * @return the default table header.
 | 
						|
   */
 | 
						|
  protected JTableHeader createDefaultTableHeader()
 | 
						|
  {
 | 
						|
    return new JTableHeader(columnModel);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Invoked when the column is added. Revalidates and repains the table.
 | 
						|
   */
 | 
						|
  public void columnAdded (TableColumnModelEvent event)
 | 
						|
  {
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Invoked when the column margin is changed.
 | 
						|
   * Revalidates and repains the table.
 | 
						|
   */
 | 
						|
  public void columnMarginChanged (ChangeEvent event)
 | 
						|
  {
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Invoked when the column is moved. Revalidates and repains the table.
 | 
						|
   */
 | 
						|
  public void columnMoved (TableColumnModelEvent event)
 | 
						|
  {
 | 
						|
    if (isEditing())
 | 
						|
      editingCanceled(null);
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Invoked when the column is removed. Revalidates and repains the table.
 | 
						|
   */
 | 
						|
  public void columnRemoved (TableColumnModelEvent event)
 | 
						|
  {
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Invoked when the the column selection changes, repaints the changed
 | 
						|
   * columns. It is not recommended to override this method, register the
 | 
						|
   * listener instead.
 | 
						|
   */
 | 
						|
  public void columnSelectionChanged (ListSelectionEvent event)
 | 
						|
  {
 | 
						|
    // We must limit the indices to the bounds of the JTable's model, because
 | 
						|
    // we might get values of -1 or greater then columnCount in the case
 | 
						|
    // when columns get removed.
 | 
						|
    int idx0 = Math.max(0, Math.min(getColumnCount() - 1,
 | 
						|
                                    event.getFirstIndex()));
 | 
						|
    int idxn = Math.max(0, Math.min(getColumnCount() - 1,
 | 
						|
                                    event.getLastIndex()));
 | 
						|
 | 
						|
    int minRow = 0;
 | 
						|
    int maxRow = getRowCount() - 1;
 | 
						|
    if (getRowSelectionAllowed())
 | 
						|
      {
 | 
						|
        minRow = selectionModel.getMinSelectionIndex();
 | 
						|
        maxRow = selectionModel.getMaxSelectionIndex();
 | 
						|
        int leadRow = selectionModel.getLeadSelectionIndex();
 | 
						|
        if (minRow == -1 && maxRow == -1)
 | 
						|
          {
 | 
						|
            minRow = leadRow;
 | 
						|
            maxRow = leadRow;
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            // In this case we need to repaint also the range to leadRow, not
 | 
						|
            // only between min and max.
 | 
						|
            if (leadRow != -1)
 | 
						|
              {
 | 
						|
                minRow = Math.min(minRow, leadRow);
 | 
						|
                maxRow = Math.max(maxRow, leadRow);
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    if (minRow != -1 && maxRow != -1)
 | 
						|
      {
 | 
						|
        Rectangle first = getCellRect(minRow, idx0, false);
 | 
						|
        Rectangle last = getCellRect(maxRow, idxn, false);
 | 
						|
        Rectangle dirty = SwingUtilities.computeUnion(first.x, first.y,
 | 
						|
                                                      first.width,
 | 
						|
                                                      first.height, last);
 | 
						|
        repaint(dirty);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Invoked when the editing is cancelled.
 | 
						|
   */
 | 
						|
  public void editingCanceled (ChangeEvent event)
 | 
						|
  {
 | 
						|
    if (editorComp!=null)
 | 
						|
      {
 | 
						|
        remove(editorComp);
 | 
						|
        repaint(editorComp.getBounds());
 | 
						|
        editorComp = null;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Finish the current editing session and update the table with the
 | 
						|
   * new value by calling {@link #setValueAt}.
 | 
						|
   *
 | 
						|
   * @param event the change event
 | 
						|
   */
 | 
						|
  public void editingStopped (ChangeEvent event)
 | 
						|
  {
 | 
						|
    if (editorComp!=null)
 | 
						|
      {
 | 
						|
        remove(editorComp);
 | 
						|
        setValueAt(cellEditor.getCellEditorValue(), editingRow, editingColumn);
 | 
						|
        repaint(editorComp.getBounds());
 | 
						|
        editorComp = null;
 | 
						|
      }
 | 
						|
    requestFocusInWindow();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Invoked when the table changes.
 | 
						|
   * <code>null</code> means everything changed.
 | 
						|
   */
 | 
						|
  public void tableChanged (TableModelEvent event)
 | 
						|
  {
 | 
						|
    // update the column model from the table model if the structure has
 | 
						|
    // changed and the flag autoCreateColumnsFromModel is set
 | 
						|
    if (event == null || (event.getFirstRow() == TableModelEvent.HEADER_ROW))
 | 
						|
      handleCompleteChange(event);
 | 
						|
    else if (event.getType() == TableModelEvent.INSERT)
 | 
						|
      handleInsert(event);
 | 
						|
    else if (event.getType() == TableModelEvent.DELETE)
 | 
						|
      handleDelete(event);
 | 
						|
    else
 | 
						|
      handleUpdate(event);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Handles a request for complete relayout. This is the case when
 | 
						|
   * event.getFirstRow() == TableModelEvent.HEADER_ROW.
 | 
						|
   *
 | 
						|
   * @param ev the table model event
 | 
						|
   */
 | 
						|
  private void handleCompleteChange(TableModelEvent ev)
 | 
						|
  {
 | 
						|
    clearSelection();
 | 
						|
    checkSelection();
 | 
						|
    rowHeights = null;
 | 
						|
    if (getAutoCreateColumnsFromModel())
 | 
						|
      createDefaultColumnsFromModel();
 | 
						|
    else
 | 
						|
      resizeAndRepaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Handles table model insertions.
 | 
						|
   *
 | 
						|
   * @param ev the table model event
 | 
						|
   */
 | 
						|
  private void handleInsert(TableModelEvent ev)
 | 
						|
  {
 | 
						|
    // Sync selection model with data model.
 | 
						|
    int first = ev.getFirstRow();
 | 
						|
    if (first < 0)
 | 
						|
      first = 0;
 | 
						|
    int last = ev.getLastRow();
 | 
						|
    if (last < 0)
 | 
						|
      last = getRowCount() - 1;
 | 
						|
    selectionModel.insertIndexInterval(first, last - first + 1, true);
 | 
						|
    checkSelection();
 | 
						|
 | 
						|
    // For variable height rows we must update the SizeSequence thing.
 | 
						|
    if (rowHeights != null)
 | 
						|
      {
 | 
						|
        rowHeights.insertEntries(first, last - first + 1, rowHeight);
 | 
						|
        // TODO: We repaint the whole thing when the rows have variable
 | 
						|
        // heights. We might want to handle this better though.
 | 
						|
        repaint();
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        // Repaint the dirty region and revalidate.
 | 
						|
        int rowHeight = getRowHeight();
 | 
						|
        Rectangle dirty = new Rectangle(0, first * rowHeight,
 | 
						|
                                        getColumnModel().getTotalColumnWidth(),
 | 
						|
                                        (getRowCount() - first) * rowHeight);
 | 
						|
        repaint(dirty);
 | 
						|
      }
 | 
						|
    revalidate();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Handles table model deletions.
 | 
						|
   *
 | 
						|
   * @param ev the table model event
 | 
						|
   */
 | 
						|
  private void handleDelete(TableModelEvent ev)
 | 
						|
  {
 | 
						|
    // Sync selection model with data model.
 | 
						|
    int first = ev.getFirstRow();
 | 
						|
    if (first < 0)
 | 
						|
      first = 0;
 | 
						|
    int last = ev.getLastRow();
 | 
						|
    if (last < 0)
 | 
						|
      last = getRowCount() - 1;
 | 
						|
 | 
						|
    selectionModel.removeIndexInterval(first, last);
 | 
						|
 | 
						|
    checkSelection();
 | 
						|
 | 
						|
    if (dataModel.getRowCount() == 0)
 | 
						|
      clearSelection();
 | 
						|
 | 
						|
    // For variable height rows we must update the SizeSequence thing.
 | 
						|
    if (rowHeights != null)
 | 
						|
      {
 | 
						|
        rowHeights.removeEntries(first, last - first + 1);
 | 
						|
        // TODO: We repaint the whole thing when the rows have variable
 | 
						|
        // heights. We might want to handle this better though.
 | 
						|
        repaint();
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        // Repaint the dirty region and revalidate.
 | 
						|
        int rowHeight = getRowHeight();
 | 
						|
        int oldRowCount = getRowCount() + last - first + 1;
 | 
						|
        Rectangle dirty = new Rectangle(0, first * rowHeight,
 | 
						|
                                        getColumnModel().getTotalColumnWidth(),
 | 
						|
                                        (oldRowCount - first) * rowHeight);
 | 
						|
        repaint(dirty);
 | 
						|
      }
 | 
						|
    revalidate();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Handles table model updates without structural changes.
 | 
						|
   *
 | 
						|
   * @param ev the table model event
 | 
						|
   */
 | 
						|
  private void handleUpdate(TableModelEvent ev)
 | 
						|
  {
 | 
						|
    if (rowHeights == null)
 | 
						|
      {
 | 
						|
        // Some cells have been changed without changing the structure.
 | 
						|
        // Figure out the dirty rectangle and repaint.
 | 
						|
        int firstRow = ev.getFirstRow();
 | 
						|
        int lastRow = ev.getLastRow();
 | 
						|
        int col = ev.getColumn();
 | 
						|
        Rectangle dirty;
 | 
						|
        if (col == TableModelEvent.ALL_COLUMNS)
 | 
						|
          {
 | 
						|
            // All columns changed.
 | 
						|
            dirty = new Rectangle(0, firstRow * getRowHeight(),
 | 
						|
                                  getColumnModel().getTotalColumnWidth(), 0);
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            // Only one cell or column of cells changed.
 | 
						|
            // We need to convert to view column first.
 | 
						|
            int column = convertColumnIndexToModel(col);
 | 
						|
            dirty = getCellRect(firstRow, column, false);
 | 
						|
          }
 | 
						|
 | 
						|
        // Now adjust the height of the dirty region.
 | 
						|
        dirty.height = (lastRow + 1) * getRowHeight();
 | 
						|
        // .. and repaint.
 | 
						|
        repaint(dirty);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        // TODO: We repaint the whole thing when the rows have variable
 | 
						|
        // heights. We might want to handle this better though.
 | 
						|
        repaint();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Helper method for adjusting the lead and anchor indices when the
 | 
						|
   * table structure changed. This sets the lead and anchor to -1 if there's
 | 
						|
   * no more rows, or set them to 0 when they were at -1 and there are actually
 | 
						|
   * some rows now.
 | 
						|
   */
 | 
						|
  private void checkSelection()
 | 
						|
  {
 | 
						|
    TableModel m = getModel();
 | 
						|
    ListSelectionModel sm = selectionModel;
 | 
						|
    if (m != null)
 | 
						|
      {
 | 
						|
        int lead = sm.getLeadSelectionIndex();
 | 
						|
        int c = m.getRowCount();
 | 
						|
        if (c == 0 && lead != -1)
 | 
						|
          {
 | 
						|
            // No rows in the model, reset lead and anchor to -1.
 | 
						|
            sm.setValueIsAdjusting(true);
 | 
						|
            sm.setAnchorSelectionIndex(-1);
 | 
						|
            sm.setLeadSelectionIndex(-1);
 | 
						|
            sm.setValueIsAdjusting(false);
 | 
						|
          }
 | 
						|
        else if (c != 0 && lead == -1)
 | 
						|
          {
 | 
						|
            // We have rows, but no lead/anchor. Set them to 0. We
 | 
						|
            // do a little trick here so that the actual selection is not
 | 
						|
            // touched.
 | 
						|
            if (sm.isSelectedIndex(0))
 | 
						|
              sm.addSelectionInterval(0, 0);
 | 
						|
            else
 | 
						|
              sm.removeSelectionInterval(0, 0);
 | 
						|
          }
 | 
						|
        // Nothing to do in the other cases.
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Invoked when another table row is selected. It is not recommended
 | 
						|
   * to override thid method, register the listener instead.
 | 
						|
   */
 | 
						|
  public void valueChanged (ListSelectionEvent event)
 | 
						|
  {
 | 
						|
    // If we are in the editing process, end the editing session.
 | 
						|
    if (isEditing())
 | 
						|
      editingStopped(null);
 | 
						|
 | 
						|
    // Repaint the changed region.
 | 
						|
    int first = Math.max(0, Math.min(getRowCount() - 1, event.getFirstIndex()));
 | 
						|
    int last = Math.max(0, Math.min(getRowCount() - 1, event.getLastIndex()));
 | 
						|
    Rectangle rect1 = getCellRect(first, 0, false);
 | 
						|
    Rectangle rect2 = getCellRect(last, getColumnCount() - 1, false);
 | 
						|
    Rectangle dirty = SwingUtilities.computeUnion(rect2.x, rect2.y,
 | 
						|
                                                  rect2.width, rect2.height,
 | 
						|
                                                  rect1);
 | 
						|
    repaint(dirty);
 | 
						|
  }
 | 
						|
 | 
						|
 /**
 | 
						|
   * Returns index of the column that contains specified point
 | 
						|
   * or -1 if this table doesn't contain this point.
 | 
						|
   *
 | 
						|
   * @param point point to identify the column
 | 
						|
   * @return index of the column that contains specified point or
 | 
						|
   * -1 if this table doesn't contain this point.
 | 
						|
   */
 | 
						|
  public int columnAtPoint(Point point)
 | 
						|
  {
 | 
						|
    int ncols = getColumnCount();
 | 
						|
    Dimension gap = getIntercellSpacing();
 | 
						|
    TableColumnModel cols = getColumnModel();
 | 
						|
    int x = point.x;
 | 
						|
 | 
						|
    for (int i = 0; i < ncols; ++i)
 | 
						|
      {
 | 
						|
        int width = cols.getColumn(i).getWidth()
 | 
						|
                    + (gap == null ? 0 : gap.width);
 | 
						|
        if (0 <= x && x < width)
 | 
						|
          return i;
 | 
						|
        x -= width;
 | 
						|
      }
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns index of the row that contains specified point or -1 if this table
 | 
						|
   * doesn't contain this point.
 | 
						|
   *
 | 
						|
   * @param point point to identify the row
 | 
						|
   * @return index of the row that contains specified point or -1 if this table
 | 
						|
   *         doesn't contain this point.
 | 
						|
   */
 | 
						|
  public int rowAtPoint(Point point)
 | 
						|
  {
 | 
						|
    if (point != null)
 | 
						|
      {
 | 
						|
        int nrows = getRowCount();
 | 
						|
        int r;
 | 
						|
        int y = point.y;
 | 
						|
        if (rowHeights == null)
 | 
						|
          {
 | 
						|
            int height = getRowHeight();
 | 
						|
            r = y / height;
 | 
						|
          }
 | 
						|
        else
 | 
						|
          r = rowHeights.getIndex(y);
 | 
						|
 | 
						|
        if (r < 0 || r >= nrows)
 | 
						|
          return -1;
 | 
						|
        else
 | 
						|
          return r;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Calculate the visible rectangle for a particular row and column. The
 | 
						|
   * row and column are specified in visual terms; the column may not match
 | 
						|
   * the {@link #dataModel} column.
 | 
						|
   *
 | 
						|
   * @param row the visible row to get the cell rectangle of
 | 
						|
   *
 | 
						|
   * @param column the visible column to get the cell rectangle of, which may
 | 
						|
   * differ from the {@link #dataModel} column
 | 
						|
   *
 | 
						|
   * @param includeSpacing whether or not to include the cell margins in the
 | 
						|
   * resulting cell. If <code>false</code>, the result will only contain the
 | 
						|
   * inner area of the target cell, not including its margins.
 | 
						|
   *
 | 
						|
   * @return a rectangle enclosing the specified cell
 | 
						|
   */
 | 
						|
  public Rectangle getCellRect(int row,
 | 
						|
                               int column,
 | 
						|
                               boolean includeSpacing)
 | 
						|
  {
 | 
						|
    Rectangle cellRect = new Rectangle(0, 0, 0, 0);
 | 
						|
 | 
						|
    // Check for valid range vertically.
 | 
						|
    if (row >= getRowCount())
 | 
						|
      {
 | 
						|
        cellRect.height = getHeight();
 | 
						|
      }
 | 
						|
    else if (row >= 0)
 | 
						|
      {
 | 
						|
        cellRect.height = getRowHeight(row);
 | 
						|
        if (rowHeights == null)
 | 
						|
          cellRect.y = row * cellRect.height;
 | 
						|
        else
 | 
						|
          cellRect.y = rowHeights.getPosition(row);
 | 
						|
 | 
						|
        if (! includeSpacing)
 | 
						|
          {
 | 
						|
            // The rounding here is important.
 | 
						|
            int rMargin = getRowMargin();
 | 
						|
            cellRect.y += rMargin / 2;
 | 
						|
            cellRect.height -= rMargin;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    // else row < 0, y = height = 0
 | 
						|
 | 
						|
    // Check for valid range horizontally.
 | 
						|
    if (column < 0)
 | 
						|
      {
 | 
						|
        if (! getComponentOrientation().isLeftToRight())
 | 
						|
          {
 | 
						|
            cellRect.x = getWidth();
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else if (column >= getColumnCount())
 | 
						|
      {
 | 
						|
        if (getComponentOrientation().isLeftToRight())
 | 
						|
          {
 | 
						|
            cellRect.x = getWidth();
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        TableColumnModel tcm = getColumnModel();
 | 
						|
        if (getComponentOrientation().isLeftToRight())
 | 
						|
          {
 | 
						|
            for (int i = 0; i < column; i++)
 | 
						|
              cellRect.x += tcm.getColumn(i).getWidth();
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            for (int i = tcm.getColumnCount() - 1; i > column; i--)
 | 
						|
              cellRect.x += tcm.getColumn(i).getWidth();
 | 
						|
          }
 | 
						|
        cellRect.width = tcm.getColumn(column).getWidth();
 | 
						|
        if (! includeSpacing)
 | 
						|
          {
 | 
						|
            // The rounding here is important.
 | 
						|
            int cMargin = tcm.getColumnMargin();
 | 
						|
            cellRect.x += cMargin / 2;
 | 
						|
            cellRect.width -= cMargin;
 | 
						|
          }
 | 
						|
      }
 | 
						|
 | 
						|
    return cellRect;
 | 
						|
  }
 | 
						|
 | 
						|
  public void clearSelection()
 | 
						|
  {
 | 
						|
    selectionModel.clearSelection();
 | 
						|
    getColumnModel().getSelectionModel().clearSelection();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the selectedRow property by delegation to
 | 
						|
   * the {@link ListSelectionModel#getMinSelectionIndex} method of the
 | 
						|
   * {@link #selectionModel} field.
 | 
						|
   *
 | 
						|
   * @return The current value of the selectedRow property
 | 
						|
   */
 | 
						|
  public int getSelectedRow ()
 | 
						|
  {
 | 
						|
    return selectionModel.getMinSelectionIndex();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #selectionModel} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public ListSelectionModel getSelectionModel()
 | 
						|
  {
 | 
						|
    //Neither Sun nor IBM returns null if rowSelection not allowed
 | 
						|
    return selectionModel;
 | 
						|
  }
 | 
						|
 | 
						|
  public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
 | 
						|
  {
 | 
						|
    int block;
 | 
						|
    if (orientation == SwingConstants.HORIZONTAL)
 | 
						|
      {
 | 
						|
        block = visibleRect.width;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        int rowHeight = getRowHeight();
 | 
						|
        if (rowHeight > 0)
 | 
						|
          block = Math.max(rowHeight, // Little hack for useful rounding.
 | 
						|
                           (visibleRect.height / rowHeight) * rowHeight);
 | 
						|
        else
 | 
						|
          block = visibleRect.height;
 | 
						|
      }
 | 
						|
    return block;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>scrollableTracksViewportHeight</code> property.
 | 
						|
   *
 | 
						|
   * @return The constant value <code>false</code>
 | 
						|
   */
 | 
						|
  public boolean getScrollableTracksViewportHeight()
 | 
						|
  {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>scrollableTracksViewportWidth</code> property.
 | 
						|
   *
 | 
						|
   * @return <code>true</code> unless the {@link #autoResizeMode} property is
 | 
						|
   * <code>AUTO_RESIZE_OFF</code>
 | 
						|
   */
 | 
						|
  public boolean getScrollableTracksViewportWidth()
 | 
						|
  {
 | 
						|
    if (autoResizeMode == AUTO_RESIZE_OFF)
 | 
						|
      return false;
 | 
						|
    else
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Return the preferred scrolling amount (in pixels) for the given scrolling
 | 
						|
   * direction and orientation. This method handles a partially exposed row by
 | 
						|
   * returning the distance required to completely expose the item. When
 | 
						|
   * scrolling the top item is completely exposed.
 | 
						|
   *
 | 
						|
   * @param visibleRect the currently visible part of the component.
 | 
						|
   * @param orientation the scrolling orientation
 | 
						|
   * @param direction the scrolling direction (negative - up, positive -down).
 | 
						|
   *          The values greater than one means that more mouse wheel or similar
 | 
						|
   *          events were generated, and hence it is better to scroll the longer
 | 
						|
   *          distance.
 | 
						|
   *
 | 
						|
   * @author Roman Kennke (kennke@aicas.com)
 | 
						|
   */
 | 
						|
  public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
 | 
						|
                                        int direction)
 | 
						|
  {
 | 
						|
    int unit;
 | 
						|
    if (orientation == SwingConstants.HORIZONTAL)
 | 
						|
      unit = 100;
 | 
						|
    else
 | 
						|
      {
 | 
						|
        unit = getRowHeight();
 | 
						|
        // The following adjustment doesn't work for variable height rows.
 | 
						|
        // It fully exposes partially visible rows in the scrolling direction.
 | 
						|
        if (rowHeights == null)
 | 
						|
          {
 | 
						|
            if (direction > 0)
 | 
						|
              {
 | 
						|
                // Scroll down.
 | 
						|
                // How much pixles are exposed from the last item?
 | 
						|
                int exposed = (visibleRect.y + visibleRect.height) % unit;
 | 
						|
                if (exposed > 0 && exposed < unit - 1)
 | 
						|
                  unit = unit - exposed - 1;
 | 
						|
              }
 | 
						|
            else
 | 
						|
              {
 | 
						|
                // Scroll up.
 | 
						|
                int exposed = visibleRect.y % unit;
 | 
						|
                if (exposed > 0 && exposed < unit)
 | 
						|
                  unit = exposed;
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return unit;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the cell editor, suitable for editing the given cell. The default
 | 
						|
   * method requests the editor from the column model. If the column model does
 | 
						|
   * not provide the editor, the call is forwarded to the
 | 
						|
   * {@link #getDefaultEditor(Class)} with the parameter, obtained from
 | 
						|
   * {@link TableModel#getColumnClass(int)}.
 | 
						|
   *
 | 
						|
   * @param row the cell row
 | 
						|
   * @param column the cell column
 | 
						|
   * @return the editor to edit that cell
 | 
						|
   */
 | 
						|
  public TableCellEditor getCellEditor(int row, int column)
 | 
						|
  {
 | 
						|
    TableCellEditor editor = columnModel.getColumn(column).getCellEditor();
 | 
						|
 | 
						|
    if (editor == null)
 | 
						|
      {
 | 
						|
        int mcolumn = convertColumnIndexToModel(column);
 | 
						|
        editor = getDefaultEditor(dataModel.getColumnClass(mcolumn));
 | 
						|
      }
 | 
						|
 | 
						|
    return editor;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the default editor for editing values of the given type
 | 
						|
   * (String, Boolean and so on).
 | 
						|
   *
 | 
						|
   * @param columnClass the class of the value that will be edited.
 | 
						|
   *
 | 
						|
   * @return the editor, suitable for editing this data type
 | 
						|
   */
 | 
						|
  public TableCellEditor getDefaultEditor(Class<?> columnClass)
 | 
						|
  {
 | 
						|
    if (defaultEditorsByColumnClass.containsKey(columnClass))
 | 
						|
      return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass);
 | 
						|
    else
 | 
						|
      {
 | 
						|
        JTextField t = new TableTextField();
 | 
						|
        TableCellEditor r = new DefaultCellEditor(t);
 | 
						|
        defaultEditorsByColumnClass.put(columnClass, r);
 | 
						|
        return r;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the cell renderer for rendering the given cell.
 | 
						|
   *
 | 
						|
   * @param row the cell row
 | 
						|
   * @param column the cell column
 | 
						|
   * @return the cell renderer to render that cell.
 | 
						|
   */
 | 
						|
  public TableCellRenderer getCellRenderer(int row, int column)
 | 
						|
  {
 | 
						|
    TableCellRenderer renderer = null;
 | 
						|
    if (columnModel.getColumnCount() > 0)
 | 
						|
      renderer = columnModel.getColumn(column).getCellRenderer();
 | 
						|
    if (renderer == null)
 | 
						|
      {
 | 
						|
        int mcolumn = convertColumnIndexToModel(column);
 | 
						|
        renderer = getDefaultRenderer(dataModel.getColumnClass(mcolumn));
 | 
						|
      }
 | 
						|
    return renderer;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set default renderer for rendering the given data type.
 | 
						|
   *
 | 
						|
   * @param columnClass the data type (String, Boolean and so on) that must be
 | 
						|
   *          rendered.
 | 
						|
   * @param rend the renderer that will rend this data type
 | 
						|
   */
 | 
						|
  public void setDefaultRenderer(Class<?> columnClass, TableCellRenderer rend)
 | 
						|
  {
 | 
						|
    defaultRenderersByColumnClass.put(columnClass, rend);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the default renderer for rendering the given data type.
 | 
						|
   *
 | 
						|
   * @param columnClass the data that must be rendered
 | 
						|
   *
 | 
						|
   * @return the appropriate defauld renderer for rendering that data type.
 | 
						|
   */
 | 
						|
  public TableCellRenderer getDefaultRenderer(Class<?> columnClass)
 | 
						|
  {
 | 
						|
    if (defaultRenderersByColumnClass.containsKey(columnClass))
 | 
						|
      return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass);
 | 
						|
    else
 | 
						|
      {
 | 
						|
        TableCellRenderer r = new DefaultTableCellRenderer();
 | 
						|
        defaultRenderersByColumnClass.put(columnClass, r);
 | 
						|
        return r;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Convert the table model index into the table column number.
 | 
						|
   * The model number need not match the real column position. The columns
 | 
						|
   * may be rearranged by the user with mouse at any time by dragging the
 | 
						|
   * column headers.
 | 
						|
   *
 | 
						|
   * @param vc the column number (0=first).
 | 
						|
   *
 | 
						|
   * @return the table column model index of this column.
 | 
						|
   *
 | 
						|
   * @see TableColumn#getModelIndex()
 | 
						|
   */
 | 
						|
  public int convertColumnIndexToModel(int vc)
 | 
						|
  {
 | 
						|
    if (vc < 0)
 | 
						|
      return vc;
 | 
						|
    else
 | 
						|
      return columnModel.getColumn(vc).getModelIndex();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Convert the table column number to the table column model index.
 | 
						|
   * The model number need not match the real column position. The columns
 | 
						|
   * may be rearranged by the user with mouse at any time by dragging the
 | 
						|
   * column headers.
 | 
						|
   *
 | 
						|
   * @param mc the table column index (0=first).
 | 
						|
   *
 | 
						|
   * @return the table column number in the model
 | 
						|
   *
 | 
						|
   * @see TableColumn#getModelIndex()
 | 
						|
   */
 | 
						|
  public int convertColumnIndexToView(int mc)
 | 
						|
  {
 | 
						|
    if (mc < 0)
 | 
						|
      return mc;
 | 
						|
    int ncols = getColumnCount();
 | 
						|
    for (int vc = 0; vc < ncols; ++vc)
 | 
						|
      {
 | 
						|
        if (columnModel.getColumn(vc).getModelIndex() == mc)
 | 
						|
          return vc;
 | 
						|
      }
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Prepare the renderer for rendering the given cell.
 | 
						|
   *
 | 
						|
   * @param renderer the renderer being prepared
 | 
						|
   * @param row the row of the cell being rendered
 | 
						|
   * @param column the column of the cell being rendered
 | 
						|
   *
 | 
						|
   * @return the component which .paint() method will paint the cell.
 | 
						|
   */
 | 
						|
  public Component prepareRenderer(TableCellRenderer renderer,
 | 
						|
                                   int row,
 | 
						|
                                   int column)
 | 
						|
  {
 | 
						|
    boolean rowSelAllowed = getRowSelectionAllowed();
 | 
						|
    boolean colSelAllowed = getColumnSelectionAllowed();
 | 
						|
    boolean isSel = false;
 | 
						|
    if (rowSelAllowed && colSelAllowed || !rowSelAllowed && !colSelAllowed)
 | 
						|
      isSel = isCellSelected(row, column);
 | 
						|
    else
 | 
						|
      isSel = isRowSelected(row) && getRowSelectionAllowed()
 | 
						|
           || isColumnSelected(column) && getColumnSelectionAllowed();
 | 
						|
 | 
						|
    // Determine the focused cell. The focused cell is the cell at the
 | 
						|
    // leadSelectionIndices of the row and column selection model.
 | 
						|
    ListSelectionModel rowSel = getSelectionModel();
 | 
						|
    ListSelectionModel colSel = getColumnModel().getSelectionModel();
 | 
						|
    boolean hasFocus = hasFocus() && isEnabled()
 | 
						|
                       && rowSel.getLeadSelectionIndex() == row
 | 
						|
                       && colSel.getLeadSelectionIndex() == column;
 | 
						|
 | 
						|
    return renderer.getTableCellRendererComponent(this,
 | 
						|
                                                  dataModel.getValueAt(row,
 | 
						|
                                                                       convertColumnIndexToModel(column)),
 | 
						|
                                                  isSel,
 | 
						|
                                                  hasFocus,
 | 
						|
                                                  row, column);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #autoCreateColumnsFromModel} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public boolean getAutoCreateColumnsFromModel()
 | 
						|
  {
 | 
						|
    return autoCreateColumnsFromModel;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #autoResizeMode} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public int getAutoResizeMode()
 | 
						|
  {
 | 
						|
    return autoResizeMode;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #rowHeight} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public int getRowHeight()
 | 
						|
  {
 | 
						|
    return rowHeight;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the height of the specified row.
 | 
						|
   *
 | 
						|
   * @param row the row whose height to return
 | 
						|
   */
 | 
						|
  public int getRowHeight(int row)
 | 
						|
  {
 | 
						|
    int rh = rowHeight;
 | 
						|
    if (rowHeights != null)
 | 
						|
      rh = rowHeights.getSize(row);
 | 
						|
    return rh;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #rowMargin} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public int getRowMargin()
 | 
						|
  {
 | 
						|
    return rowMargin;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #rowSelectionAllowed} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   *
 | 
						|
   * @see #setRowSelectionAllowed(boolean)
 | 
						|
   */
 | 
						|
  public boolean getRowSelectionAllowed()
 | 
						|
  {
 | 
						|
    return rowSelectionAllowed;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #cellSelectionEnabled} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public boolean getCellSelectionEnabled()
 | 
						|
  {
 | 
						|
    return getColumnSelectionAllowed() && getRowSelectionAllowed();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #dataModel} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public TableModel getModel()
 | 
						|
  {
 | 
						|
    return dataModel;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>columnCount</code> property by
 | 
						|
   * delegation to the {@link #columnModel} field.
 | 
						|
   *
 | 
						|
   * @return The current value of the columnCount property
 | 
						|
   */
 | 
						|
  public int getColumnCount()
 | 
						|
  {
 | 
						|
    return columnModel.getColumnCount();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>rowCount</code> property by
 | 
						|
   * delegation to the {@link #dataModel} field.
 | 
						|
   *
 | 
						|
   * @return The current value of the rowCount property
 | 
						|
   */
 | 
						|
  public int getRowCount()
 | 
						|
  {
 | 
						|
    return dataModel.getRowCount();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #columnModel} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public TableColumnModel getColumnModel()
 | 
						|
  {
 | 
						|
    return columnModel;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>selectedColumn</code> property by
 | 
						|
   * delegation to the {@link #columnModel} field.
 | 
						|
   *
 | 
						|
   * @return The current value of the selectedColumn property
 | 
						|
   */
 | 
						|
  public int getSelectedColumn()
 | 
						|
  {
 | 
						|
    return columnModel.getSelectionModel().getMinSelectionIndex();
 | 
						|
  }
 | 
						|
 | 
						|
  private static int countSelections(ListSelectionModel lsm)
 | 
						|
  {
 | 
						|
    int lo = lsm.getMinSelectionIndex();
 | 
						|
    int hi = lsm.getMaxSelectionIndex();
 | 
						|
    int sum = 0;
 | 
						|
    if (lo != -1 && hi != -1)
 | 
						|
      {
 | 
						|
        switch (lsm.getSelectionMode())
 | 
						|
          {
 | 
						|
          case ListSelectionModel.SINGLE_SELECTION:
 | 
						|
            sum = 1;
 | 
						|
            break;
 | 
						|
 | 
						|
          case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
 | 
						|
            sum = hi - lo + 1;
 | 
						|
            break;
 | 
						|
 | 
						|
          case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
 | 
						|
            for (int i = lo; i <= hi; ++i)
 | 
						|
              if (lsm.isSelectedIndex(i))
 | 
						|
                ++sum;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return sum;
 | 
						|
  }
 | 
						|
 | 
						|
  private static int[] getSelections(ListSelectionModel lsm)
 | 
						|
  {
 | 
						|
    int sz = countSelections(lsm);
 | 
						|
    int [] ret = new int[sz];
 | 
						|
 | 
						|
    int lo = lsm.getMinSelectionIndex();
 | 
						|
    int hi = lsm.getMaxSelectionIndex();
 | 
						|
    int j = 0;
 | 
						|
    if (lo != -1 && hi != -1)
 | 
						|
      {
 | 
						|
        switch (lsm.getSelectionMode())
 | 
						|
          {
 | 
						|
          case ListSelectionModel.SINGLE_SELECTION:
 | 
						|
            ret[0] = lo;
 | 
						|
            break;
 | 
						|
 | 
						|
          case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
 | 
						|
            for (int i = lo; i <= hi; ++i)
 | 
						|
              ret[j++] = i;
 | 
						|
            break;
 | 
						|
 | 
						|
          case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
 | 
						|
            for (int i = lo; i <= hi; ++i)
 | 
						|
              if (lsm.isSelectedIndex(i))
 | 
						|
                ret[j++] = i;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>selectedColumnCount</code> property by
 | 
						|
   * delegation to the {@link #columnModel} field.
 | 
						|
   *
 | 
						|
   * @return The current value of the selectedColumnCount property
 | 
						|
   */
 | 
						|
  public int getSelectedColumnCount()
 | 
						|
  {
 | 
						|
    return countSelections(columnModel.getSelectionModel());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>selectedColumns</code> property by
 | 
						|
   * delegation to the {@link #columnModel} field.
 | 
						|
   *
 | 
						|
   * @return The current value of the selectedColumns property
 | 
						|
   */
 | 
						|
  public int[] getSelectedColumns()
 | 
						|
  {
 | 
						|
    return getSelections(columnModel.getSelectionModel());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>columnSelectionAllowed</code> property.
 | 
						|
   *
 | 
						|
   * @return The current value of the columnSelectionAllowed property
 | 
						|
   *
 | 
						|
   * @see #setColumnSelectionAllowed(boolean)
 | 
						|
   */
 | 
						|
  public boolean getColumnSelectionAllowed()
 | 
						|
  {
 | 
						|
    return getColumnModel().getColumnSelectionAllowed();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>selectedRowCount</code> property by
 | 
						|
   * delegation to the {@link #selectionModel} field.
 | 
						|
   *
 | 
						|
   * @return The current value of the selectedRowCount property
 | 
						|
   */
 | 
						|
  public int getSelectedRowCount()
 | 
						|
  {
 | 
						|
    return countSelections(selectionModel);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>selectedRows</code> property by
 | 
						|
   * delegation to the {@link #selectionModel} field.
 | 
						|
   *
 | 
						|
   * @return The current value of the selectedRows property
 | 
						|
   */
 | 
						|
  public int[] getSelectedRows()
 | 
						|
  {
 | 
						|
    return getSelections(selectionModel);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #accessibleContext} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public AccessibleContext getAccessibleContext()
 | 
						|
  {
 | 
						|
    if (accessibleContext == null)
 | 
						|
      {
 | 
						|
        AccessibleJTable ctx = new AccessibleJTable();
 | 
						|
        addPropertyChangeListener(ctx);
 | 
						|
        TableColumnModel tcm = getColumnModel();
 | 
						|
        tcm.addColumnModelListener(ctx);
 | 
						|
        tcm.getSelectionModel().addListSelectionListener(ctx);
 | 
						|
        getSelectionModel().addListSelectionListener(ctx);
 | 
						|
 | 
						|
        accessibleContext = ctx;
 | 
						|
      }
 | 
						|
    return accessibleContext;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #cellEditor} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public TableCellEditor getCellEditor()
 | 
						|
  {
 | 
						|
    return cellEditor;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #dragEnabled} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public boolean getDragEnabled()
 | 
						|
  {
 | 
						|
    return dragEnabled;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #gridColor} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public Color getGridColor()
 | 
						|
  {
 | 
						|
    return gridColor;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the <code>intercellSpacing</code> property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public Dimension getIntercellSpacing()
 | 
						|
  {
 | 
						|
    return new Dimension(columnModel.getColumnMargin(), rowMargin);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #preferredViewportSize} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public Dimension getPreferredScrollableViewportSize()
 | 
						|
  {
 | 
						|
    return preferredViewportSize;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #selectionBackground} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public Color getSelectionBackground()
 | 
						|
  {
 | 
						|
    return selectionBackground;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #selectionForeground} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public Color getSelectionForeground()
 | 
						|
  {
 | 
						|
    return selectionForeground;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #showHorizontalLines} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public boolean getShowHorizontalLines()
 | 
						|
  {
 | 
						|
    return showHorizontalLines;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #showVerticalLines} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public boolean getShowVerticalLines()
 | 
						|
  {
 | 
						|
    return showVerticalLines;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the value of the {@link #tableHeader} property.
 | 
						|
   *
 | 
						|
   * @return The current value of the property
 | 
						|
   */
 | 
						|
  public JTableHeader getTableHeader()
 | 
						|
  {
 | 
						|
    return tableHeader;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Removes specified column from displayable columns of this table.
 | 
						|
   *
 | 
						|
   * @param column column to removed
 | 
						|
   */
 | 
						|
  public void removeColumn(TableColumn column)
 | 
						|
  {
 | 
						|
    columnModel.removeColumn(column);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Moves column at the specified index to new given location.
 | 
						|
   *
 | 
						|
   * @param column index of the column to move
 | 
						|
   * @param targetColumn index specifying new location of the column
 | 
						|
   */
 | 
						|
  public void moveColumn(int column,int targetColumn)
 | 
						|
  {
 | 
						|
    columnModel.moveColumn(column, targetColumn);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #autoCreateColumnsFromModel} flag.  If the
 | 
						|
   * flag changes from <code>false</code> to <code>true</code>, the
 | 
						|
   * {@link #createDefaultColumnsFromModel()} method is called.
 | 
						|
   *
 | 
						|
   * @param autoCreate  the new value of the flag.
 | 
						|
   */
 | 
						|
  public void setAutoCreateColumnsFromModel(boolean autoCreate)
 | 
						|
  {
 | 
						|
    if (autoCreateColumnsFromModel != autoCreate)
 | 
						|
    {
 | 
						|
      autoCreateColumnsFromModel = autoCreate;
 | 
						|
      if (autoCreate)
 | 
						|
        createDefaultColumnsFromModel();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #autoResizeMode} property.
 | 
						|
   *
 | 
						|
   * @param a The new value of the autoResizeMode property
 | 
						|
   */
 | 
						|
  public void setAutoResizeMode(int a)
 | 
						|
  {
 | 
						|
    autoResizeMode = a;
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Sets the height for all rows in the table. If you want to change the
 | 
						|
   * height of a single row instead, use {@link #setRowHeight(int, int)}.
 | 
						|
   *
 | 
						|
   * @param r the height to set for all rows
 | 
						|
   *
 | 
						|
   * @see #getRowHeight()
 | 
						|
   * @see #setRowHeight(int, int)
 | 
						|
   * @see #getRowHeight(int)
 | 
						|
   */
 | 
						|
  public void setRowHeight(int r)
 | 
						|
  {
 | 
						|
    if (r < 1)
 | 
						|
      throw new IllegalArgumentException();
 | 
						|
 | 
						|
    clientRowHeightSet = true;
 | 
						|
 | 
						|
    rowHeight = r;
 | 
						|
    rowHeights = null;
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Sets the height of a single row in the table.
 | 
						|
   *
 | 
						|
   * @param rh the new row height
 | 
						|
   * @param row the row to change the height of
 | 
						|
   */
 | 
						|
  public void setRowHeight(int row, int rh)
 | 
						|
  {
 | 
						|
    if (rowHeights == null)
 | 
						|
      {
 | 
						|
        rowHeights = new SizeSequence(getRowCount(), rowHeight);
 | 
						|
      }
 | 
						|
    rowHeights.setSize(row, rh);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #rowMargin} property.
 | 
						|
   *
 | 
						|
   * @param r The new value of the rowMargin property
 | 
						|
   */
 | 
						|
  public void setRowMargin(int r)
 | 
						|
  {
 | 
						|
    rowMargin = r;
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #rowSelectionAllowed} property.
 | 
						|
   *
 | 
						|
   * @param r The new value of the rowSelectionAllowed property
 | 
						|
   *
 | 
						|
   * @see #getRowSelectionAllowed()
 | 
						|
   */
 | 
						|
  public void setRowSelectionAllowed(boolean r)
 | 
						|
  {
 | 
						|
    if (rowSelectionAllowed != r)
 | 
						|
      {
 | 
						|
        rowSelectionAllowed = r;
 | 
						|
        firePropertyChange("rowSelectionAllowed", !r, r);
 | 
						|
        repaint();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #cellSelectionEnabled} property.
 | 
						|
   *
 | 
						|
   * @param c The new value of the cellSelectionEnabled property
 | 
						|
   */
 | 
						|
  public void setCellSelectionEnabled(boolean c)
 | 
						|
  {
 | 
						|
    setColumnSelectionAllowed(c);
 | 
						|
    setRowSelectionAllowed(c);
 | 
						|
    // for backward-compatibility sake:
 | 
						|
    cellSelectionEnabled = true;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>Set the value of the {@link #dataModel} property.</p>
 | 
						|
   *
 | 
						|
   * <p>Unregister <code>this</code> as a {@link TableModelListener} from
 | 
						|
   * previous {@link #dataModel} and register it with new parameter
 | 
						|
   * <code>m</code>.</p>
 | 
						|
   *
 | 
						|
   * @param m The new value of the model property
 | 
						|
   */
 | 
						|
  public void setModel(TableModel m)
 | 
						|
  {
 | 
						|
    // Throw exception is m is null.
 | 
						|
    if (m == null)
 | 
						|
      throw new IllegalArgumentException();
 | 
						|
 | 
						|
    // Don't do anything if setting the current model again.
 | 
						|
    if (dataModel == m)
 | 
						|
      return;
 | 
						|
 | 
						|
    TableModel oldModel = dataModel;
 | 
						|
 | 
						|
    // Remove table as TableModelListener from old model.
 | 
						|
    if (dataModel != null)
 | 
						|
      dataModel.removeTableModelListener(this);
 | 
						|
 | 
						|
    if (m != null)
 | 
						|
      {
 | 
						|
        // Set property.
 | 
						|
        dataModel = m;
 | 
						|
 | 
						|
        // Add table as TableModelListener to new model.
 | 
						|
        dataModel.addTableModelListener(this);
 | 
						|
 | 
						|
        // Notify the tableChanged method.
 | 
						|
        tableChanged(new TableModelEvent(dataModel,
 | 
						|
                                         TableModelEvent.HEADER_ROW));
 | 
						|
 | 
						|
        // Automatically create columns.
 | 
						|
        if (autoCreateColumnsFromModel)
 | 
						|
          createDefaultColumnsFromModel();
 | 
						|
      }
 | 
						|
 | 
						|
    // This property is bound, so we fire a property change event.
 | 
						|
    firePropertyChange("model", oldModel, dataModel);
 | 
						|
 | 
						|
    // Repaint table.
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>Set the value of the {@link #columnModel} property.</p>
 | 
						|
   *
 | 
						|
   * <p>Unregister <code>this</code> as a {@link TableColumnModelListener}
 | 
						|
   * from previous {@link #columnModel} and register it with new parameter
 | 
						|
   * <code>c</code>.</p>
 | 
						|
   *
 | 
						|
   * @param c The new value of the columnModel property
 | 
						|
   */
 | 
						|
  public void setColumnModel(TableColumnModel c)
 | 
						|
  {
 | 
						|
    if (c == null)
 | 
						|
      throw new IllegalArgumentException();
 | 
						|
    TableColumnModel tmp = columnModel;
 | 
						|
    if (tmp != null)
 | 
						|
      tmp.removeColumnModelListener(this);
 | 
						|
    if (c != null)
 | 
						|
      c.addColumnModelListener(this);
 | 
						|
    columnModel = c;
 | 
						|
    if (dataModel != null && columnModel != null)
 | 
						|
      {
 | 
						|
        int ncols = getColumnCount();
 | 
						|
        TableColumn column;
 | 
						|
        for (int i = 0; i < ncols; ++i)
 | 
						|
          {
 | 
						|
            column = columnModel.getColumn(i);
 | 
						|
            if (column.getHeaderValue()==null)
 | 
						|
              column.setHeaderValue(dataModel.getColumnName(i));
 | 
						|
          }
 | 
						|
      }
 | 
						|
 | 
						|
    // according to Sun's spec we also have to set the tableHeader's
 | 
						|
    // column model here
 | 
						|
    if (tableHeader != null)
 | 
						|
      tableHeader.setColumnModel(c);
 | 
						|
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the <code>columnSelectionAllowed</code> property.
 | 
						|
   *
 | 
						|
   * @param c The new value of the property
 | 
						|
   *
 | 
						|
   * @see #getColumnSelectionAllowed()
 | 
						|
   */
 | 
						|
  public void setColumnSelectionAllowed(boolean c)
 | 
						|
  {
 | 
						|
    if (columnModel.getColumnSelectionAllowed() != c)
 | 
						|
      {
 | 
						|
        columnModel.setColumnSelectionAllowed(c);
 | 
						|
        firePropertyChange("columnSelectionAllowed", !c, c);
 | 
						|
        repaint();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>Set the value of the {@link #selectionModel} property.</p>
 | 
						|
   *
 | 
						|
   * <p>Unregister <code>this</code> as a {@link ListSelectionListener}
 | 
						|
   * from previous {@link #selectionModel} and register it with new
 | 
						|
   * parameter <code>s</code>.</p>
 | 
						|
   *
 | 
						|
   * @param s The new value of the selectionModel property
 | 
						|
   */
 | 
						|
  public void setSelectionModel(ListSelectionModel s)
 | 
						|
  {
 | 
						|
    if (s == null)
 | 
						|
      throw new IllegalArgumentException();
 | 
						|
    ListSelectionModel tmp = selectionModel;
 | 
						|
    if (tmp != null)
 | 
						|
      tmp.removeListSelectionListener(this);
 | 
						|
    if (s != null)
 | 
						|
      s.addListSelectionListener(this);
 | 
						|
    selectionModel = s;
 | 
						|
    checkSelection();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the <code>selectionMode</code> property by
 | 
						|
   * delegation to the {@link #selectionModel} field. The same selection
 | 
						|
   * mode is set for row and column selection models.
 | 
						|
   *
 | 
						|
   * @param s The new value of the property
 | 
						|
   */
 | 
						|
  public void setSelectionMode(int s)
 | 
						|
  {
 | 
						|
    selectionModel.setSelectionMode(s);
 | 
						|
    columnModel.getSelectionModel().setSelectionMode(s);
 | 
						|
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>Set the value of the {@link #cellEditor} property.</p>
 | 
						|
   *
 | 
						|
   * <p>Unregister <code>this</code> as a {@link CellEditorListener} from
 | 
						|
   * previous {@link #cellEditor} and register it with new parameter
 | 
						|
   * <code>c</code>.</p>
 | 
						|
   *
 | 
						|
   * @param c The new value of the cellEditor property
 | 
						|
   */
 | 
						|
  public void setCellEditor(TableCellEditor c)
 | 
						|
  {
 | 
						|
    TableCellEditor tmp = cellEditor;
 | 
						|
    if (tmp != null)
 | 
						|
      tmp.removeCellEditorListener(this);
 | 
						|
    if (c != null)
 | 
						|
      c.addCellEditorListener(this);
 | 
						|
    cellEditor = c;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #dragEnabled} property.
 | 
						|
   *
 | 
						|
   * @param d The new value of the dragEnabled property
 | 
						|
   */
 | 
						|
  public void setDragEnabled(boolean d)
 | 
						|
  {
 | 
						|
    dragEnabled = d;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #gridColor} property.
 | 
						|
   *
 | 
						|
   * @param g The new value of the gridColor property
 | 
						|
   */
 | 
						|
  public void setGridColor(Color g)
 | 
						|
  {
 | 
						|
    gridColor = g;
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the <code>intercellSpacing</code> property.
 | 
						|
   *
 | 
						|
   * @param i The new value of the intercellSpacing property
 | 
						|
   */
 | 
						|
  public void setIntercellSpacing(Dimension i)
 | 
						|
  {
 | 
						|
    rowMargin = i.height;
 | 
						|
    columnModel.setColumnMargin(i.width);
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #preferredViewportSize} property.
 | 
						|
   *
 | 
						|
   * @param p The new value of the preferredViewportSize property
 | 
						|
   */
 | 
						|
  public void setPreferredScrollableViewportSize(Dimension p)
 | 
						|
  {
 | 
						|
    preferredViewportSize = p;
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>Set the value of the {@link #selectionBackground} property.</p>
 | 
						|
   *
 | 
						|
   * <p>Fire a PropertyChangeEvent with name {@link
 | 
						|
   * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if
 | 
						|
   * selectionBackground changed.</p>
 | 
						|
   *
 | 
						|
   * @param s The new value of the selectionBackground property
 | 
						|
   */
 | 
						|
  public void setSelectionBackground(Color s)
 | 
						|
  {
 | 
						|
    Color tmp = selectionBackground;
 | 
						|
    selectionBackground = s;
 | 
						|
    if (((tmp == null && s != null)
 | 
						|
         || (s == null && tmp != null)
 | 
						|
         || (tmp != null && s != null && !tmp.equals(s))))
 | 
						|
      firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY, tmp, s);
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>Set the value of the {@link #selectionForeground} property.</p>
 | 
						|
   *
 | 
						|
   * <p>Fire a PropertyChangeEvent with name {@link
 | 
						|
   * #SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if
 | 
						|
   * selectionForeground changed.</p>
 | 
						|
   *
 | 
						|
   * @param s The new value of the selectionForeground property
 | 
						|
   */
 | 
						|
  public void setSelectionForeground(Color s)
 | 
						|
  {
 | 
						|
    Color tmp = selectionForeground;
 | 
						|
    selectionForeground = s;
 | 
						|
    if (((tmp == null && s != null)
 | 
						|
         || (s == null && tmp != null)
 | 
						|
         || (tmp != null && s != null && !tmp.equals(s))))
 | 
						|
      firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY, tmp, s);
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the <code>showGrid</code> property.
 | 
						|
   *
 | 
						|
   * @param s The new value of the showGrid property
 | 
						|
   */
 | 
						|
  public void setShowGrid(boolean s)
 | 
						|
  {
 | 
						|
    setShowVerticalLines(s);
 | 
						|
    setShowHorizontalLines(s);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #showHorizontalLines} property.
 | 
						|
   *
 | 
						|
   * @param s The new value of the showHorizontalLines property
 | 
						|
   */
 | 
						|
  public void setShowHorizontalLines(boolean s)
 | 
						|
  {
 | 
						|
    showHorizontalLines = s;
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #showVerticalLines} property.
 | 
						|
   *
 | 
						|
   * @param s The new value of the showVerticalLines property
 | 
						|
   */
 | 
						|
  public void setShowVerticalLines(boolean s)
 | 
						|
  {
 | 
						|
    showVerticalLines = s;
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the value of the {@link #tableHeader} property.
 | 
						|
   *
 | 
						|
   * @param t The new value of the tableHeader property
 | 
						|
   */
 | 
						|
  public void setTableHeader(JTableHeader t)
 | 
						|
  {
 | 
						|
    if (tableHeader != null)
 | 
						|
      tableHeader.setTable(null);
 | 
						|
    tableHeader = t;
 | 
						|
    if (tableHeader != null)
 | 
						|
      tableHeader.setTable(this);
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  protected void configureEnclosingScrollPane()
 | 
						|
  {
 | 
						|
    JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
 | 
						|
    if (jsp != null && tableHeader != null)
 | 
						|
      {
 | 
						|
        jsp.setColumnHeaderView(tableHeader);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  protected void unconfigureEnclosingScrollPane()
 | 
						|
  {
 | 
						|
    JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
 | 
						|
    if (jsp != null)
 | 
						|
      {
 | 
						|
        jsp.setColumnHeaderView(null);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  public void addNotify()
 | 
						|
  {
 | 
						|
    super.addNotify();
 | 
						|
    configureEnclosingScrollPane();
 | 
						|
  }
 | 
						|
 | 
						|
  public void removeNotify()
 | 
						|
  {
 | 
						|
    super.addNotify();
 | 
						|
    unconfigureEnclosingScrollPane();
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * This distributes the superfluous width in a table evenly on its columns.
 | 
						|
   *
 | 
						|
   * The implementation used here is different to that one described in
 | 
						|
   * the JavaDocs. It is much simpler, and seems to work very well.
 | 
						|
   *
 | 
						|
   * TODO: correctly implement the algorithm described in the JavaDoc
 | 
						|
   */
 | 
						|
  private void distributeSpill(TableColumn[] cols, int spill)
 | 
						|
  {
 | 
						|
    int average = spill / cols.length;
 | 
						|
    for (int i = 0; i < cols.length; i++)
 | 
						|
      {
 | 
						|
        if (cols[i] != null)
 | 
						|
          cols[i].setWidth(cols[i].getPreferredWidth() + average);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * This distributes the superfluous width in a table, setting the width of the
 | 
						|
   * column being resized strictly to its preferred width.
 | 
						|
   */
 | 
						|
  private void distributeSpillResizing(TableColumn[] cols, int spill,
 | 
						|
                                       TableColumn resizeIt)
 | 
						|
  {
 | 
						|
    int average = 0;
 | 
						|
    if (cols.length != 1)
 | 
						|
      average = spill / (cols.length-1);
 | 
						|
    for (int i = 0; i < cols.length; i++)
 | 
						|
      {
 | 
						|
        if (cols[i] != null && !cols[i].equals(resizeIt))
 | 
						|
          cols[i].setWidth(cols[i].getPreferredWidth() + average);
 | 
						|
      }
 | 
						|
    resizeIt.setWidth(resizeIt.getPreferredWidth());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the widths of all columns, taking they preferred widths into
 | 
						|
   * consideration. The excess space, if any, will be distrubuted between
 | 
						|
   * all columns. This method also handles special cases when one of the
 | 
						|
   * collumns is currently being resized.
 | 
						|
   *
 | 
						|
   * @see TableColumn#setPreferredWidth(int)
 | 
						|
   */
 | 
						|
  public void doLayout()
 | 
						|
  {
 | 
						|
    TableColumn resizingColumn = null;
 | 
						|
 | 
						|
    int ncols = columnModel.getColumnCount();
 | 
						|
    if (ncols < 1)
 | 
						|
      return;
 | 
						|
 | 
						|
    int prefSum = 0;
 | 
						|
    int rCol = -1;
 | 
						|
 | 
						|
    if (tableHeader != null)
 | 
						|
      resizingColumn = tableHeader.getResizingColumn();
 | 
						|
 | 
						|
    for (int i = 0; i < ncols; ++i)
 | 
						|
      {
 | 
						|
        TableColumn col = columnModel.getColumn(i);
 | 
						|
        int p = col.getPreferredWidth();
 | 
						|
        prefSum += p;
 | 
						|
        if (resizingColumn == col)
 | 
						|
          rCol = i;
 | 
						|
      }
 | 
						|
 | 
						|
    int spill = getWidth() - prefSum;
 | 
						|
 | 
						|
    if (resizingColumn != null)
 | 
						|
      {
 | 
						|
        TableColumn col;
 | 
						|
        TableColumn [] cols;
 | 
						|
 | 
						|
        switch (getAutoResizeMode())
 | 
						|
          {
 | 
						|
          case AUTO_RESIZE_LAST_COLUMN:
 | 
						|
            col = columnModel.getColumn(ncols-1);
 | 
						|
            col.setWidth(col.getPreferredWidth() + spill);
 | 
						|
            break;
 | 
						|
 | 
						|
          case AUTO_RESIZE_NEXT_COLUMN:
 | 
						|
            col = columnModel.getColumn(ncols-1);
 | 
						|
            col.setWidth(col.getPreferredWidth() + spill);
 | 
						|
            break;
 | 
						|
 | 
						|
          case AUTO_RESIZE_ALL_COLUMNS:
 | 
						|
            cols = new TableColumn[ncols];
 | 
						|
            for (int i = 0; i < ncols; ++i)
 | 
						|
              cols[i] = columnModel.getColumn(i);
 | 
						|
            distributeSpillResizing(cols, spill, resizingColumn);
 | 
						|
            break;
 | 
						|
 | 
						|
          case AUTO_RESIZE_SUBSEQUENT_COLUMNS:
 | 
						|
 | 
						|
            // Subtract the width of the non-resized columns from the spill.
 | 
						|
            int w = 0;
 | 
						|
            int wp = 0;
 | 
						|
            TableColumn column;
 | 
						|
            for (int i = 0; i < rCol; i++)
 | 
						|
              {
 | 
						|
                column = columnModel.getColumn(i);
 | 
						|
                w += column.getWidth();
 | 
						|
                wp+= column.getPreferredWidth();
 | 
						|
              }
 | 
						|
 | 
						|
            // The number of columns right from the column being resized.
 | 
						|
            int n = ncols-rCol-1;
 | 
						|
            if (n>0)
 | 
						|
              {
 | 
						|
                // If there are any columns on the right sied to resize.
 | 
						|
                spill = (getWidth()-w) - (prefSum-wp);
 | 
						|
                int average = spill / n;
 | 
						|
 | 
						|
                 // For all columns right from the column being resized:
 | 
						|
                for (int i = rCol+1; i < ncols; i++)
 | 
						|
                  {
 | 
						|
                    column = columnModel.getColumn(i);
 | 
						|
                    column.setWidth(column.getPreferredWidth() + average);
 | 
						|
                  }
 | 
						|
              }
 | 
						|
            resizingColumn.setWidth(resizingColumn.getPreferredWidth());
 | 
						|
            break;
 | 
						|
 | 
						|
          case AUTO_RESIZE_OFF:
 | 
						|
          default:
 | 
						|
            int prefWidth = resizingColumn.getPreferredWidth();
 | 
						|
            resizingColumn.setWidth(prefWidth);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        TableColumn[] cols = new TableColumn[ncols];
 | 
						|
 | 
						|
        for (int i = 0; i < ncols; ++i)
 | 
						|
          cols[i] = columnModel.getColumn(i);
 | 
						|
 | 
						|
        distributeSpill(cols, spill);
 | 
						|
      }
 | 
						|
 | 
						|
    if (editorComp!=null)
 | 
						|
      moveToCellBeingEdited(editorComp);
 | 
						|
 | 
						|
    int leftBoundary = getLeftResizingBoundary();
 | 
						|
    int width = getWidth() - leftBoundary;
 | 
						|
    repaint(leftBoundary, 0, width, getHeight());
 | 
						|
    if (tableHeader != null)
 | 
						|
      tableHeader.repaint(leftBoundary, 0, width, tableHeader.getHeight());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the left boundary of the rectangle which changes during the column
 | 
						|
   * resizing.
 | 
						|
   */
 | 
						|
  int getLeftResizingBoundary()
 | 
						|
  {
 | 
						|
    if (tableHeader == null || getAutoResizeMode() == AUTO_RESIZE_ALL_COLUMNS)
 | 
						|
      return 0;
 | 
						|
    else
 | 
						|
      {
 | 
						|
        TableColumn resizingColumn = tableHeader.getResizingColumn();
 | 
						|
        if (resizingColumn == null)
 | 
						|
          return 0;
 | 
						|
 | 
						|
        int rc = convertColumnIndexToView(resizingColumn.getModelIndex());
 | 
						|
        int p = 0;
 | 
						|
 | 
						|
        for (int i = 0; i < rc; i++)
 | 
						|
          p += columnModel.getColumn(i).getWidth();
 | 
						|
 | 
						|
        return p;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @deprecated Replaced by <code>doLayout()</code>
 | 
						|
   */
 | 
						|
  public void sizeColumnsToFit(boolean lastColumnOnly)
 | 
						|
  {
 | 
						|
    doLayout();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Obsolete since JDK 1.4. Please use <code>doLayout()</code>.
 | 
						|
   */
 | 
						|
  public void sizeColumnsToFit(int resizingColumn)
 | 
						|
  {
 | 
						|
    doLayout();
 | 
						|
  }
 | 
						|
 | 
						|
  public String getUIClassID()
 | 
						|
  {
 | 
						|
    return "TableUI";
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * This method returns the table's UI delegate.
 | 
						|
   *
 | 
						|
   * @return The table's UI delegate.
 | 
						|
   */
 | 
						|
  public TableUI getUI()
 | 
						|
  {
 | 
						|
    return (TableUI) ui;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * This method sets the table's UI delegate.
 | 
						|
   *
 | 
						|
   * @param ui The table's UI delegate.
 | 
						|
   */
 | 
						|
  public void setUI(TableUI ui)
 | 
						|
  {
 | 
						|
    super.setUI(ui);
 | 
						|
    // The editors and renderers must be recreated because they constructors
 | 
						|
    // may use the look and feel properties.
 | 
						|
    createDefaultEditors();
 | 
						|
    createDefaultRenderers();
 | 
						|
  }
 | 
						|
 | 
						|
  public void updateUI()
 | 
						|
  {
 | 
						|
    setUI((TableUI) UIManager.getUI(this));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the class (datatype) of the column. The cells are rendered and edited
 | 
						|
   * differently, depending from they data type.
 | 
						|
   *
 | 
						|
   * @param column the column (not the model index).
 | 
						|
   *
 | 
						|
   * @return the class, defining data type of that column (String.class for
 | 
						|
   * String, Boolean.class for boolean and so on).
 | 
						|
   */
 | 
						|
  public Class<?> getColumnClass(int column)
 | 
						|
  {
 | 
						|
    return getModel().getColumnClass(convertColumnIndexToModel(column));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the name of the column. If the column has the column identifier set,
 | 
						|
   * the return value is the result of the .toString() method call on that
 | 
						|
   * identifier. If the identifier is not explicitly set, the returned value
 | 
						|
   * is calculated by
 | 
						|
   * {@link javax.swing.table.AbstractTableModel#getColumnName(int)}.
 | 
						|
   *
 | 
						|
   * @param column the column
 | 
						|
   *
 | 
						|
   * @return the name of that column.
 | 
						|
   */
 | 
						|
  public String getColumnName(int column)
 | 
						|
  {
 | 
						|
    int modelColumn = columnModel.getColumn(column).getModelIndex();
 | 
						|
    return dataModel.getColumnName(modelColumn);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the column, currently being edited
 | 
						|
   *
 | 
						|
   * @return the column, currently being edited.
 | 
						|
   */
 | 
						|
  public int getEditingColumn()
 | 
						|
  {
 | 
						|
    return editingColumn;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the column, currently being edited
 | 
						|
   *
 | 
						|
   * @param column the column, currently being edited.
 | 
						|
   */
 | 
						|
  public void setEditingColumn(int column)
 | 
						|
  {
 | 
						|
    editingColumn = column;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the row currently being edited.
 | 
						|
   *
 | 
						|
   * @return the row, currently being edited.
 | 
						|
   */
 | 
						|
  public int getEditingRow()
 | 
						|
  {
 | 
						|
    return editingRow;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the row currently being edited.
 | 
						|
   *
 | 
						|
   * @param row the row, that will be edited
 | 
						|
   */
 | 
						|
  public void setEditingRow(int row)
 | 
						|
  {
 | 
						|
    editingRow = row;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the editor component that is currently editing one of the cells
 | 
						|
   *
 | 
						|
   * @return the editor component or null, if none of the cells is being
 | 
						|
   * edited.
 | 
						|
   */
 | 
						|
  public Component getEditorComponent()
 | 
						|
  {
 | 
						|
    return editorComp;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Check if one of the table cells is currently being edited.
 | 
						|
   *
 | 
						|
   * @return true if there is a cell being edited.
 | 
						|
   */
 | 
						|
  public boolean isEditing()
 | 
						|
  {
 | 
						|
    return editorComp != null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the default editor for the given column class (column data type).
 | 
						|
   * By default, String is handled by text field and Boolean is handled by
 | 
						|
   * the check box.
 | 
						|
   *
 | 
						|
   * @param columnClass the column data type
 | 
						|
   * @param editor the editor that will edit this data type
 | 
						|
   *
 | 
						|
   * @see TableModel#getColumnClass(int)
 | 
						|
   */
 | 
						|
  public void setDefaultEditor(Class<?> columnClass, TableCellEditor editor)
 | 
						|
  {
 | 
						|
    if (editor != null)
 | 
						|
      defaultEditorsByColumnClass.put(columnClass, editor);
 | 
						|
    else
 | 
						|
      defaultEditorsByColumnClass.remove(columnClass);
 | 
						|
  }
 | 
						|
 | 
						|
  public void addColumnSelectionInterval(int index0, int index1)
 | 
						|
  {
 | 
						|
    if ((index0 < 0 || index0 > (getColumnCount()-1)
 | 
						|
         || index1 < 0 || index1 > (getColumnCount()-1)))
 | 
						|
      throw new IllegalArgumentException("Column index out of range.");
 | 
						|
 | 
						|
    getColumnModel().getSelectionModel().addSelectionInterval(index0, index1);
 | 
						|
  }
 | 
						|
 | 
						|
  public void addRowSelectionInterval(int index0, int index1)
 | 
						|
  {
 | 
						|
    if ((index0 < 0 || index0 > (getRowCount()-1)
 | 
						|
         || index1 < 0 || index1 > (getRowCount()-1)))
 | 
						|
      throw new IllegalArgumentException("Row index out of range.");
 | 
						|
 | 
						|
    getSelectionModel().addSelectionInterval(index0, index1);
 | 
						|
  }
 | 
						|
 | 
						|
  public void setColumnSelectionInterval(int index0, int index1)
 | 
						|
  {
 | 
						|
    if ((index0 < 0 || index0 > (getColumnCount()-1)
 | 
						|
         || index1 < 0 || index1 > (getColumnCount()-1)))
 | 
						|
      throw new IllegalArgumentException("Column index out of range.");
 | 
						|
 | 
						|
    getColumnModel().getSelectionModel().setSelectionInterval(index0, index1);
 | 
						|
  }
 | 
						|
 | 
						|
  public void setRowSelectionInterval(int index0, int index1)
 | 
						|
  {
 | 
						|
    if ((index0 < 0 || index0 > (getRowCount()-1)
 | 
						|
         || index1 < 0 || index1 > (getRowCount()-1)))
 | 
						|
      throw new IllegalArgumentException("Row index out of range.");
 | 
						|
 | 
						|
    getSelectionModel().setSelectionInterval(index0, index1);
 | 
						|
  }
 | 
						|
 | 
						|
  public void removeColumnSelectionInterval(int index0, int index1)
 | 
						|
  {
 | 
						|
    if ((index0 < 0 || index0 > (getColumnCount()-1)
 | 
						|
         || index1 < 0 || index1 > (getColumnCount()-1)))
 | 
						|
      throw new IllegalArgumentException("Column index out of range.");
 | 
						|
 | 
						|
    getColumnModel().getSelectionModel().removeSelectionInterval(index0, index1);
 | 
						|
  }
 | 
						|
 | 
						|
  public void removeRowSelectionInterval(int index0, int index1)
 | 
						|
  {
 | 
						|
    if ((index0 < 0 || index0 > (getRowCount()-1)
 | 
						|
         || index1 < 0 || index1 > (getRowCount()-1)))
 | 
						|
      throw new IllegalArgumentException("Row index out of range.");
 | 
						|
 | 
						|
    getSelectionModel().removeSelectionInterval(index0, index1);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Checks if the given column is selected.
 | 
						|
   *
 | 
						|
   * @param column the column
 | 
						|
   *
 | 
						|
   * @return true if the column is selected (as reported by the selection
 | 
						|
   * model, associated with the column model), false otherwise.
 | 
						|
   */
 | 
						|
  public boolean isColumnSelected(int column)
 | 
						|
  {
 | 
						|
    return getColumnModel().getSelectionModel().isSelectedIndex(column);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Checks if the given row is selected.
 | 
						|
   *
 | 
						|
   * @param row the row
 | 
						|
   *
 | 
						|
   * @return true if the row is selected (as reported by the selection model),
 | 
						|
   * false otherwise.
 | 
						|
   */
 | 
						|
  public boolean isRowSelected(int row)
 | 
						|
  {
 | 
						|
    return getSelectionModel().isSelectedIndex(row);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Checks if the given cell is selected. The cell is selected if both
 | 
						|
   * the cell row and the cell column are selected.
 | 
						|
   *
 | 
						|
   * @param row the cell row
 | 
						|
   * @param column the cell column
 | 
						|
   *
 | 
						|
   * @return true if the cell is selected, false otherwise
 | 
						|
   */
 | 
						|
  public boolean isCellSelected(int row, int column)
 | 
						|
  {
 | 
						|
    return isRowSelected(row) && isColumnSelected(column);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Select all table.
 | 
						|
   */
 | 
						|
  public void selectAll()
 | 
						|
  {
 | 
						|
    // The table is empty - nothing to do!
 | 
						|
    if (getRowCount() == 0 || getColumnCount() == 0)
 | 
						|
      return;
 | 
						|
 | 
						|
    // rowLead and colLead store the current lead selection indices
 | 
						|
    int rowLead = selectionModel.getLeadSelectionIndex();
 | 
						|
    int colLead = getColumnModel().getSelectionModel().getLeadSelectionIndex();
 | 
						|
    // the following calls to setSelectionInterval change the lead selection
 | 
						|
    // indices
 | 
						|
    setColumnSelectionInterval(0, getColumnCount() - 1);
 | 
						|
    setRowSelectionInterval(0, getRowCount() - 1);
 | 
						|
    // the following addSelectionInterval calls restore the lead selection
 | 
						|
    // indices to their previous values
 | 
						|
    addColumnSelectionInterval(colLead,colLead);
 | 
						|
    addRowSelectionInterval(rowLead, rowLead);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the cell value at the given position.
 | 
						|
   *
 | 
						|
   * @param row the row to get the value
 | 
						|
   * @param column the actual column number (not the model index)
 | 
						|
   * to get the value.
 | 
						|
   *
 | 
						|
   * @return the cell value, as returned by model.
 | 
						|
   */
 | 
						|
  public Object getValueAt(int row, int column)
 | 
						|
  {
 | 
						|
    return dataModel.getValueAt(row, convertColumnIndexToModel(column));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set value for the cell at the given position. The modified cell is
 | 
						|
   * repainted.
 | 
						|
   *
 | 
						|
   * @param value the value to set
 | 
						|
   * @param row the row of the cell being modified
 | 
						|
   * @param column the column of the cell being modified
 | 
						|
   */
 | 
						|
  public void setValueAt(Object value, int row, int column)
 | 
						|
  {
 | 
						|
    dataModel.setValueAt(value, row, convertColumnIndexToModel(column));
 | 
						|
 | 
						|
    repaint(getCellRect(row, column, true));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get table column with the given identified.
 | 
						|
   *
 | 
						|
   * @param identifier the column identifier
 | 
						|
   *
 | 
						|
   * @return the table column with this identifier
 | 
						|
   *
 | 
						|
   * @throws IllegalArgumentException if <code>identifier</code> is
 | 
						|
   *         <code>null</code> or there is no column with that identifier.
 | 
						|
   *
 | 
						|
   * @see TableColumn#setIdentifier(Object)
 | 
						|
   */
 | 
						|
  public TableColumn getColumn(Object identifier)
 | 
						|
  {
 | 
						|
    return columnModel.getColumn(columnModel.getColumnIndex(identifier));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>true</code> if the specified cell is editable, and
 | 
						|
   * <code>false</code> otherwise.
 | 
						|
   *
 | 
						|
   * @param row  the row index.
 | 
						|
   * @param column  the column index.
 | 
						|
   *
 | 
						|
   * @return true if the cell is editable, false otherwise.
 | 
						|
   */
 | 
						|
  public boolean isCellEditable(int row, int column)
 | 
						|
  {
 | 
						|
    return dataModel.isCellEditable(row, convertColumnIndexToModel(column));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Clears any existing columns from the <code>JTable</code>'s
 | 
						|
   * {@link TableColumnModel} and creates new columns to match the values in
 | 
						|
   * the data ({@link TableModel}) used by the table.
 | 
						|
   *
 | 
						|
   * @see #setAutoCreateColumnsFromModel(boolean)
 | 
						|
   */
 | 
						|
  public void createDefaultColumnsFromModel()
 | 
						|
  {
 | 
						|
    assert columnModel != null : "The columnModel must not be null.";
 | 
						|
 | 
						|
    // remove existing columns
 | 
						|
    int columnIndex = columnModel.getColumnCount() - 1;
 | 
						|
    while (columnIndex >= 0)
 | 
						|
    {
 | 
						|
      columnModel.removeColumn(columnModel.getColumn(columnIndex));
 | 
						|
      columnIndex--;
 | 
						|
    }
 | 
						|
 | 
						|
    // add new columns to match the TableModel
 | 
						|
    int columnCount = dataModel.getColumnCount();
 | 
						|
    for (int c = 0; c < columnCount; c++)
 | 
						|
    {
 | 
						|
      TableColumn column = new TableColumn(c);
 | 
						|
      column.setIdentifier(dataModel.getColumnName(c));
 | 
						|
      column.setHeaderValue(dataModel.getColumnName(c));
 | 
						|
      columnModel.addColumn(column);
 | 
						|
      column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  public void changeSelection (int rowIndex, int columnIndex, boolean toggle, boolean extend)
 | 
						|
  {
 | 
						|
    if (toggle && extend)
 | 
						|
      {
 | 
						|
        // Leave the selection state as is, but move the anchor
 | 
						|
        //   index to the specified location
 | 
						|
        selectionModel.setAnchorSelectionIndex(rowIndex);
 | 
						|
        getColumnModel().getSelectionModel().setAnchorSelectionIndex(columnIndex);
 | 
						|
      }
 | 
						|
    else if (toggle)
 | 
						|
      {
 | 
						|
        // Toggle the state of the specified cell
 | 
						|
        if (isCellSelected(rowIndex,columnIndex))
 | 
						|
          {
 | 
						|
            selectionModel.removeSelectionInterval(rowIndex,rowIndex);
 | 
						|
            getColumnModel().getSelectionModel().removeSelectionInterval(columnIndex,columnIndex);
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            selectionModel.addSelectionInterval(rowIndex,rowIndex);
 | 
						|
            getColumnModel().getSelectionModel().addSelectionInterval(columnIndex,columnIndex);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else if (extend)
 | 
						|
      {
 | 
						|
        // Extend the previous selection from the anchor to the
 | 
						|
        // specified cell, clearing all other selections
 | 
						|
        selectionModel.setLeadSelectionIndex(rowIndex);
 | 
						|
        getColumnModel().getSelectionModel().setLeadSelectionIndex(columnIndex);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        // Clear the previous selection and ensure the new cell
 | 
						|
        // is selected
 | 
						|
         selectionModel.clearSelection();
 | 
						|
        selectionModel.setSelectionInterval(rowIndex,rowIndex);
 | 
						|
        getColumnModel().getSelectionModel().clearSelection();
 | 
						|
        getColumnModel().getSelectionModel().setSelectionInterval(columnIndex, columnIndex);
 | 
						|
 | 
						|
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Programmatically starts editing the specified cell.
 | 
						|
   *
 | 
						|
   * @param row the row of the cell to edit.
 | 
						|
   * @param column the column of the cell to edit.
 | 
						|
   */
 | 
						|
  public boolean editCellAt(int row, int column)
 | 
						|
  {
 | 
						|
    // Complete the previous editing session, if still active.
 | 
						|
    if (isEditing())
 | 
						|
      editingStopped(new ChangeEvent("editingStopped"));
 | 
						|
 | 
						|
    TableCellEditor editor = getCellEditor(row, column);
 | 
						|
 | 
						|
    // The boolean values are inverted by the single click without the
 | 
						|
    // real editing session.
 | 
						|
    if (editor == booleanInvertingEditor && isCellEditable(row, column))
 | 
						|
      {
 | 
						|
        if (Boolean.TRUE.equals(getValueAt(row, column)))
 | 
						|
          setValueAt(Boolean.FALSE, row, column);
 | 
						|
        else
 | 
						|
          setValueAt(Boolean.TRUE, row, column);
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        editingRow = row;
 | 
						|
        editingColumn = column;
 | 
						|
 | 
						|
        setCellEditor(editor);
 | 
						|
        editorComp = prepareEditor(cellEditor, row, column);
 | 
						|
 | 
						|
        // Remove the previous editor components, if present. Only one
 | 
						|
        // editor component at time is allowed in the table.
 | 
						|
        removeAll();
 | 
						|
        add(editorComp);
 | 
						|
        moveToCellBeingEdited(editorComp);
 | 
						|
        scrollRectToVisible(editorComp.getBounds());
 | 
						|
        editorComp.requestFocusInWindow();
 | 
						|
 | 
						|
        // Deliver the should select event.
 | 
						|
        return editor.shouldSelectCell(null);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Move the given component under the cell being edited.
 | 
						|
   * The table must be in the editing mode.
 | 
						|
   *
 | 
						|
   * @param component the component to move.
 | 
						|
   */
 | 
						|
  private void moveToCellBeingEdited(Component component)
 | 
						|
  {
 | 
						|
     Rectangle r = getCellRect(editingRow, editingColumn, true);
 | 
						|
     // Adjust bounding box of the editing component, so that it lies
 | 
						|
     // 'above' the grid on all edges, not only right and bottom.
 | 
						|
     // The table grid is painted only at the right and bottom edge of a cell.
 | 
						|
     r.x -= 1;
 | 
						|
     r.y -= 1;
 | 
						|
     r.width += 1;
 | 
						|
     r.height += 1;
 | 
						|
     component.setBounds(r);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Programmatically starts editing the specified cell.
 | 
						|
   *
 | 
						|
   * @param row the row of the cell to edit.
 | 
						|
   * @param column the column of the cell to edit.
 | 
						|
   */
 | 
						|
  public boolean editCellAt (int row, int column, EventObject e)
 | 
						|
  {
 | 
						|
    return editCellAt(row, column);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Discards the editor object.
 | 
						|
   */
 | 
						|
  public void removeEditor()
 | 
						|
  {
 | 
						|
    editingStopped(new ChangeEvent(this));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Prepares the editor by querying for the value and selection state of the
 | 
						|
   * cell at (row, column).
 | 
						|
   *
 | 
						|
   * @param editor the TableCellEditor to set up
 | 
						|
   * @param row the row of the cell to edit
 | 
						|
   * @param column the column of the cell to edit
 | 
						|
   * @return the Component being edited
 | 
						|
   */
 | 
						|
  public Component prepareEditor (TableCellEditor editor, int row, int column)
 | 
						|
  {
 | 
						|
    return editor.getTableCellEditorComponent
 | 
						|
      (this, getValueAt(row, column), isCellSelected(row, column), row, column);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * This revalidates the <code>JTable</code> and queues a repaint.
 | 
						|
   */
 | 
						|
  protected void resizeAndRepaint()
 | 
						|
  {
 | 
						|
    revalidate();
 | 
						|
    repaint();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Sets whether cell editors of this table should receive keyboard focus
 | 
						|
   * when the editor is activated by a keystroke. The default setting is
 | 
						|
   * <code>false</code> which means that the table should keep the keyboard
 | 
						|
   * focus until the cell is selected by a mouse click.
 | 
						|
   *
 | 
						|
   * @param value the value to set
 | 
						|
   *
 | 
						|
   * @since 1.4
 | 
						|
   */
 | 
						|
  public void setSurrendersFocusOnKeystroke(boolean value)
 | 
						|
  {
 | 
						|
    // TODO: Implement functionality of this property (in UI impl).
 | 
						|
    surrendersFocusOnKeystroke = value;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns whether cell editors of this table should receive keyboard focus
 | 
						|
   * when the editor is activated by a keystroke. The default setting is
 | 
						|
   * <code>false</code> which means that the table should keep the keyboard
 | 
						|
   * focus until the cell is selected by a mouse click.
 | 
						|
   *
 | 
						|
   * @return whether cell editors of this table should receive keyboard focus
 | 
						|
   *         when the editor is activated by a keystroke
 | 
						|
   *
 | 
						|
   * @since 1.4
 | 
						|
   */
 | 
						|
  public boolean getSurrendersFocusOnKeystroke()
 | 
						|
  {
 | 
						|
    // TODO: Implement functionality of this property (in UI impl).
 | 
						|
    return surrendersFocusOnKeystroke;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Helper method for
 | 
						|
   * {@link LookAndFeel#installProperty(JComponent, String, Object)}.
 | 
						|
   *
 | 
						|
   * @param propertyName the name of the property
 | 
						|
   * @param value the value of the property
 | 
						|
   *
 | 
						|
   * @throws IllegalArgumentException if the specified property cannot be set
 | 
						|
   *         by this method
 | 
						|
   * @throws ClassCastException if the property value does not match the
 | 
						|
   *         property type
 | 
						|
   * @throws NullPointerException if <code>c</code> or
 | 
						|
   *         <code>propertyValue</code> is <code>null</code>
 | 
						|
   */
 | 
						|
  void setUIProperty(String propertyName, Object value)
 | 
						|
  {
 | 
						|
    if (propertyName.equals("rowHeight"))
 | 
						|
      {
 | 
						|
        if (! clientRowHeightSet)
 | 
						|
          {
 | 
						|
            setRowHeight(((Integer) value).intValue());
 | 
						|
            clientRowHeightSet = false;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        super.setUIProperty(propertyName, value);
 | 
						|
      }
 | 
						|
  }
 | 
						|
}
 |