Source for javax.swing.JTable

   1: /* JTable.java -- 
   2:    Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing;
  40: 
  41: import java.awt.Color;
  42: import java.awt.Component;
  43: import java.awt.Dimension;
  44: import java.awt.Point;
  45: import java.awt.Rectangle;
  46: import java.awt.event.ActionEvent;
  47: import java.awt.event.ActionListener;
  48: import java.awt.event.KeyAdapter;
  49: import java.awt.event.KeyEvent;
  50: import java.text.DateFormat;
  51: import java.text.NumberFormat;
  52: import java.util.Date;
  53: import java.util.EventObject;
  54: import java.util.Hashtable;
  55: import java.util.Vector;
  56: 
  57: import javax.accessibility.Accessible;
  58: import javax.accessibility.AccessibleContext;
  59: import javax.swing.event.CellEditorListener;
  60: import javax.swing.event.ChangeEvent;
  61: import javax.swing.event.ListSelectionEvent;
  62: import javax.swing.event.ListSelectionListener;
  63: import javax.swing.event.TableColumnModelEvent;
  64: import javax.swing.event.TableColumnModelListener;
  65: import javax.swing.event.TableModelEvent;
  66: import javax.swing.event.TableModelListener;
  67: import javax.swing.plaf.TableUI;
  68: import javax.swing.table.DefaultTableCellRenderer;
  69: import javax.swing.table.DefaultTableColumnModel;
  70: import javax.swing.table.DefaultTableModel;
  71: import javax.swing.table.JTableHeader;
  72: import javax.swing.table.TableCellEditor;
  73: import javax.swing.table.TableCellRenderer;
  74: import javax.swing.table.TableColumn;
  75: import javax.swing.table.TableColumnModel;
  76: import javax.swing.table.TableModel;
  77: import javax.swing.text.Caret;
  78: 
  79: public class JTable extends JComponent
  80:   implements TableModelListener, Scrollable, TableColumnModelListener,
  81:              ListSelectionListener, CellEditorListener, Accessible
  82: {
  83: 
  84:   /**
  85:    * A cell renderer for boolean values.
  86:    */
  87:   private class BooleanCellRenderer
  88:     extends DefaultTableCellRenderer
  89:   {
  90: 
  91:     /**
  92:      * The CheckBox that is used for rendering.
  93:      */
  94:     private JCheckBox checkBox = new JCheckBox();
  95: 
  96:     /**
  97:      * Returns the component that is used for rendering the value.
  98:      *
  99:      * @param table the JTable
 100:      * @param value the value of the object
 101:      * @param isSelected is the cell selected?
 102:      * @param hasFocus has the cell the focus?
 103:      * @param row the row to render
 104:      * @param column the cell to render
 105:      * 
 106:      * @return this component (the default table cell renderer)
 107:      */
 108:     public Component getTableCellRendererComponent(JTable table, Object value,
 109:                                                    boolean isSelected,
 110:                                                    boolean hasFocus, int row,
 111:                                                    int column)
 112:     {
 113:       Boolean boolValue = (Boolean) value;
 114:       checkBox.setSelected(boolValue.booleanValue());
 115:       return checkBox;
 116:     }
 117:   }
 118: 
 119:   /**
 120:    * A cell renderer for Date values.
 121:    */
 122:   private class DateCellRenderer
 123:     extends DefaultTableCellRenderer
 124:   {
 125:     /**
 126:      * Returns the component that is used for rendering the value.
 127:      *
 128:      * @param table the JTable
 129:      * @param value the value of the object
 130:      * @param isSelected is the cell selected?
 131:      * @param hasFocus has the cell the focus?
 132:      * @param row the row to render
 133:      * @param column the cell to render
 134:      * 
 135:      * @return this component (the default table cell renderer)
 136:      */
 137:     public Component getTableCellRendererComponent(JTable table, Object value,
 138:                                                    boolean isSelected,
 139:                                                    boolean hasFocus, int row,
 140:                                                    int column)
 141:     {
 142:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
 143:                                           row, column);
 144:       if (value instanceof Date)
 145:         {
 146:           Date dateValue = (Date) value;
 147:           DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
 148:           setText(df.format(dateValue));
 149:         }
 150:       return this;
 151:     }
 152:   }
 153: 
 154:   /**
 155:    * A cell renderer for Double values.
 156:    */
 157:   private class DoubleCellRenderer
 158:     extends DefaultTableCellRenderer
 159:   {
 160:     /**
 161:      * Creates a new instance of NumberCellRenderer.
 162:      */
 163:     public DoubleCellRenderer()
 164:     {
 165:       setHorizontalAlignment(JLabel.RIGHT);
 166:     }
 167: 
 168:     /**
 169:      * Returns the component that is used for rendering the value.
 170:      *
 171:      * @param table the JTable
 172:      * @param value the value of the object
 173:      * @param isSelected is the cell selected?
 174:      * @param hasFocus has the cell the focus?
 175:      * @param row the row to render
 176:      * @param column the cell to render
 177:      * 
 178:      * @return this component (the default table cell renderer)
 179:      */
 180:     public Component getTableCellRendererComponent(JTable table, Object value,
 181:                                                    boolean isSelected,
 182:                                                    boolean hasFocus, int row,
 183:                                                    int column)
 184:     {
 185:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
 186:                                           row, column);
 187:       if (value instanceof Double)
 188:         {
 189:           Double doubleValue = (Double) value;
 190:           NumberFormat nf = NumberFormat.getInstance();
 191:           setText(nf.format(doubleValue.doubleValue()));
 192:         }
 193:       return this;
 194:     }
 195:   }
 196: 
 197:   /**
 198:    * A cell renderer for Float values.
 199:    */
 200:   private class FloatCellRenderer
 201:     extends DefaultTableCellRenderer
 202:   {
 203:     /**
 204:      * Creates a new instance of NumberCellRenderer.
 205:      */
 206:     public FloatCellRenderer()
 207:     {
 208:       setHorizontalAlignment(JLabel.RIGHT);
 209:     }
 210: 
 211:     /**
 212:      * Returns the component that is used for rendering the value.
 213:      *
 214:      * @param table the JTable
 215:      * @param value the value of the object
 216:      * @param isSelected is the cell selected?
 217:      * @param hasFocus has the cell the focus?
 218:      * @param row the row to render
 219:      * @param column the cell to render
 220:      * 
 221:      * @return this component (the default table cell renderer)
 222:      */
 223:     public Component getTableCellRendererComponent(JTable table, Object value,
 224:                                                    boolean isSelected,
 225:                                                    boolean hasFocus, int row,
 226:                                                    int column)
 227:     {
 228:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
 229:                                           row, column);
 230:       if (value instanceof Float)
 231:         {
 232:           Float floatValue = (Float) value;
 233:           NumberFormat nf = NumberFormat.getInstance();
 234:           setText(nf.format(floatValue.floatValue()));
 235:         }
 236:       return this;
 237:     }
 238:   }
 239: 
 240:   /**
 241:    * A cell renderer for Number values.
 242:    */
 243:   private class NumberCellRenderer
 244:     extends DefaultTableCellRenderer
 245:   {
 246:     /**
 247:      * Creates a new instance of NumberCellRenderer.
 248:      */
 249:     public NumberCellRenderer()
 250:     {
 251:       setHorizontalAlignment(JLabel.RIGHT);
 252:     }
 253:   }
 254: 
 255:   /**
 256:    * A cell renderer for Icon values.
 257:    */
 258:   private class IconCellRenderer
 259:     extends DefaultTableCellRenderer
 260:   {
 261:     /**
 262:      * Returns the component that is used for rendering the value.
 263:      *
 264:      * @param table the JTable
 265:      * @param value the value of the object
 266:      * @param isSelected is the cell selected?
 267:      * @param hasFocus has the cell the focus?
 268:      * @param row the row to render
 269:      * @param column the cell to render
 270:      * 
 271:      * @return this component (the default table cell renderer)
 272:      */
 273:     public Component getTableCellRendererComponent(JTable table, Object value,
 274:                                                    boolean isSelected,
 275:                                                    boolean hasFocus, int row,
 276:                                                    int column)
 277:     {
 278:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
 279:                                           row, column);
 280:       if (value instanceof Icon)
 281:         {
 282:           Icon iconValue = (Icon) value;
 283:           setIcon(iconValue);
 284:         }
 285:       return this;
 286:     }
 287:   }
 288: 
 289:   private static final long serialVersionUID = 3876025080382781659L;
 290: 
 291: 
 292:   /**
 293:    * When resizing columns, do not automatically change any columns. In this
 294:    * case the table should be enclosed in a {@link JScrollPane} in order to
 295:    * accomodate cases in which the table size exceeds its visible area.
 296:    */
 297:   public static final int AUTO_RESIZE_OFF = 0;
 298: 
 299:   /**
 300:    * When resizing column <code>i</code>, automatically change only the
 301:    * single column <code>i+1</code> to provide or absorb excess space
 302:    * requirements.
 303:    */
 304:   public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
 305: 
 306:   /**
 307:    * When resizing column <code>i</code> in a table of <code>n</code>
 308:    * columns, automatically change all columns in the range <code>[i+1,
 309:    * n)</code>, uniformly, to provide or absorb excess space requirements.
 310:    */
 311:   public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
 312:   
 313:   /**
 314:    * When resizing column <code>i</code> in a table of <code>n</code>
 315:    * columns, automatically change all columns in the range <code>[0,
 316:    * n)</code> (with the exception of column i) uniformly, to provide or
 317:    * absorb excess space requirements.
 318:    */
 319:   public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
 320: 
 321:   /**
 322:    * When resizing column <code>i</code> in a table of <code>n</code>
 323:    * columns, automatically change column <code>n-1</code> (the last column
 324:    * in the table) to provide or absorb excess space requirements.
 325:    */
 326:   public static final int AUTO_RESIZE_LAST_COLUMN = 3;
 327: 
 328: 
 329:   /**
 330:    * A table mapping {@link java.lang.Class} objects to 
 331:    * {@link TableCellEditor} objects. This table is consulted by the 
 332:    * FIXME
 333:    */
 334:   protected Hashtable defaultEditorsByColumnClass;
 335: 
 336:   /**
 337:    * A table mapping {@link java.lang.Class} objects to 
 338:    * {@link TableCellEditor} objects. This table is consulted by the 
 339:    * FIXME
 340:    */
 341:   protected Hashtable defaultRenderersByColumnClass;
 342: 
 343:   /**
 344:    * The column that is edited, -1 if the table is not edited currently.
 345:    */
 346:   protected int editingColumn;
 347: 
 348:   /**
 349:    * The row that is edited, -1 if the table is not edited currently.
 350:    */
 351:   protected int editingRow;
 352: 
 353:   /**
 354:    * The component that is used for editing.
 355:    * <code>null</code> if the table is not editing currently.
 356:    *
 357:    */
 358:   protected transient Component editorComp;
 359: 
 360: 
 361:   /**
 362:    * Whether or not the table should automatically compute a matching
 363:    * {@link TableColumnModel} and assign it to the {@link #columnModel}
 364:    * property when the {@link #dataModel} property is changed. 
 365:    *
 366:    * @see #setModel(TableModel)
 367:    * @see #createColumnsFromModel()
 368:    * @see #setColumnModel(TableColumnModel)
 369:    * @see #setAutoCreateColumnsFromModel(boolean)
 370:    * @see #getAutoCreateColumnsFromModel()
 371:    */
 372:   protected boolean autoCreateColumnsFromModel;
 373: 
 374:   /**
 375:    * A numeric code specifying the resizing behavior of the table. Must be
 376:    * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link
 377:    * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link
 378:    * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}.
 379:    * 
 380:    * @see #doLayout()
 381:    * @see #setAutoResizeMode(int)
 382:    * @see #getAutoResizeMode()
 383:    */
 384:   protected int autoResizeMode;
 385: 
 386:   /**
 387:    * The height in pixels of any row of the table. All rows in a table are
 388:    * of uniform height. This differs from column width, which varies on a
 389:    * per-column basis, and is stored in the individual columns of the
 390:    * {@link #columnModel}.
 391:    * 
 392:    * @see #getRowHeight()
 393:    * @see #setRowHeight(int)
 394:    * @see TableColumn#getWidth()
 395:    * @see TableColumn#setWidth(int)
 396:    */
 397:   protected int rowHeight;
 398: 
 399:   /**
 400:    * The height in pixels of the gap left between any two rows of the table. 
 401:    * 
 402:    * @see #setRowMargin(int)
 403:    * @see #getRowHeight()
 404:    * @see #getIntercellSpacing()
 405:    * @see #setIntercellSpacing(Dimension)
 406:    * @see TableColumnModel#getColumnMargin()
 407:    * @see TableColumnModel#setColumnMargin(int)
 408:    */
 409:   protected int rowMargin;
 410: 
 411:   /**
 412:    * Whether or not the table should allow row selection. If the table
 413:    * allows both row <em>and</em> column selection, it is said to allow
 414:    * "cell selection". Previous versions of the JDK supported cell
 415:    * selection as an independent concept, but it is now represented solely
 416:    * in terms of simultaneous row and column selection.
 417:    *
 418:    * @see TableColumnModel#getColumnSelectionAllowed()
 419:    * @see #setRowSelectionAllowed(boolean)
 420:    * @see #getRowSelectionAllowed()
 421:    * @see #getCellSelectionEnabled()
 422:    * @see #setCellSelectionEnabled(boolean)
 423:    */
 424:   protected boolean rowSelectionAllowed;
 425: 
 426:   /**
 427:    * @deprecated Use {@link #rowSelectionAllowed}, {@link 
 428:    * #getColumnSelectionAllowed}, or the combined methods {@link
 429:    * #getCellSelectionEnabled} and {@link #setCellSelectionEnabled(boolean)}.
 430:    */
 431:   protected boolean cellSelectionEnabled;
 432:   
 433:   /**
 434:    * The model for data stored in the table. Confusingly, the published API
 435:    * requires that this field be called <code>dataModel</code>, despite its
 436:    * property name. The table listens to its model as a {@link
 437:    * TableModelListener}.
 438:    *
 439:    * @see #tableChanged(TableModelEvent)
 440:    * @see TableModel#addTableModelListener(TableModelListener)
 441:    */
 442:   protected TableModel dataModel;
 443: 
 444:   /**
 445:    * <p>A model of various aspects of the columns of the table, <em>not
 446:    * including</em> the data stored in them. The {@link TableColumnModel}
 447:    * is principally concerned with holding a set of {@link TableColumn}
 448:    * objects, each of which describes the display parameters of a column
 449:    * and the numeric index of the column from the data model which the
 450:    * column is presenting.</p>
 451:    *
 452:    * <p>The TableColumnModel also contains a {@link ListSelectionModel} which
 453:    * indicates which columns are currently selected. This selection model
 454:    * works in combination with the {@link #selectionModel} of the table
 455:    * itself to specify a <em>table selection</em>: a combination of row and
 456:    * column selections.</p>
 457:    *
 458:    * <p>Most application programmers do not need to work with this property
 459:    * at all: setting {@link #autoCreateColumnsFromModel} will construct the
 460:    * columnModel automatically, and the table acts as a facade for most of
 461:    * the interesting properties of the columnModel anyways.</p>
 462:    * 
 463:    * @see #setColumnModel(TableColumnModel)
 464:    * @see #getColumnModel()
 465:    */
 466:   protected TableColumnModel columnModel;
 467: 
 468:   /**
 469:    * A model of the rows of this table which are currently selected. This
 470:    * model is used in combination with the column selection model held as a
 471:    * member of the {@link #columnModel} property, to represent the rows and
 472:    * columns (or both: cells) of the table which are currently selected.
 473:    *
 474:    * @see #rowSelectionAllowed
 475:    * @see #setSelectionModel(ListSelectionModel)
 476:    * @see #getSelectionModel()
 477:    * @see TableColumnModel#getSelectionModel()
 478:    * @see ListSelectionModel#addListSelectionListener(ListSelectionListener)   
 479:    */
 480:   protected ListSelectionModel selectionModel;
 481: 
 482:   /**
 483:    * The accessibleContext property.
 484:    */
 485:   protected AccessibleContext accessibleContext;
 486: 
 487:   /**
 488:    * The current cell editor. 
 489:    */
 490:   protected TableCellEditor cellEditor;
 491: 
 492:   /**
 493:    * Whether or not drag-and-drop is enabled on this table.
 494:    *
 495:    * @see #setDragEnabled()
 496:    * @see #getDragEnabled()
 497:    */
 498:   private boolean dragEnabled;
 499: 
 500:   /**
 501:    * The color to paint the grid lines of the table, when either {@link
 502:    * #showHorizontalLines} or {@link #showVerticalLines} is set.
 503:    *
 504:    * @see #setGridColor(Color)
 505:    * @see #getGridColor()
 506:    */
 507:   protected Color gridColor;
 508: 
 509:   /**
 510:    * The size this table would prefer its viewport assume, if it is
 511:    * contained in a {@link JScrollPane}.
 512:    *
 513:    * @see #setPreferredScrollableViewportSize(Dimension)
 514:    * @see #getPreferredScrollableViewportSize()
 515:    */
 516:   protected Dimension preferredViewportSize;
 517: 
 518:   /**
 519:    * The color to paint the background of selected cells. Fires a property
 520:    * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY}
 521:    * when its value changes.
 522:    *
 523:    * @see #setSelectionBackground(Color)
 524:    * @see #getSelectionBackground()
 525:    */
 526:   protected Color selectionBackground;
 527: 
 528:   /**
 529:    * The name carried in property change events when the {@link
 530:    * #selectionBackground} property changes.
 531:    */
 532:   private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY = "selectionBackground";
 533: 
 534:   /**
 535:    * The color to paint the foreground of selected cells. Fires a property
 536:    * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY}
 537:    * when its value changes.
 538:    *
 539:    * @see #setSelectionForeground(Color)
 540:    * @see #getSelectionForeground()
 541:    */
 542:   protected Color selectionForeground;
 543: 
 544:   /**
 545:    * The name carried in property change events when the
 546:    * {@link #selectionForeground} property changes.
 547:    */
 548:   private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY = "selectionForeground";
 549: 
 550:   /**
 551:    * The showHorizontalLines property.
 552:    */
 553:   protected boolean showHorizontalLines;
 554: 
 555:   /**
 556:    * The showVerticalLines property.
 557:    */
 558:   protected boolean showVerticalLines;
 559: 
 560:   /**
 561:    * The tableHeader property.
 562:    */
 563:   protected JTableHeader tableHeader;
 564: 
 565:   /**
 566:    * The row of the cell being edited.
 567:    */
 568:   int rowBeingEdited = -1;
 569: 
 570:   /**
 571:    * The column of the cell being edited.
 572:    */
 573:   int columnBeingEdited = -1;
 574: 
 575:   /**
 576:    * The action listener for the editor's Timer.
 577:    */
 578:   Timer editorTimer = new EditorUpdateTimer();
 579: 
 580:   /**
 581:    * Stores the old value of a cell before it was edited, in case
 582:    * editing is cancelled
 583:    */
 584:   Object oldCellValue;
 585: 
 586:   /**
 587:    * Creates a new <code>JTable</code> instance.
 588:    */
 589:   public JTable ()
 590:   {
 591:     this(null, null, null);
 592:   }
 593: 
 594:   /**
 595:    * Creates a new <code>JTable</code> instance.
 596:    *
 597:    * @param numRows an <code>int</code> value
 598:    * @param numColumns an <code>int</code> value
 599:    */
 600:   public JTable (int numRows, int numColumns)
 601:   {
 602:     this(new DefaultTableModel(numRows, numColumns));
 603:   }
 604: 
 605:   /**
 606:    * Creates a new <code>JTable</code> instance.
 607:    *
 608:    * @param data an <code>Object[][]</code> value
 609:    * @param columnNames an <code>Object[]</code> value
 610:    */
 611:   public JTable(Object[][] data, Object[] columnNames)
 612:   {
 613:     this(new DefaultTableModel(data, columnNames));
 614:   }
 615: 
 616:   /**
 617:    * Creates a new <code>JTable</code> instance.
 618:    *
 619:    * @param dm a <code>TableModel</code> value
 620:    */
 621:   public JTable (TableModel dm)
 622:   {
 623:     this(dm, null, null);
 624:   }
 625: 
 626:   /**
 627:    * Creates a new <code>JTable</code> instance.
 628:    *
 629:    * @param dm a <code>TableModel</code> value
 630:    * @param cm a <code>TableColumnModel</code> value
 631:    */
 632:   public JTable (TableModel dm, TableColumnModel cm)
 633:   {
 634:     this(dm, cm, null);
 635:   }
 636: 
 637:   /**
 638:    * Creates a new <code>JTable</code> instance.
 639:    *
 640:    * @param dm a <code>TableModel</code> value
 641:    * @param cm a <code>TableColumnModel</code> value
 642:    * @param sm a <code>ListSelectionModel</code> value
 643:    */
 644:   public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm)
 645:   {
 646:     setModel(dm == null ? createDefaultDataModel() : dm);
 647:     setSelectionModel(sm == null ? createDefaultSelectionModel() : sm);
 648:     
 649:     this.columnModel = cm;
 650:     initializeLocalVars();
 651:     // The next two lines are for compliance with the JDK which starts
 652:     // the JLists associated with a JTable  with both lead selection 
 653:     // indices at 0, rather than -1 as in regular JLists
 654:     selectionModel.setLeadSelectionIndex(0);
 655:     columnModel.getSelectionModel().setLeadSelectionIndex(0);
 656:     updateUI();
 657:   }    
 658: 
 659:   protected void initializeLocalVars()
 660:   {
 661:     setTableHeader(createDefaultTableHeader());
 662:     this.autoCreateColumnsFromModel = false;
 663:     if (columnModel == null)
 664:       {
 665:         this.autoCreateColumnsFromModel = true;
 666:         createColumnsFromModel();
 667:       }
 668:     this.columnModel.addColumnModelListener(this);
 669:     
 670:     this.defaultRenderersByColumnClass = new Hashtable();
 671:     createDefaultRenderers();
 672: 
 673:     this.defaultEditorsByColumnClass = new Hashtable();
 674:     createDefaultEditors();
 675: 
 676:     this.autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS;
 677:     this.rowHeight = 16;
 678:     this.rowMargin = 1;
 679:     this.rowSelectionAllowed = true;
 680:     // this.accessibleContext = new AccessibleJTable();
 681:     this.cellEditor = null;
 682:     // COMPAT: Both Sun and IBM have drag enabled
 683:     this.dragEnabled = true;
 684:     this.preferredViewportSize = new Dimension(450,400);
 685:     this.showHorizontalLines = true;
 686:     this.showVerticalLines = true;
 687:     this.editingColumn = -1;
 688:     this.editingRow = -1;
 689:     setIntercellSpacing(new Dimension(1,1));
 690:   }
 691: 
 692:   /**
 693:    * Creates a new <code>JTable</code> instance.
 694:    *
 695:    * @param data a <code>Vector</code> value
 696:    * @param columnNames a <code>Vector</code> value
 697:    */
 698:   public JTable(Vector data, Vector columnNames)
 699:   {
 700:     this(new DefaultTableModel(data, columnNames));
 701:   }
 702: 
 703:   /**
 704:    * The timer that updates the editor component.
 705:    */
 706:   private class EditorUpdateTimer
 707:     extends Timer
 708:     implements ActionListener
 709:   {
 710:     /**
 711:      * Creates a new EditorUpdateTimer object with a default delay of 0.5 seconds.
 712:      */
 713:     public EditorUpdateTimer()
 714:     {
 715:       super(500, null);
 716:       addActionListener(this);
 717:     }
 718: 
 719:     /**
 720:      * Lets the caret blink and repaints the table.
 721:      */
 722:     public void actionPerformed(ActionEvent ev)
 723:     {
 724:       Caret c = ((JTextField)JTable.this.editorComp).getCaret();
 725:       if (c != null)
 726:         c.setVisible(!c.isVisible());
 727:       JTable.this.repaint();
 728:     }
 729: 
 730:     /**
 731:      * Updates the blink delay according to the current caret.
 732:      */
 733:     public void update()
 734:     {
 735:       stop();
 736:       Caret c = ((JTextField)JTable.this.editorComp).getCaret();
 737:       if (c != null)
 738:     {
 739:       setDelay(c.getBlinkRate());
 740:       if (((JTextField)JTable.this.editorComp).isEditable())
 741:         start();
 742:       else
 743:         c.setVisible(false);
 744:     }
 745:     }
 746:   }
 747: 
 748:   public void addColumn(TableColumn column)
 749:   {
 750:     if (column.getHeaderValue() == null)
 751:       {
 752:         String name = dataModel.getColumnName(column.getModelIndex());
 753:         column.setHeaderValue(name);
 754:       }
 755:     
 756:     columnModel.addColumn(column);
 757:   }
 758: 
 759:   protected void createDefaultEditors()
 760:   {
 761:     //FIXME: Create the editor object.
 762:   }
 763: 
 764:   protected void createDefaultRenderers()
 765:   {
 766:     setDefaultRenderer(Boolean.class, new BooleanCellRenderer());
 767:     setDefaultRenderer(Number.class, new NumberCellRenderer());
 768:     setDefaultRenderer(Double.class, new DoubleCellRenderer());
 769:     setDefaultRenderer(Double.class, new FloatCellRenderer());
 770:     setDefaultRenderer(Date.class, new DateCellRenderer());
 771:     setDefaultRenderer(Icon.class, new IconCellRenderer());
 772:   }
 773:   
 774:   /**
 775:    * @deprecated 1.0.2, replaced by <code>new JScrollPane(JTable)</code>
 776:    */
 777:   public static JScrollPane createScrollPaneForTable(JTable table)
 778:   {
 779:     return new JScrollPane(table);
 780:   }
 781: 
 782:   protected TableColumnModel createDefaultColumnModel()
 783:   {
 784:     return new DefaultTableColumnModel();
 785:   }
 786: 
 787:   protected TableModel createDefaultDataModel()
 788:   {
 789:     return new DefaultTableModel();
 790:   }
 791: 
 792:   protected ListSelectionModel createDefaultSelectionModel()
 793:   {
 794:     return new DefaultListSelectionModel();
 795:   }
 796: 
 797:   protected JTableHeader createDefaultTableHeader()
 798:   {
 799:     return new JTableHeader(columnModel);
 800:   }
 801:  
 802:   private void createColumnsFromModel()
 803:   {
 804:     if (dataModel == null)
 805:       return;
 806: 
 807:     TableColumnModel cm = createDefaultColumnModel();
 808: 
 809:     for (int i = 0; i < dataModel.getColumnCount(); ++i)
 810:       {
 811:         cm.addColumn(new TableColumn(i));
 812:       }
 813:     this.setColumnModel(cm);
 814:   }
 815: 
 816:   // listener support 
 817: 
 818:   public void columnAdded (TableColumnModelEvent event)
 819:   {
 820:     revalidate();
 821:     repaint();
 822:   }
 823: 
 824:   public void columnMarginChanged (ChangeEvent event)
 825:   {
 826:     revalidate();
 827:     repaint();
 828:   }
 829: 
 830:   public void columnMoved (TableColumnModelEvent event)
 831:   {
 832:     revalidate();
 833:     repaint();
 834:   }
 835: 
 836:   public void columnRemoved (TableColumnModelEvent event)
 837:   {
 838:     revalidate();
 839:     repaint();
 840:   }
 841:   
 842:   public void columnSelectionChanged (ListSelectionEvent event)
 843:   {
 844:     repaint();
 845:   }
 846: 
 847:   public void editingCanceled (ChangeEvent event)
 848:   {
 849:     if (rowBeingEdited > -1 && columnBeingEdited > -1)
 850:       {
 851:         if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField)
 852:           {
 853:             remove ((Component)getValueAt(rowBeingEdited, columnBeingEdited));
 854:             setValueAt(oldCellValue, rowBeingEdited, columnBeingEdited);
 855:           }
 856:         rowBeingEdited = -1;
 857:         columnBeingEdited = -1;
 858:       }
 859:     editorTimer.stop();
 860:     editorComp = null;
 861:     cellEditor = null;
 862:     requestFocusInWindow(false);
 863:     repaint();
 864:   }
 865: 
 866:   public void editingStopped (ChangeEvent event)
 867:   {
 868:     if (rowBeingEdited > -1 && columnBeingEdited > -1)
 869:       {
 870:         if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField)
 871:           {
 872:             remove((Component)getValueAt(rowBeingEdited, columnBeingEdited));
 873:             setValueAt(((JTextField)editorComp).getText(), 
 874:                        rowBeingEdited, columnBeingEdited);
 875:           }
 876:         rowBeingEdited = -1;
 877:         columnBeingEdited = -1;
 878:       }
 879:     editorTimer.stop();
 880:     editorComp = null;
 881:     cellEditor = null;
 882:     requestFocusInWindow(false);
 883:     repaint();
 884:   }
 885: 
 886:   public void tableChanged (TableModelEvent event)
 887:   {
 888:     // update the column model from the table model if the structure has
 889:     // changed and the flag autoCreateColumnsFromModel is set
 890:     if ((event.getFirstRow() ==TableModelEvent.HEADER_ROW)
 891:         && autoCreateColumnsFromModel)
 892: 
 893:         createColumnsFromModel();
 894: 
 895:     repaint();
 896:   }
 897: 
 898:   public void valueChanged (ListSelectionEvent event)
 899:   {
 900:     repaint();
 901:   }
 902: 
 903:  /**
 904:    * Returns index of the column that contains specified point 
 905:    * or -1 if this table doesn't contain this point.
 906:    *
 907:    * @param point point to identify the column
 908:    * @return index of the column that contains specified point or 
 909:    * -1 if this table doesn't contain this point.
 910:    */
 911:   public int columnAtPoint(Point point)
 912:   {
 913:     if (point != null)
 914:       {
 915:         int x0 = getLocation().x;
 916:         int ncols = getColumnCount();
 917:         Dimension gap = getIntercellSpacing();
 918:         TableColumnModel cols = getColumnModel();
 919:         int x = point.x;
 920: 
 921:         for (int i = 0; i < ncols; ++i)
 922:           {
 923:             int width = cols.getColumn(i).getWidth()
 924:                         + (gap == null ? 0 : gap.width);
 925:             if (0 <= x && x < width)
 926:               return i;
 927:             x -= width;
 928:           }
 929:       }
 930:     return -1;
 931:   }
 932: 
 933:   /**
 934:    * Returns index of the row that contains specified point or 
 935:    * -1 if this table doesn't contain this point.
 936:    *
 937:    * @param point point to identify the row
 938:    * @return index of the row that contains specified point or 
 939:    * -1 if this table doesn't contain this point.
 940:    */
 941:   public int rowAtPoint(Point point)
 942:   {
 943:     if (point != null)
 944:       {
 945:         int y0 = getLocation().y;
 946:         int nrows = getRowCount();
 947:         Dimension gap = getIntercellSpacing();
 948:         int height = getRowHeight() + (gap == null ? 0 : gap.height);
 949:         int y = point.y;
 950: 
 951:         for (int i = 0; i < nrows; ++i)
 952:           {
 953:             if (0 <= y && y < height)
 954:               return i;
 955:             y -= height;
 956:           }
 957:       }
 958:     return -1;
 959:   }
 960: 
 961:   /** 
 962:    * Calculate the visible rectangle for a particular row and column. The
 963:    * row and column are specified in visual terms; the column may not match
 964:    * the {@link #dataModel} column.
 965:    *
 966:    * @param row the visible row to get the cell rectangle of
 967:    *
 968:    * @param column the visible column to get the cell rectangle of, which may
 969:    * differ from the {@link #dataModel} column
 970:    *
 971:    * @param includeSpacing whether or not to include the cell margins in the
 972:    * resulting cell. If <code>false</code>, the result will only contain the
 973:    * inner area of the target cell, not including its margins.
 974:    *
 975:    * @return a rectangle enclosing the specified cell
 976:    */
 977:   public Rectangle getCellRect(int row,
 978:                                int column,
 979:                                boolean includeSpacing)
 980:   {
 981:     int height = getRowHeight(row);
 982:     int width = columnModel.getColumn(column).getWidth();
 983:     int x_gap = columnModel.getColumnMargin();
 984:     int y_gap = rowMargin;
 985: 
 986:     column = Math.max(0, Math.min(column, getColumnCount() - 1));
 987:     row = Math.max(0, Math.min(row, getRowCount() - 1));
 988: 
 989:     int x = 0;
 990:     int y = (height + y_gap) * row;
 991: 
 992:     for (int i = 0; i < column; ++i)
 993:       {        
 994:         x += columnModel.getColumn(i).getWidth();
 995:         x += x_gap;
 996:       }
 997: 
 998:     if (includeSpacing)
 999:       return new Rectangle(x, y, width, height);
1000:     else
1001:       return new Rectangle(x, y, width - x_gap, height - y_gap);
1002:   }
1003: 
1004:   public void clearSelection()
1005:   {
1006:     selectionModel.clearSelection();
1007:     getColumnModel().getSelectionModel().clearSelection();
1008:   }
1009: 
1010:   /**
1011:    * Get the value of the selectedRow property by delegation to
1012:    * the {@link ListSelectionModel#getMinSelectionIndex} method of the
1013:    * {@link #selectionModel} field.
1014:    *
1015:    * @return The current value of the selectedRow property
1016:    */
1017:   public int getSelectedRow ()
1018:   {
1019:     return selectionModel.getMinSelectionIndex();
1020:   }
1021:   
1022:   /**
1023:    * Get the value of the {@link #selectionModel} property.
1024:    *
1025:    * @return The current value of the property
1026:    */
1027:   public ListSelectionModel getSelectionModel()
1028:   {
1029:     //Neither Sun nor IBM returns null if rowSelection not allowed
1030:     return selectionModel;
1031:   }
1032:   
1033:   public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
1034:   {
1035:     if (orientation == SwingConstants.VERTICAL)
1036:       return visibleRect.height * direction;
1037:     else
1038:       return visibleRect.width * direction;
1039:   }
1040: 
1041:   /**
1042:    * Get the value of the <code>scrollableTracksViewportHeight</code> property.
1043:    *
1044:    * @return The constant value <code>false</code>
1045:    */
1046:   public boolean getScrollableTracksViewportHeight()
1047:   {
1048:     return false;
1049:   }
1050:   
1051:   /**
1052:    * Get the value of the <code>scrollableTracksViewportWidth</code> property.
1053:    *
1054:    * @return <code>true</code> unless the {@link #autoResizeMode} property is
1055:    * <code>AUTO_RESIZE_OFF</code>
1056:    */
1057:   public boolean getScrollableTracksViewportWidth()
1058:   {
1059:     if (autoResizeMode == AUTO_RESIZE_OFF)
1060:       return false;
1061:     else
1062:       return true;
1063:   }
1064: 
1065:   public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
1066:   {
1067:     // FIXME: I don't exactly know what sun does here. in both cases they
1068:     // pick values which do *not* simply expose the next cell in a given
1069:     // scroll direction.
1070: 
1071:     if (orientation == SwingConstants.VERTICAL)
1072:       return rowHeight;
1073:     else
1074:       {
1075:         int sum = 0;
1076:         for (int i = 0; i < getColumnCount(); ++i)
1077:           sum += columnModel.getColumn(0).getWidth();
1078:         return getColumnCount() == 0 ? 10 : sum / getColumnCount();
1079:       }
1080:   }
1081: 
1082: 
1083:   public TableCellEditor getCellEditor(int row, int column)
1084:   {
1085:     TableCellEditor editor = columnModel.getColumn(column).getCellEditor();
1086: 
1087:     if (editor == null)
1088:       editor = getDefaultEditor(dataModel.getColumnClass(column));
1089:     
1090:     return editor;
1091:   }
1092: 
1093:   public TableCellEditor getDefaultEditor(Class columnClass)
1094:   {
1095:     if (defaultEditorsByColumnClass.containsKey(columnClass))
1096:       return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass);
1097:     else
1098:       {
1099:     // FIXME: We have at least an editor for Object.class in our defaults.
1100:         TableCellEditor r = new DefaultCellEditor(new JTextField());
1101:         defaultEditorsByColumnClass.put(columnClass, r);
1102:         return r;
1103:       }
1104:   }
1105: 
1106: 
1107: 
1108:   public TableCellRenderer getCellRenderer(int row, int column)
1109:   {
1110:     TableCellRenderer renderer =
1111:       columnModel.getColumn(column).getCellRenderer();
1112:     
1113:     if (renderer == null)
1114:       renderer = getDefaultRenderer(dataModel.getColumnClass(column));
1115:     
1116:     return renderer;
1117:   }
1118: 
1119:   public void setDefaultRenderer(Class columnClass, TableCellRenderer rend)
1120:   {
1121:     defaultRenderersByColumnClass.put(columnClass, rend);
1122:   }
1123: 
1124:   public TableCellRenderer getDefaultRenderer(Class columnClass)
1125:   {
1126:     if (defaultRenderersByColumnClass.containsKey(columnClass))
1127:       return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass);
1128:     else
1129:       {
1130:         TableCellRenderer r = new DefaultTableCellRenderer();
1131:         defaultRenderersByColumnClass.put(columnClass, r);
1132:         return r;
1133:       }
1134:   }
1135: 
1136:   public int convertColumnIndexToModel(int vc)
1137:   {
1138:     if (vc < 0)
1139:       return vc;
1140:     else
1141:       return columnModel.getColumn(vc).getModelIndex();
1142:   }
1143: 
1144:   public int convertColumnIndexToView(int mc)
1145:   {
1146:     if (mc < 0)
1147:       return mc;
1148:     int ncols = getColumnCount();
1149:     for (int vc = 0; vc < ncols; ++vc)
1150:       {
1151:         if (columnModel.getColumn(vc).getModelIndex() == mc)
1152:           return vc;
1153:       }
1154:     return -1;
1155:   }
1156: 
1157:   public Component prepareRenderer(TableCellRenderer renderer,
1158:                                    int row,
1159:                                    int column)
1160:   {
1161:     boolean rsa = getRowSelectionAllowed();
1162:     boolean csa = getColumnSelectionAllowed();
1163:     boolean rs = rsa ? getSelectionModel().isSelectedIndex(row) : false;
1164:     boolean cs = csa ? columnModel.getSelectionModel().isSelectedIndex(column) : false;
1165:     boolean isSelected = ((rsa && csa && rs && cs) 
1166:                           || (rsa && !csa && rs) 
1167:                           || (!rsa && csa && cs));
1168:     
1169:     return renderer.getTableCellRendererComponent(this,
1170:                                                   dataModel.getValueAt(row, 
1171:                                                convertColumnIndexToModel(column)),
1172:                                                   isSelected,
1173:                                                   false, // hasFocus
1174:                                                   row, column);
1175:   }
1176: 
1177: 
1178:   /**
1179:    * Get the value of the {@link #autoCreateColumnsFromModel} property.
1180:    *
1181:    * @return The current value of the property
1182:    */
1183:   public boolean getAutoCreateColumnsFromModel()
1184:   {
1185:     return autoCreateColumnsFromModel;
1186:   }
1187: 
1188:   /**
1189:    * Get the value of the {@link #autoResizeMode} property.
1190:    *
1191:    * @return The current value of the property
1192:    */
1193:   public int getAutoResizeMode()
1194:   {
1195:     return autoResizeMode;
1196:   }
1197: 
1198:   /**
1199:    * Get the value of the {@link #rowHeight} property.
1200:    *
1201:    * @return The current value of the property
1202:    */
1203:   public int getRowHeight()
1204:   {
1205:     return rowHeight;
1206:   }
1207: 
1208:   /**
1209:    * Get the height of the specified row.
1210:    *
1211:    * @param row the row whose height to return
1212:    */
1213:   public int getRowHeight(int row)
1214:   {
1215:     // FIXME: return the height of the specified row
1216:     // which may be different from the general rowHeight
1217:     return rowHeight;
1218:   }
1219: 
1220: 
1221:   /**
1222:    * Get the value of the {@link #rowMargin} property.
1223:    *
1224:    * @return The current value of the property
1225:    */
1226:   public int getRowMargin()
1227:   {
1228:     return rowMargin;
1229:   }
1230: 
1231:   /**
1232:    * Get the value of the {@link #rowSelectionAllowed} property.
1233:    *
1234:    * @return The current value of the property
1235:    */
1236:   public boolean getRowSelectionAllowed()
1237:   {
1238:     return rowSelectionAllowed;
1239:   }
1240: 
1241:   /**
1242:    * Get the value of the {@link #cellSelectionEnabled} property.
1243:    *
1244:    * @return The current value of the property
1245:    */
1246:   public boolean getCellSelectionEnabled()
1247:   {
1248:     return getColumnSelectionAllowed() && getRowSelectionAllowed();
1249:   }
1250: 
1251:   /**
1252:    * Get the value of the {@link #dataModel} property.
1253:    *
1254:    * @return The current value of the property
1255:    */
1256:   public TableModel getModel()
1257:   {
1258:     return dataModel;
1259:   }
1260: 
1261:   /**
1262:    * Get the value of the <code>columnCount</code> property by
1263:    * delegation to the @{link #columnModel} field.
1264:    *
1265:    * @return The current value of the columnCount property
1266:    */
1267:   public int getColumnCount()
1268:   {
1269:     return columnModel.getColumnCount();    
1270:   }
1271: 
1272:   /**
1273:    * Get the value of the <code>rowCount</code> property by
1274:    * delegation to the @{link #dataModel} field.
1275:    *
1276:    * @return The current value of the rowCount property
1277:    */
1278:   public int getRowCount()
1279:   {
1280:     return dataModel.getRowCount();
1281:   }
1282: 
1283:   /**
1284:    * Get the value of the {@link #columnModel} property.
1285:    *
1286:    * @return The current value of the property
1287:    */
1288:   public TableColumnModel getColumnModel()
1289:   {
1290:     return columnModel;
1291:   }
1292: 
1293:   /**
1294:    * Get the value of the <code>selectedColumn</code> property by
1295:    * delegation to the @{link #columnModel} field.
1296:    *
1297:    * @return The current value of the selectedColumn property
1298:    */
1299:   public int getSelectedColumn()
1300:   {
1301:     return columnModel.getSelectionModel().getMinSelectionIndex();
1302:   }
1303: 
1304:   private static int countSelections(ListSelectionModel lsm)
1305:   {
1306:     int lo = lsm.getMinSelectionIndex();
1307:     int hi = lsm.getMaxSelectionIndex();
1308:     int sum = 0;
1309:     if (lo != -1 && hi != -1)
1310:       {
1311:         switch (lsm.getSelectionMode())
1312:           {
1313:           case ListSelectionModel.SINGLE_SELECTION:
1314:             sum = 1;
1315:             break;
1316:             
1317:           case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
1318:             sum = hi - lo + 1;
1319:             break;
1320:             
1321:           case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
1322:             for (int i = lo; i <= hi; ++i)
1323:               if (lsm.isSelectedIndex(i))        
1324:                 ++sum;
1325:             break;
1326:           }
1327:       }
1328:     return sum;
1329:   }
1330: 
1331:   private static int[] getSelections(ListSelectionModel lsm)
1332:   {
1333:     int sz = countSelections(lsm);
1334:     int [] ret = new int[sz];
1335: 
1336:     int lo = lsm.getMinSelectionIndex();
1337:     int hi = lsm.getMaxSelectionIndex();
1338:     int j = 0;
1339:     java.util.ArrayList ls = new java.util.ArrayList();
1340:     if (lo != -1 && hi != -1)
1341:       {
1342:         switch (lsm.getSelectionMode())
1343:           {
1344:           case ListSelectionModel.SINGLE_SELECTION:
1345:             ret[0] = lo;
1346:             break;      
1347:       
1348:           case ListSelectionModel.SINGLE_INTERVAL_SELECTION:            
1349:             for (int i = lo; i <= hi; ++i)
1350:               ret[j++] = i;
1351:             break;
1352:             
1353:           case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
1354:             for (int i = lo; i <= hi; ++i)
1355:               if (lsm.isSelectedIndex(i))        
1356:                 ret[j++] = i;
1357:             break;
1358:           }
1359:       }
1360:     return ret;
1361:   }
1362: 
1363:   /**
1364:    * Get the value of the <code>selectedColumnCount</code> property by
1365:    * delegation to the @{link #columnModel} field.
1366:    *
1367:    * @return The current value of the selectedColumnCount property
1368:    */  
1369:   public int getSelectedColumnCount()
1370:   {
1371:     return countSelections(columnModel.getSelectionModel());
1372:   }
1373: 
1374:   /**
1375:    * Get the value of the <code>selectedColumns</code> property by
1376:    * delegation to the @{link #columnModel} field.
1377:    *
1378:    * @return The current value of the selectedColumns property
1379:    */
1380:   public int[] getSelectedColumns()
1381:   {
1382:     return getSelections(columnModel.getSelectionModel());
1383:   }
1384: 
1385:   /**
1386:    * Get the value of the <code>columnSelectionAllowed</code> property.
1387:    *
1388:    * @return The current value of the columnSelectionAllowed property
1389:    */
1390:   public boolean getColumnSelectionAllowed()
1391:   {
1392:     return getColumnModel().getColumnSelectionAllowed();
1393:   }
1394: 
1395:   /**
1396:    * Get the value of the <code>selectedRowCount</code> property by
1397:    * delegation to the @{link #selectionModel} field.
1398:    *
1399:    * @return The current value of the selectedRowCount property
1400:    */
1401:   public int getSelectedRowCount()
1402:   {
1403:     return countSelections(selectionModel);
1404:   }
1405: 
1406:   /**
1407:    * Get the value of the <code>selectedRows</code> property by
1408:    * delegation to the @{link #selectionModel} field.
1409:    *
1410:    * @return The current value of the selectedRows property
1411:    */
1412:   public int[] getSelectedRows()
1413:   {
1414:     return getSelections(selectionModel);
1415:   }
1416: 
1417:   /**
1418:    * Get the value of the {@link #accessibleContext} property.
1419:    *
1420:    * @return The current value of the property
1421:    */
1422:   public AccessibleContext getAccessibleContext()
1423:   {
1424:     return accessibleContext;
1425:   }
1426: 
1427:   /**
1428:    * Get the value of the {@link #cellEditor} property.
1429:    *
1430:    * @return The current value of the property
1431:    */
1432:   public TableCellEditor getCellEditor()
1433:   {
1434:     return cellEditor;
1435:   }
1436: 
1437:   /**
1438:    * Get the value of the {@link #dragEnabled} property.
1439:    *
1440:    * @return The current value of the property
1441:    */
1442:   public boolean getDragEnabled()
1443:   {
1444:     return dragEnabled;
1445:   }
1446: 
1447:   /**
1448:    * Get the value of the {@link #gridColor} property.
1449:    *
1450:    * @return The current value of the property
1451:    */
1452:   public Color getGridColor()
1453:   {
1454:     return gridColor;
1455:   }
1456: 
1457:   /**
1458:    * Get the value of the <code>intercellSpacing</code> property.
1459:    *
1460:    * @return The current value of the property
1461:    */
1462:   public Dimension getIntercellSpacing()
1463:   {
1464:     return new Dimension(columnModel.getColumnMargin(), rowMargin);
1465:   }
1466: 
1467:   /**
1468:    * Get the value of the {@link #preferredViewportSize} property.
1469:    *
1470:    * @return The current value of the property
1471:    */
1472:   public Dimension getPreferredScrollableViewportSize()
1473:   {
1474:     return preferredViewportSize;
1475:   }
1476: 
1477:   /**
1478:    * Get the value of the {@link #selectionBackground} property.
1479:    *
1480:    * @return The current value of the property
1481:    */
1482:   public Color getSelectionBackground()
1483:   {
1484:     return selectionBackground;
1485:   }
1486: 
1487:   /**
1488:    * Get the value of the {@link #selectionForeground} property.
1489:    *
1490:    * @return The current value of the property
1491:    */
1492:   public Color getSelectionForeground()
1493:   {
1494:     return selectionForeground;
1495:   }
1496: 
1497:   /**
1498:    * Get the value of the {@link #showHorizontalLines} property.
1499:    *
1500:    * @return The current value of the property
1501:    */
1502:   public boolean getShowHorizontalLines()
1503:   {
1504:     return showHorizontalLines;
1505:   }
1506: 
1507:   /**
1508:    * Get the value of the {@link #showVerticalLines} property.
1509:    *
1510:    * @return The current value of the property
1511:    */
1512:   public boolean getShowVerticalLines()
1513:   {
1514:     return showVerticalLines;
1515:   }
1516: 
1517:   /**
1518:    * Get the value of the {@link #tableHeader} property.
1519:    *
1520:    * @return The current value of the property
1521:    */
1522:   public JTableHeader getTableHeader()
1523:   {
1524:     return tableHeader;
1525:   }
1526: 
1527:   /**
1528:    * Removes specified column from displayable columns of this table.
1529:    *
1530:    * @param column column to removed
1531:    */
1532:   public void removeColumn(TableColumn column)
1533:   {    
1534:     columnModel.removeColumn(column);
1535:   }
1536: 
1537:   /**
1538:    * Moves column at the specified index to new given location.
1539:    *
1540:    * @param column index of the column to move
1541:    * @param targetColumn index specifying new location of the column
1542:    */ 
1543:   public void moveColumn(int column,int targetColumn) 
1544:   {
1545:     columnModel.moveColumn(column, targetColumn);
1546:   }
1547: 
1548:   /**
1549:    * Set the value of the {@link #autoCreateColumnsFromModel} flag.  If the
1550:    * flag changes from <code>false</code> to <code>true</code>, the
1551:    * {@link #createDefaultColumnsFromModel()} method is called.
1552:    *
1553:    * @param autoCreate  the new value of the flag.
1554:    */ 
1555:   public void setAutoCreateColumnsFromModel(boolean autoCreate)
1556:   {
1557:     if (autoCreateColumnsFromModel != autoCreate)
1558:     {
1559:       autoCreateColumnsFromModel = autoCreate;
1560:       if (autoCreate)
1561:         createDefaultColumnsFromModel();
1562:     }
1563:   }
1564: 
1565:   /**
1566:    * Set the value of the {@link #autoResizeMode} property.
1567:    *
1568:    * @param a The new value of the autoResizeMode property
1569:    */ 
1570:   public void setAutoResizeMode(int a)
1571:   {
1572:     autoResizeMode = a;
1573:     revalidate();
1574:     repaint();
1575:   }
1576: 
1577:   /**
1578:    * Set the value of the {@link #rowHeight} property.
1579:    *
1580:    * @param r The new value of the rowHeight property
1581:    */ 
1582:   public void setRowHeight(int r)
1583:   {
1584:     if (r < 1)
1585:       throw new IllegalArgumentException();
1586:     
1587:     rowHeight = r;
1588:     revalidate();
1589:     repaint();
1590:   }
1591:   
1592:   /**
1593:    * Sets the value of the rowHeight property for the specified
1594:    * row.
1595:    * 
1596:    * @param rh is the new rowHeight
1597:    * @param row is the row to change the rowHeight of
1598:    */
1599:   public void setRowHeight(int row, int rh)
1600:   {
1601:      setRowHeight(rh);
1602:      // FIXME: not implemented
1603:   }
1604:   
1605:   /**
1606:    * Set the value of the {@link #rowMargin} property.
1607:    *
1608:    * @param r The new value of the rowMargin property
1609:    */ 
1610:   public void setRowMargin(int r)
1611:   {
1612:     rowMargin = r;
1613:     revalidate();
1614:     repaint();
1615:   }
1616: 
1617:   /**
1618:    * Set the value of the {@link #rowSelectionAllowed} property.
1619:    *
1620:    * @param r The new value of the rowSelectionAllowed property
1621:    */ 
1622:   public void setRowSelectionAllowed(boolean r)
1623:   {
1624:     rowSelectionAllowed = r;
1625:     repaint();
1626:   }
1627: 
1628:   /**
1629:    * Set the value of the {@link #cellSelectionEnabled} property.
1630:    *
1631:    * @param c The new value of the cellSelectionEnabled property
1632:    */ 
1633:   public void setCellSelectionEnabled(boolean c)
1634:   {
1635:     setColumnSelectionAllowed(c);
1636:     setRowSelectionAllowed(c);
1637:     // for backward-compatibility sake:
1638:     cellSelectionEnabled = true;
1639:   }
1640: 
1641:   /**
1642:    * <p>Set the value of the {@link #dataModel} property.</p>
1643:    *
1644:    * <p>Unregister <code>this</code> as a {@link TableModelListener} from
1645:    * previous {@link #dataModel} and register it with new parameter
1646:    * <code>m</code>.</p>
1647:    *
1648:    * @param m The new value of the model property
1649:    */ 
1650:   public void setModel(TableModel m)
1651:   {
1652:     // Throw exception is m is null.
1653:     if (m == null)
1654:       throw new IllegalArgumentException();
1655:    
1656:     // Don't do anything if setting the current model again.
1657:     if (dataModel == m)
1658:       return;
1659:     
1660:     // Remove table as TableModelListener from old model.
1661:     if (dataModel != null)
1662:       dataModel.removeTableModelListener(this);
1663:     
1664:     if (m != null)
1665:       {
1666:     // Set property.
1667:         dataModel = m;
1668: 
1669:     // Add table as TableModelListener to new model.
1670:     dataModel.addTableModelListener(this);
1671: 
1672:     // Automatically create columns.
1673:     if (autoCreateColumnsFromModel)
1674:       createColumnsFromModel();
1675:       }
1676:     
1677:     // Repaint table.
1678:     revalidate();
1679:     repaint();
1680:   }
1681: 
1682:   /**
1683:    * <p>Set the value of the {@link #columnModel} property.</p>
1684:    *
1685:    * <p>Unregister <code>this</code> as a {@link TableColumnModelListener}
1686:    * from previous {@link #columnModel} and register it with new parameter
1687:    * <code>c</code>.</p>
1688:    *
1689:    * @param c The new value of the columnModel property
1690:    */ 
1691:   public void setColumnModel(TableColumnModel c)
1692:   {
1693:     if (c == null)
1694:       throw new IllegalArgumentException();
1695:     TableColumnModel tmp = columnModel;
1696:     if (tmp != null)
1697:       tmp.removeColumnModelListener(this);
1698:     if (c != null)
1699:       c.addColumnModelListener(this);
1700:     columnModel = c;
1701:     if (dataModel != null && columnModel != null)
1702:       {
1703:         int ncols = getColumnCount();
1704:         for (int i = 0; i < ncols; ++i)
1705:           columnModel.getColumn(i).setHeaderValue(dataModel.getColumnName(i));
1706:       }
1707: 
1708:     // according to Sun's spec we also have to set the tableHeader's
1709:     // column model here
1710:     if (tableHeader != null)
1711:       tableHeader.setColumnModel(c);
1712: 
1713:     revalidate();
1714:     repaint();
1715:   }
1716: 
1717:   /**
1718:    * Set the value of the <code>columnSelectionAllowed</code> property.
1719:    *
1720:    * @param c The new value of the property
1721:    */ 
1722:   public void setColumnSelectionAllowed(boolean c)
1723:   {
1724:     getColumnModel().setColumnSelectionAllowed(c);
1725:     repaint();
1726:   }
1727: 
1728:   /**
1729:    * <p>Set the value of the {@link #selectionModel} property.</p>
1730:    *
1731:    * <p>Unregister <code>this</code> as a {@link ListSelectionListener}
1732:    * from previous {@link #selectionModel} and register it with new
1733:    * parameter <code>s</code>.</p>
1734:    *
1735:    * @param s The new value of the selectionModel property
1736:    */ 
1737:   public void setSelectionModel(ListSelectionModel s)
1738:   {
1739:     if (s == null)
1740:       throw new IllegalArgumentException();
1741:     ListSelectionModel tmp = selectionModel;
1742:     if (tmp != null)
1743:       tmp.removeListSelectionListener(this);
1744:     if (s != null)
1745:       s.addListSelectionListener(this);
1746:     selectionModel = s;
1747:   }
1748: 
1749:   /**
1750:    * Set the value of the <code>selectionMode</code> property by
1751:    * delegation to the {@link #selectionModel} field. The same selection
1752:    * mode is set for row and column selection models.
1753:    *
1754:    * @param s The new value of the property
1755:    */ 
1756:   public void setSelectionMode(int s)
1757:   { 
1758:     selectionModel.setSelectionMode(s);    
1759:     columnModel.getSelectionModel().setSelectionMode(s);
1760:     
1761:     repaint();
1762:   }
1763: 
1764:   /**
1765:    * <p>Set the value of the {@link #cellEditor} property.</p>
1766:    *
1767:    * <p>Unregister <code>this</code> as a {@link CellEditorListener} from
1768:    * previous {@link #cellEditor} and register it with new parameter
1769:    * <code>c</code>.</p>
1770:    *
1771:    * @param c The new value of the cellEditor property
1772:    */ 
1773:   public void setCellEditor(TableCellEditor c)
1774:   {
1775:     TableCellEditor tmp = cellEditor;
1776:     if (tmp != null)
1777:       tmp.removeCellEditorListener(this);
1778:     if (c != null)
1779:       c.addCellEditorListener(this);
1780:     cellEditor = c;
1781:   }
1782: 
1783:   /**
1784:    * Set the value of the {@link #dragEnabled} property.
1785:    *
1786:    * @param d The new value of the dragEnabled property
1787:    */ 
1788:   public void setDragEnabled(boolean d)
1789:   {
1790:     dragEnabled = d;
1791:   }
1792: 
1793:   /**
1794:    * Set the value of the {@link #gridColor} property.
1795:    *
1796:    * @param g The new value of the gridColor property
1797:    */ 
1798:   public void setGridColor(Color g)
1799:   {
1800:     gridColor = g;
1801:     repaint();
1802:   }
1803: 
1804:   /**
1805:    * Set the value of the <code>intercellSpacing</code> property.
1806:    *
1807:    * @param i The new value of the intercellSpacing property
1808:    */ 
1809:   public void setIntercellSpacing(Dimension i)
1810:   {
1811:     rowMargin = i.height;
1812:     columnModel.setColumnMargin(i.width);
1813:     repaint();
1814:   }
1815: 
1816:   /**
1817:    * Set the value of the {@link #preferredViewportSize} property.
1818:    *
1819:    * @param p The new value of the preferredViewportSize property
1820:    */ 
1821:   public void setPreferredScrollableViewportSize(Dimension p)
1822:   {
1823:     preferredViewportSize = p;
1824:     revalidate();
1825:     repaint();
1826:   }
1827: 
1828:   /**
1829:    * <p>Set the value of the {@link #selectionBackground} property.</p>
1830:    *
1831:    * <p>Fire a PropertyChangeEvent with name {@link
1832:    * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if
1833:    * selectionBackground changed.</p>
1834:    *
1835:    * @param s The new value of the selectionBackground property
1836:    */ 
1837:   public void setSelectionBackground(Color s)
1838:   {
1839:     Color tmp = selectionBackground;
1840:     selectionBackground = s;
1841:     if (((tmp == null && s != null)
1842:          || (s == null && tmp != null)
1843:          || (tmp != null && s != null && !tmp.equals(s))))
1844:       firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY, tmp, s);
1845:     repaint();
1846:   }
1847: 
1848:   /**
1849:    * <p>Set the value of the {@link #selectionForeground} property.</p>
1850:    *
1851:    * <p>Fire a PropertyChangeEvent with name {@link
1852:    * #SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if
1853:    * selectionForeground changed.</p>
1854:    *
1855:    * @param s The new value of the selectionForeground property
1856:    */ 
1857:   public void setSelectionForeground(Color s)
1858:   {
1859:     Color tmp = selectionForeground;
1860:     selectionForeground = s;
1861:     if (((tmp == null && s != null)
1862:          || (s == null && tmp != null)
1863:          || (tmp != null && s != null && !tmp.equals(s))))
1864:       firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY, tmp, s);
1865:     repaint();
1866:   }
1867: 
1868:   /**
1869:    * Set the value of the <code>showGrid</code> property.
1870:    *
1871:    * @param s The new value of the showGrid property
1872:    */ 
1873:   public void setShowGrid(boolean s)
1874:   {
1875:     setShowVerticalLines(s);
1876:     setShowHorizontalLines(s);
1877:   }
1878: 
1879:   /**
1880:    * Set the value of the {@link #showHorizontalLines} property.
1881:    *
1882:    * @param s The new value of the showHorizontalLines property
1883:    */ 
1884:   public void setShowHorizontalLines(boolean s)
1885:   {
1886:     showHorizontalLines = s;
1887:     repaint();
1888:   }
1889: 
1890:   /**
1891:    * Set the value of the {@link #showVerticalLines} property.
1892:    *
1893:    * @param s The new value of the showVerticalLines property
1894:    */ 
1895:   public void setShowVerticalLines(boolean s)
1896:   {
1897:     showVerticalLines = s;
1898:     repaint();
1899:   }
1900: 
1901:   /**
1902:    * Set the value of the {@link #tableHeader} property.
1903:    *
1904:    * @param t The new value of the tableHeader property
1905:    */ 
1906:   public void setTableHeader(JTableHeader t)
1907:   {
1908:     if (tableHeader != null)
1909:       tableHeader.setTable(null);
1910:     tableHeader = t;
1911:     if (tableHeader != null)
1912:       tableHeader.setTable(this);
1913:     revalidate();
1914:     repaint();
1915:   }
1916: 
1917:   protected void configureEnclosingScrollPane()
1918:   {
1919:     JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
1920:     if (jsp != null && tableHeader != null)
1921:       {
1922:         jsp.setColumnHeaderView(tableHeader);
1923:       }
1924:   }
1925: 
1926:   protected void unconfigureEnclosingScrollPane()
1927:   {
1928:     JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
1929:     if (jsp != null)
1930:       {
1931:         jsp.setColumnHeaderView(null);
1932:       }    
1933:   }
1934: 
1935: 
1936:   public void addNotify()
1937:   {
1938:     super.addNotify();
1939:     configureEnclosingScrollPane();
1940:   }
1941: 
1942:   public void removeNotify()
1943:   {
1944:     super.addNotify();
1945:     unconfigureEnclosingScrollPane();
1946:   }
1947: 
1948: 
1949:   /**
1950:    * This distributes the superfluous width in a table evenly on its columns.
1951:    *
1952:    * The implementation used here is different to that one described in
1953:    * the JavaDocs. It is much simpler, and seems to work very well.
1954:    *
1955:    * TODO: correctly implement the algorithm described in the JavaDoc
1956:    */
1957:   private void distributeSpill(TableColumn[] cols, int spill)
1958:   {
1959:     int average = spill / cols.length;
1960:     for (int i = 0; i < cols.length; i++)
1961:       {
1962:         cols[i].setWidth(cols[i].getWidth() + average);
1963:       }
1964:   }
1965: 
1966:   public void doLayout()
1967:   {
1968:     TableColumn resizingColumn = null;
1969: 
1970:     int ncols = getColumnCount();
1971:     if (ncols < 1)
1972:       return;
1973: 
1974:     int[] pref = new int[ncols];
1975:     int prefSum = 0;
1976:     int rCol = -1;
1977: 
1978:     if (tableHeader != null)
1979:       resizingColumn = tableHeader.getResizingColumn();
1980: 
1981:     for (int i = 0; i < ncols; ++i)
1982:       {
1983:         TableColumn col = columnModel.getColumn(i);
1984:         int p = col.getWidth();
1985:         pref[i] = p;
1986:         prefSum += p;
1987:         if (resizingColumn == col)
1988:           rCol = i;
1989:       }
1990: 
1991:     int spill = getWidth() - prefSum;
1992: 
1993:     if (resizingColumn != null)
1994:       {
1995:         TableColumn col;
1996:         TableColumn [] cols;
1997: 
1998:         switch (getAutoResizeMode())
1999:           {
2000:           case AUTO_RESIZE_LAST_COLUMN:
2001:             col = columnModel.getColumn(ncols-1);
2002:             col.setWidth(col.getPreferredWidth() + spill);
2003:             break;
2004:             
2005:           case AUTO_RESIZE_NEXT_COLUMN:
2006:             col = columnModel.getColumn(ncols-1);
2007:             col.setWidth(col.getPreferredWidth() + spill);
2008:             break;
2009: 
2010:           case AUTO_RESIZE_ALL_COLUMNS:
2011:             cols = new TableColumn[ncols];
2012:             for (int i = 0; i < ncols; ++i)
2013:               cols[i] = columnModel.getColumn(i);
2014:             distributeSpill(cols, spill);
2015:             break;
2016: 
2017:           case AUTO_RESIZE_SUBSEQUENT_COLUMNS:
2018:             cols = new TableColumn[ncols];
2019:             for (int i = rCol; i < ncols; ++i)
2020:               cols[i] = columnModel.getColumn(i);
2021:             distributeSpill(cols, spill);
2022:             break;
2023: 
2024:           case AUTO_RESIZE_OFF:
2025:           default:
2026:           }
2027:       }
2028:     else
2029:       {
2030:         TableColumn [] cols = new TableColumn[ncols];
2031:         for (int i = 0; i < ncols; ++i)
2032:           cols[i] = columnModel.getColumn(i);
2033:         distributeSpill(cols, spill);        
2034:       }
2035:   }
2036:   
2037:   /**
2038:    * @deprecated Replaced by <code>doLayout()</code>
2039:    */
2040:   public void sizeColumnsToFit(boolean lastColumnOnly)
2041:   {
2042:     doLayout();
2043:   }
2044: 
2045:   /**
2046:    * Obsolete since JDK 1.4. Please use <code>doLayout()</code>.
2047:    */
2048:   public void sizeColumnsToFit(int resizingColumn)
2049:   {
2050:     doLayout();
2051:   }
2052: 
2053:   public String getUIClassID()
2054:   {
2055:     return "TableUI";
2056:   }
2057: 
2058:   /**
2059:    * This method returns the table's UI delegate.
2060:    *
2061:    * @return The table's UI delegate.
2062:    */
2063:   public TableUI getUI()
2064:   {
2065:     return (TableUI) ui;
2066:   }
2067: 
2068:   /**
2069:    * This method sets the table's UI delegate.
2070:    *
2071:    * @param ui The table's UI delegate.
2072:    */
2073:   public void setUI(TableUI ui)
2074:   {
2075:     super.setUI(ui);
2076:   }
2077: 
2078:   public void updateUI()
2079:   {
2080:     setUI((TableUI) UIManager.getUI(this));
2081:     revalidate();
2082:     repaint();
2083:   }
2084: 
2085:   public Class getColumnClass(int column)
2086:   {
2087:     return dataModel.getColumnClass(column);
2088:   }
2089:   
2090:   public String getColumnName(int column)
2091:   {
2092:     int modelColumn = columnModel.getColumn(column).getModelIndex();
2093:     return dataModel.getColumnName(modelColumn);
2094:   }
2095: 
2096:   public int getEditingColumn()
2097:   {
2098:     return editingColumn;
2099:   }
2100: 
2101:   public void setEditingColumn(int column)
2102:   {
2103:     editingColumn = column;
2104:   }
2105:   
2106:   public int getEditingRow()
2107:   {
2108:     return editingRow;
2109:   }
2110: 
2111:   public void setEditingRow(int column)
2112:   {
2113:     editingRow = column;
2114:   }
2115:   
2116:   public Component getEditorComponent()
2117:   {
2118:     return editorComp;
2119:   }
2120:   
2121:   public boolean isEditing()
2122:   {
2123:     return editorComp != null;
2124:   }
2125: 
2126:   public void setDefaultEditor(Class columnClass, TableCellEditor editor)
2127:   {
2128:     if (editor != null)
2129:       defaultEditorsByColumnClass.put(columnClass, editor);
2130:     else
2131:       defaultEditorsByColumnClass.remove(columnClass);
2132:   }
2133: 
2134:   public void addColumnSelectionInterval(int index0, int index1)
2135:   {
2136:     if ((index0 < 0 || index0 > (getColumnCount()-1)
2137:          || index1 < 0 || index1 > (getColumnCount()-1)))
2138:       throw new IllegalArgumentException("Column index out of range.");
2139:     
2140:     getColumnModel().getSelectionModel().addSelectionInterval(index0, index1);
2141:   }
2142:   
2143:   public void addRowSelectionInterval(int index0, int index1)
2144:   {            
2145:     if ((index0 < 0 || index0 > (getRowCount()-1)
2146:          || index1 < 0 || index1 > (getRowCount()-1)))
2147:       throw new IllegalArgumentException("Row index out of range.");
2148:           
2149:     getSelectionModel().addSelectionInterval(index0, index1);
2150:   }
2151:   
2152:   public void setColumnSelectionInterval(int index0, int index1)
2153:   {
2154:     if ((index0 < 0 || index0 > (getColumnCount()-1)
2155:          || index1 < 0 || index1 > (getColumnCount()-1)))
2156:       throw new IllegalArgumentException("Column index out of range.");
2157: 
2158:     getColumnModel().getSelectionModel().setSelectionInterval(index0, index1);
2159:   }
2160:   
2161:   public void setRowSelectionInterval(int index0, int index1)
2162:   {    
2163:     if ((index0 < 0 || index0 > (getRowCount()-1)
2164:          || index1 < 0 || index1 > (getRowCount()-1)))
2165:       throw new IllegalArgumentException("Row index out of range.");
2166: 
2167:     getSelectionModel().setSelectionInterval(index0, index1);
2168:   }
2169:   
2170:   public void removeColumnSelectionInterval(int index0, int index1)  
2171:   {
2172:     if ((index0 < 0 || index0 > (getColumnCount()-1)
2173:          || index1 < 0 || index1 > (getColumnCount()-1)))
2174:       throw new IllegalArgumentException("Column index out of range.");
2175: 
2176:     getColumnModel().getSelectionModel().removeSelectionInterval(index0, index1);
2177:   }
2178:   
2179:   public void removeRowSelectionInterval(int index0, int index1)
2180:   {
2181:     if ((index0 < 0 || index0 > (getRowCount()-1)
2182:          || index1 < 0 || index1 > (getRowCount()-1)))
2183:       throw new IllegalArgumentException("Row index out of range.");
2184: 
2185:     getSelectionModel().removeSelectionInterval(index0, index1);
2186:   }
2187:   
2188:   public boolean isColumnSelected(int column)
2189:   {
2190:     return getColumnModel().getSelectionModel().isSelectedIndex(column);
2191:   }
2192: 
2193:   public boolean isRowSelected(int row)
2194:   {
2195:     return getSelectionModel().isSelectedIndex(row);
2196:   }
2197: 
2198:   public boolean isCellSelected(int row, int column)
2199:   {
2200:     return isRowSelected(row) && isColumnSelected(column);
2201:   }
2202:   
2203:   public void selectAll()
2204:   {
2205:     // rowLead and colLead store the current lead selection indices
2206:     int rowLead = selectionModel.getLeadSelectionIndex();
2207:     int colLead = getColumnModel().getSelectionModel().getLeadSelectionIndex();
2208:     // the following calls to setSelectionInterval change the lead selection
2209:     // indices
2210:     setColumnSelectionInterval(0, getColumnCount() - 1);
2211:     setRowSelectionInterval(0, getRowCount() - 1);
2212:     // the following addSelectionInterval calls restore the lead selection
2213:     // indices to their previous values
2214:     addColumnSelectionInterval(colLead,colLead);
2215:     addRowSelectionInterval(rowLead, rowLead);
2216:   }
2217: 
2218:   public Object getValueAt(int row, int column)
2219:   {
2220:     return dataModel.getValueAt(row, convertColumnIndexToModel(column));
2221:   }
2222: 
2223:   public void setValueAt(Object value, int row, int column)
2224:   {
2225:     if (!isCellEditable(row, column))
2226:       return;
2227: 
2228:     if (value instanceof Component)
2229:       add((Component)value);
2230:     dataModel.setValueAt(value, row, convertColumnIndexToModel(column));
2231:   }
2232: 
2233:   public TableColumn getColumn(Object identifier)
2234:   {
2235:     return columnModel.getColumn(columnModel.getColumnIndex(identifier));
2236:   }
2237: 
2238:   /**
2239:    * Returns <code>true</code> if the specified cell is editable, and
2240:    * <code>false</code> otherwise.
2241:    *
2242:    * @param row  the row index.
2243:    * @param column  the column index.
2244:    *
2245:    * @return A boolean.
2246:    */
2247:   public boolean isCellEditable(int row, int column)
2248:   {
2249:     return dataModel.isCellEditable(row, convertColumnIndexToModel(column));
2250:   }
2251: 
2252:   /**
2253:    * Clears any existing columns from the <code>JTable</code>'s
2254:    * {@link TableColumnModel} and creates new columns to match the values in
2255:    * the data ({@link TableModel}) used by the table.
2256:    *
2257:    * @see #setAutoCreateColumnsFromModel(boolean)
2258:    */
2259:   public void createDefaultColumnsFromModel()
2260:   {
2261:     // remove existing columns
2262:     int columnIndex = columnModel.getColumnCount() - 1;
2263:     while (columnIndex >= 0)
2264:     {
2265:       columnModel.removeColumn(columnModel.getColumn(columnIndex));
2266:       columnIndex--;
2267:     }
2268:   
2269:     // add new columns to match the TableModel
2270:     int columnCount = dataModel.getColumnCount();
2271:     for (int c = 0; c < columnCount; c++)
2272:     {
2273:       TableColumn column = new TableColumn(c);
2274:       column.setIdentifier(dataModel.getColumnName(c));
2275:       columnModel.addColumn(column);
2276:     }
2277:   }
2278: 
2279:   public void changeSelection (int rowIndex, int columnIndex, boolean toggle, boolean extend)
2280:   {
2281:     if (toggle && extend)
2282:       {
2283:         // Leave the selection state as is, but move the anchor
2284:         //   index to the specified location
2285:         selectionModel.setAnchorSelectionIndex(rowIndex);
2286:         getColumnModel().getSelectionModel().setAnchorSelectionIndex(columnIndex);
2287:       }
2288:     else if (toggle)
2289:       {
2290:         // Toggle the state of the specified cell
2291:         if (isCellSelected(rowIndex,columnIndex))
2292:           {
2293:             selectionModel.removeSelectionInterval(rowIndex,rowIndex);
2294:             getColumnModel().getSelectionModel().removeSelectionInterval(columnIndex,columnIndex);
2295:           }
2296:         else
2297:           {
2298:             selectionModel.addSelectionInterval(rowIndex,rowIndex);
2299:             getColumnModel().getSelectionModel().addSelectionInterval(columnIndex,columnIndex);
2300:           }
2301:       }
2302:     else if (extend)
2303:       {
2304:         // Extend the previous selection from the anchor to the 
2305:         // specified cell, clearing all other selections
2306:         selectionModel.setLeadSelectionIndex(rowIndex);
2307:         getColumnModel().getSelectionModel().setLeadSelectionIndex(columnIndex);
2308:       }
2309:     else
2310:       {
2311:         // Clear the previous selection and ensure the new cell
2312:         // is selected
2313:          selectionModel.clearSelection();
2314:         selectionModel.setSelectionInterval(rowIndex,rowIndex);
2315:         getColumnModel().getSelectionModel().clearSelection();
2316:         getColumnModel().getSelectionModel().setSelectionInterval(columnIndex, columnIndex);
2317:         
2318:         
2319:       }
2320:   }
2321: 
2322:   /**
2323:    * Programmatically starts editing the specified cell.
2324:    *
2325:    * @param row the row of the cell to edit.
2326:    * @param column the column of the cell to edit.
2327:    */
2328:   public boolean editCellAt (int row, int column)
2329:   {
2330:     oldCellValue = getValueAt(row, column);
2331:     setCellEditor(getCellEditor(row, column));
2332:     editorComp = prepareEditor(cellEditor, row, column);
2333:     cellEditor.addCellEditorListener(this);
2334:     rowBeingEdited = row;
2335:     columnBeingEdited = column;
2336:     setValueAt(editorComp, row, column);
2337:     ((JTextField)editorComp).requestFocusInWindow(false);
2338:     editorTimer.start();
2339:     return true;
2340:   }
2341: 
2342:   /**
2343:    * Programmatically starts editing the specified cell.
2344:    *
2345:    * @param row the row of the cell to edit.
2346:    * @param column the column of the cell to edit.
2347:    */
2348:   public boolean editCellAt (int row, int column, EventObject e)
2349:   {
2350:     return editCellAt(row, column);
2351:   }
2352: 
2353:   /**
2354:    * Discards the editor object.
2355:    */
2356:   public void removeEditor()
2357:   {
2358:     editingStopped(new ChangeEvent(this));
2359:   }
2360: 
2361:   /**
2362:    * Prepares the editor by querying for the value and selection state of the
2363:    * cell at (row, column).
2364:    *
2365:    * @param editor the TableCellEditor to set up
2366:    * @param row the row of the cell to edit
2367:    * @param column the column of the cell to edit
2368:    * @return the Component being edited
2369:    */
2370:   public Component prepareEditor (TableCellEditor editor, int row, int column)
2371:   {
2372:     return editor.getTableCellEditorComponent
2373:       (this, getValueAt(row, column), isCellSelected(row, column), row, column);
2374:   }
2375: }