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.Cursor;
  44: import java.awt.Dimension;
  45: import java.awt.Font;
  46: import java.awt.FontMetrics;
  47: import java.awt.Point;
  48: import java.awt.Rectangle;
  49: import java.awt.event.ActionEvent;
  50: import java.awt.event.ActionListener;
  51: import java.awt.event.FocusListener;
  52: import java.beans.PropertyChangeEvent;
  53: import java.beans.PropertyChangeListener;
  54: import java.text.DateFormat;
  55: import java.text.NumberFormat;
  56: import java.util.Date;
  57: import java.util.EventObject;
  58: import java.util.Hashtable;
  59: import java.util.Locale;
  60: import java.util.Vector;
  61: 
  62: import javax.accessibility.Accessible;
  63: import javax.accessibility.AccessibleComponent;
  64: import javax.accessibility.AccessibleContext;
  65: import javax.accessibility.AccessibleExtendedTable;
  66: import javax.accessibility.AccessibleRole;
  67: import javax.accessibility.AccessibleSelection;
  68: import javax.accessibility.AccessibleStateSet;
  69: import javax.accessibility.AccessibleTable;
  70: import javax.accessibility.AccessibleTableModelChange;
  71: import javax.swing.event.CellEditorListener;
  72: import javax.swing.event.ChangeEvent;
  73: import javax.swing.event.ListSelectionEvent;
  74: import javax.swing.event.ListSelectionListener;
  75: import javax.swing.event.TableColumnModelEvent;
  76: import javax.swing.event.TableColumnModelListener;
  77: import javax.swing.event.TableModelEvent;
  78: import javax.swing.event.TableModelListener;
  79: import javax.swing.plaf.TableUI;
  80: import javax.swing.table.DefaultTableCellRenderer;
  81: import javax.swing.table.DefaultTableColumnModel;
  82: import javax.swing.table.DefaultTableModel;
  83: import javax.swing.table.JTableHeader;
  84: import javax.swing.table.TableCellEditor;
  85: import javax.swing.table.TableCellRenderer;
  86: import javax.swing.table.TableColumn;
  87: import javax.swing.table.TableColumnModel;
  88: import javax.swing.table.TableModel;
  89: import javax.swing.text.Caret;
  90: 
  91: public class JTable
  92:   extends JComponent
  93:   implements TableModelListener, Scrollable, TableColumnModelListener,
  94:              ListSelectionListener, CellEditorListener, Accessible
  95: {
  96:   /**
  97:    * Provides accessibility support for <code>JTable</code>.
  98:    *
  99:    * @author Roman Kennke (kennke@aicas.com)
 100:    */
 101:   protected class AccessibleJTable
 102:     extends AccessibleJComponent
 103:     implements AccessibleSelection, ListSelectionListener, TableModelListener,
 104:     TableColumnModelListener, CellEditorListener, PropertyChangeListener,
 105:     AccessibleExtendedTable
 106:   {
 107: 
 108:     /**
 109:      * Provides accessibility support for table cells.
 110:      *
 111:      * @author Roman Kennke (kennke@aicas.com)
 112:      */
 113:     protected class AccessibleJTableCell
 114:       extends AccessibleContext
 115:       implements Accessible, AccessibleComponent
 116:     {
 117: 
 118:       /**
 119:        * The table of this cell.
 120:        */
 121:       private JTable table;
 122: 
 123:       /**
 124:        * The row index of this cell.
 125:        */
 126:       private int row;
 127: 
 128:       /**
 129:        * The column index of this cell.
 130:        */
 131:       private int column;
 132: 
 133:       /**
 134:        * The index of this cell inside the AccessibleJTable parent.
 135:        */
 136:       private int index;
 137: 
 138:       /**
 139:        * Creates a new <code>AccessibleJTableCell</code>.
 140:        *
 141:        * @param t the table
 142:        * @param r the row
 143:        * @param c the column
 144:        * @param i the index of this cell inside the accessible table parent
 145:        */
 146:       public AccessibleJTableCell(JTable t, int r, int c, int i)
 147:       {
 148:         table = t;
 149:         row = r;
 150:         column = c;
 151:         index = i;
 152:       }
 153: 
 154:       /**
 155:        * Returns the accessible row for the table cell.
 156:        *
 157:        * @return the accessible row for the table cell
 158:        */
 159:       public AccessibleRole getAccessibleRole()
 160:       {
 161:         // TODO: What is the role of the table cell?
 162:         return AccessibleRole.UNKNOWN;
 163:       }
 164: 
 165:       /**
 166:        * Returns the accessible state set of this accessible table cell.
 167:        *
 168:        * @return the accessible state set of this accessible table cell
 169:        */
 170:       public AccessibleStateSet getAccessibleStateSet()
 171:       {
 172:         // TODO: What state shoiuld be returned here?
 173:         return new AccessibleStateSet();
 174:       }
 175: 
 176:       /**
 177:        * Returns the index of this cell in the parent object.
 178:        *
 179:        * @return the index of this cell in the parent object
 180:        */
 181:       public int getAccessibleIndexInParent()
 182:       {
 183:         return index;
 184:       }
 185: 
 186:       /**
 187:        * Returns the number of children of this object. Table cells cannot have
 188:        * children, so we return <code>0</code> here.
 189:        *
 190:        * @return <code>0</code>
 191:        */
 192:       public int getAccessibleChildrenCount()
 193:       {
 194:         return 0;
 195:       }
 196: 
 197:       /**
 198:        * Returns the accessible child at index <code>i</code>. Table cells
 199:        * don't have children, so we return <code>null</code> here.
 200:        *
 201:        * @return <code>null</code>
 202:        */
 203:       public Accessible getAccessibleChild(int i)
 204:       {
 205:         return null;
 206:       }
 207: 
 208:       /**
 209:        * Returns the locale setting for this accessible table cell.
 210:        *
 211:        * @return the locale setting for this accessible table cell
 212:        */
 213:       public Locale getLocale()
 214:       {
 215:         // TODO: For now, we return english here. This must be fixed as soon
 216:         // as we have a localized Swing.
 217:         return Locale.ENGLISH;
 218:       }
 219: 
 220:       /**
 221:        * Returns the accessible context of this table cell. Since accessible
 222:        * table cells are their own accessible context, we return
 223:        * <code>this</code>.
 224:        *
 225:        * @return the accessible context of this table cell
 226:        */
 227:       public AccessibleContext getAccessibleContext()
 228:       {
 229:         return this;
 230:       }
 231: 
 232:       /**
 233:        * Returns the background color of this cell.
 234:        *
 235:        * @return the background color of this cell
 236:        */
 237:       public Color getBackground()
 238:       {
 239:         return table.getBackground();
 240:       }
 241: 
 242:       /**
 243:        * Sets the background of the cell. Since table cells cannot have
 244:        * individual background colors, this method does nothing. Set the
 245:        * background directly on the table instead.
 246:        * 
 247:        * @param color not used
 248:        */
 249:       public void setBackground(Color color)
 250:       {
 251:         // This method does nothing. See API comments.
 252:       }
 253: 
 254:       /**
 255:        * Returns the foreground color of the table cell.
 256:        *
 257:        * @return the foreground color of the table cell
 258:        */
 259:       public Color getForeground()
 260:       {
 261:         return table.getForeground();
 262:       }
 263: 
 264:       /**
 265:        * Sets the foreground of the cell. Since table cells cannot have
 266:        * individual foreground colors, this method does nothing. Set the
 267:        * foreground directly on the table instead.
 268:        * 
 269:        * @param color not used
 270:        */
 271:       public void setForeground(Color color)
 272:       {
 273:         // This method does nothing. See API comments.
 274:       }
 275: 
 276:       /**
 277:        * Returns the cursor for this table cell.
 278:        *
 279:        * @return the cursor for this table cell
 280:        */
 281:       public Cursor getCursor()
 282:       {
 283:         return table.getCursor();
 284:       }
 285: 
 286:       /**
 287:        * Sets the cursor of the cell. Since table cells cannot have
 288:        * individual cursors, this method does nothing. Set the
 289:        * cursor directly on the table instead.
 290:        * 
 291:        * @param cursor not used
 292:        */
 293:       public void setCursor(Cursor cursor)
 294:       {
 295:         // This method does nothing. See API comments.
 296:       }
 297: 
 298:       /**
 299:        * Returns the font of the table cell.
 300:        *
 301:        * @return the font of the table cell
 302:        */
 303:       public Font getFont()
 304:       {
 305:         return table.getFont();
 306:       }
 307: 
 308:       /**
 309:        * Sets the font of the cell. Since table cells cannot have
 310:        * individual fonts, this method does nothing. Set the
 311:        * font directly on the table instead.
 312:        * 
 313:        * @param font not used
 314:        */
 315:       public void setFont(Font font)
 316:       {
 317:         // This method does nothing. See API comments.
 318:       }
 319: 
 320:       /**
 321:        * Returns the font metrics for a specified font.
 322:        *
 323:        * @param font the font for which we return the metrics
 324:        *
 325:        * @return the font metrics for a specified font
 326:        */
 327:       public FontMetrics getFontMetrics(Font font)
 328:       {
 329:         return table.getFontMetrics(font);
 330:       }
 331: 
 332:       /**
 333:        * Returns <code>true</code> if this table cell is enabled,
 334:        * <code>false</code> otherwise.
 335:        *
 336:        * @return <code>true</code> if this table cell is enabled,
 337:        *         <code>false</code> otherwise
 338:        */
 339:       public boolean isEnabled()
 340:       {
 341:         return table.isEnabled();
 342:       }
 343: 
 344:       /**
 345:        * Table cells cannot be disabled or enabled individually, so this method
 346:        * does nothing. Set the enabled flag on the table itself.
 347:        *
 348:        * @param b not used here
 349:        */
 350:       public void setEnabled(boolean b)
 351:       {
 352:         // This method does nothing. See API comments.
 353:       }
 354: 
 355:       /**
 356:        * Returns <code>true</code> if this cell is visible, <code>false</code>
 357:        * otherwise.
 358:        *
 359:        * @return <code>true</code> if this cell is visible, <code>false</code>
 360:        *         otherwise
 361:        */
 362:       public boolean isVisible()
 363:       {
 364:         return table.isVisible();
 365:       }
 366: 
 367:       /**
 368:        * The visibility cannot be set on individual table cells, so this method
 369:        * does nothing. Set the visibility on the table itself.
 370:        *
 371:        * @param b not used
 372:        */
 373:       public void setVisible(boolean b)
 374:       {
 375:         // This method does nothing. See API comments.
 376:       }
 377: 
 378:       /**
 379:        * Returns <code>true</code> if this table cell is currently showing on
 380:        * screen.
 381:        *
 382:        * @return <code>true</code> if this table cell is currently showing on
 383:        *         screen
 384:        */
 385:       public boolean isShowing()
 386:       {
 387:         return table.isShowing();
 388:       }
 389: 
 390:       /**
 391:        * Returns <code>true</code> if this table cell contains the location
 392:        * at <code>point</code>, <code>false</code> otherwise.
 393:        * <code>point</code> is interpreted as relative to the coordinate system
 394:        * of the table cell.
 395:        *
 396:        * @return <code>true</code> if this table cell contains the location
 397:        *         at <code>point</code>, <code>false</code> otherwise
 398:        */
 399:       public boolean contains(Point point)
 400:       {
 401:         Rectangle cellRect = table.getCellRect(row, column, true);
 402:         cellRect.x = 0;
 403:         cellRect.y = 0;
 404:         return cellRect.contains(point);
 405:       }
 406: 
 407:       /**
 408:        * Returns the screen location of the table cell.
 409:        *
 410:        * @return the screen location of the table cell
 411:        */
 412:       public Point getLocationOnScreen()
 413:       {
 414:         Point tableLoc = table.getLocationOnScreen();
 415:         Rectangle cellRect = table.getCellRect(row, column, true);
 416:         tableLoc.x += cellRect.x;
 417:         tableLoc.y += cellRect.y;
 418:         return tableLoc;
 419:       }
 420: 
 421:       /**
 422:        * Returns the location of this cell relative to the table's bounds.
 423:        *
 424:        * @return the location of this cell relative to the table's bounds
 425:        */
 426:       public Point getLocation()
 427:       {
 428:         Rectangle cellRect = table.getCellRect(row, column, true);
 429:         return new Point(cellRect.x, cellRect.y);
 430:       }
 431: 
 432:       /**
 433:        * The location of the table cells cannot be manipulated directly, so
 434:        * this method does nothing.
 435:        *
 436:        * @param point not used
 437:        */
 438:       public void setLocation(Point point)
 439:       {
 440:         // This method does nothing. See API comments.
 441:       }
 442: 
 443:       /**
 444:        * Returns the bounds of the cell relative to its table.
 445:        *
 446:        * @return the bounds of the cell relative to its table
 447:        */
 448:       public Rectangle getBounds()
 449:       {
 450:         return table.getCellRect(row, column, true);
 451:       }
 452: 
 453:       /**
 454:        * The bounds of the table cells cannot be manipulated directly, so
 455:        * this method does nothing.
 456:        *
 457:        * @param rectangle not used
 458:        */
 459:       public void setBounds(Rectangle rectangle)
 460:       {
 461:         // This method does nothing. See API comments.
 462:       }
 463: 
 464:       /**
 465:        * Returns the size of the table cell.
 466:        *
 467:        * @return the size of the table cell
 468:        */
 469:       public Dimension getSize()
 470:       {
 471:         Rectangle cellRect = table.getCellRect(row, column, true);
 472:         return new Dimension(cellRect.width, cellRect.height);
 473:       }
 474: 
 475:       /**
 476:        * The size cannot be set on table cells directly, so this method does
 477:        * nothing.
 478:        *
 479:        * @param dimension not used
 480:        */
 481:       public void setSize(Dimension dimension)
 482:       {
 483:         // This method does nothing. See API comments.
 484:       }
 485: 
 486:       /**
 487:        * Table cells have no children, so we return <code>null</code> here.
 488:        *
 489:        * @return <code>null</code>
 490:        */
 491:       public Accessible getAccessibleAt(Point point)
 492:       {
 493:         return null;
 494:       }
 495: 
 496:       /**
 497:        * Returns <code>true</code> if this table cell is focus traversable,
 498:        * <code>false</code> otherwise.
 499:        *
 500:        * @return <code>true</code> if this table cell is focus traversable,
 501:        *         <code>false</code> otherwise
 502:        */
 503:       public boolean isFocusTraversable()
 504:       {
 505:         return table.isFocusable();
 506:       }
 507: 
 508:       /**
 509:        * Requests that this table cell gets the keyboard focus.
 510:        */
 511:       public void requestFocus()
 512:       {
 513:         // We first set the selection models' lead selection to this cell.
 514:         table.getColumnModel().getSelectionModel()
 515:         .setLeadSelectionIndex(column);
 516:         table.getSelectionModel().setLeadSelectionIndex(row);
 517:         // Now we request that the table receives focus.
 518:         table.requestFocus();
 519:       }
 520: 
 521:       /**
 522:        * Adds a focus listener to this cell. The focus listener is really
 523:        * added to the table, so there is no way to find out when an individual
 524:        * cell changes the focus.
 525:        *
 526:        * @param listener the focus listener to add
 527:        */
 528:       public void addFocusListener(FocusListener listener)
 529:       {
 530:         table.addFocusListener(listener);
 531:       }
 532: 
 533:       /**
 534:        * Removes a focus listener from the cell. The focus listener is really
 535:        * removed from the table.
 536:        *
 537:        * @param listener the listener to remove
 538:        */
 539:       public void removeFocusListener(FocusListener listener)
 540:       {
 541:         table.removeFocusListener(listener);
 542:       }
 543:         
 544:     }
 545: 
 546:     protected class AccessibleJTableModelChange
 547:       implements AccessibleTableModelChange
 548:     {
 549:       protected int type;
 550:       protected int firstRow;
 551:       protected int lastRow;
 552:       protected int firstColumn;
 553:       protected int lastColumn;
 554: 
 555:       protected AccessibleJTableModelChange(int type, int firstRow,
 556:                                             int lastRow, int firstColumn,
 557:                                             int lastColumn)
 558:       {
 559:         this.type = type;
 560:         this.firstRow = firstRow;
 561:         this.lastRow = lastRow;
 562:         this.firstColumn = firstColumn;
 563:         this.lastColumn = lastColumn;
 564:       }
 565: 
 566:       public int getType()
 567:       {
 568:         return type;
 569:       }
 570: 
 571:       public int getFirstRow()
 572:       {
 573:         return firstRow;
 574:       }
 575: 
 576:       public int getLastRow()
 577:       {
 578:         return lastRow;
 579:       }
 580: 
 581:       public int getFirstColumn()
 582:       {
 583:         return firstColumn;
 584:       }
 585: 
 586:       public int getLastColumn()
 587:       {
 588:         return lastColumn;
 589:       }
 590:     }
 591: 
 592:     /**
 593:      * Creates a new <code>AccessibleJTable</code>.
 594:      *
 595:      * @since JDK1.5
 596:      */
 597:     protected AccessibleJTable()
 598:     {
 599:       getModel().addTableModelListener(this);
 600:       getSelectionModel().addListSelectionListener(this);
 601:       getColumnModel().addColumnModelListener(this);
 602:       getCellEditor().addCellEditorListener(this);
 603:     }
 604: 
 605:     /**
 606:      * Returns the number of selected items in this table.
 607:      */
 608:     public int getAccessibleSelectionCount()
 609:     {
 610:       return getSelectedColumnCount();
 611:     }
 612: 
 613:     public Accessible getAccessibleSelection(int i)
 614:     {
 615:       // TODO Auto-generated method stub
 616:       return null;
 617:     }
 618: 
 619:     public boolean isAccessibleChildSelected(int i)
 620:     {
 621:       // TODO Auto-generated method stub
 622:       return false;
 623:     }
 624: 
 625:     public void addAccessibleSelection(int i)
 626:     {
 627:       // TODO Auto-generated method stub
 628:       
 629:     }
 630: 
 631:     public void removeAccessibleSelection(int i)
 632:     {
 633:       // TODO Auto-generated method stub
 634:       
 635:     }
 636: 
 637:     public void clearAccessibleSelection()
 638:     {
 639:       // TODO Auto-generated method stub
 640:       
 641:     }
 642: 
 643:     public void selectAllAccessibleSelection()
 644:     {
 645:       // TODO Auto-generated method stub
 646:       
 647:     }
 648: 
 649:     public void valueChanged(ListSelectionEvent event)
 650:     {
 651:       // TODO Auto-generated method stub
 652:       
 653:     }
 654: 
 655:     /**
 656:      * Receives notification when the table model changes. Depending on the
 657:      * type of change, this method calls {@link #tableRowsInserted} or
 658:      * {@link #tableRowsDeleted}.
 659:      *
 660:      * @param event the table model event
 661:      */
 662:     public void tableChanged(TableModelEvent event)
 663:     {
 664:       switch (event.getType())
 665:         {
 666:         case TableModelEvent.INSERT:
 667:           tableRowsInserted(event);
 668:           break;
 669:         case TableModelEvent.DELETE:
 670:           tableRowsDeleted(event);
 671:           break;
 672:         }
 673:     }
 674: 
 675:     /**
 676:      * Receives notification when one or more rows have been inserted into the
 677:      * table.
 678:      *
 679:      * @param event the table model event
 680:      */
 681:     public void tableRowsInserted(TableModelEvent event)
 682:     {
 683:       // TODO: What to do here, if anything? This might be a hook method for
 684:       // subclasses...
 685:     }
 686: 
 687:     /**
 688:      * Receives notification when one or more rows have been deleted from the
 689:      * table.
 690:      *
 691:      * @param event the table model event
 692:      */
 693:     public void tableRowsDeleted(TableModelEvent event)
 694:     {
 695:       // TODO: What to do here, if anything? This might be a hook method for
 696:       // subclasses...
 697:     }
 698: 
 699:     public void columnAdded(TableColumnModelEvent event)
 700:     {
 701:       // TODO Auto-generated method stub
 702:       
 703:     }
 704: 
 705:     public void columnMarginChanged(ChangeEvent event)
 706:     {
 707:       // TODO Auto-generated method stub
 708:       
 709:     }
 710: 
 711:     public void columnMoved(TableColumnModelEvent event)
 712:     {
 713:       // TODO Auto-generated method stub
 714:       
 715:     }
 716: 
 717:     public void columnRemoved(TableColumnModelEvent event)
 718:     {
 719:       // TODO Auto-generated method stub
 720:       
 721:     }
 722: 
 723:     public void columnSelectionChanged(ListSelectionEvent event)
 724:     {
 725:       // TODO Auto-generated method stub
 726:       
 727:     }
 728: 
 729:     public void editingCanceled(ChangeEvent event)
 730:     {
 731:       // TODO Auto-generated method stub
 732:       
 733:     }
 734: 
 735:     public void editingStopped(ChangeEvent event)
 736:     {
 737:       // TODO Auto-generated method stub
 738:       
 739:     }
 740: 
 741:     /**
 742:      * Receives notification when any of the JTable's properties changes. This
 743:      * is used to replace the listeners on the table's model, selection model,
 744:      * column model and cell editor.
 745:      *
 746:      * @param e the property change event
 747:      */
 748:     public void propertyChange(PropertyChangeEvent e)
 749:     {
 750:       String propName = e.getPropertyName(); 
 751:       if (propName.equals("tableModel"))
 752:         {
 753:           TableModel oldModel = (TableModel) e.getOldValue();
 754:           oldModel.removeTableModelListener(this);
 755:           TableModel newModel = (TableModel) e.getNewValue();
 756:           newModel.addTableModelListener(this);
 757:         }
 758:       else if (propName.equals("columnModel"))
 759:         {
 760:           TableColumnModel oldModel = (TableColumnModel) e.getOldValue();
 761:           oldModel.removeColumnModelListener(this);
 762:           TableColumnModel newModel = (TableColumnModel) e.getNewValue();
 763:           newModel.addColumnModelListener(this);
 764:         }
 765:       else if (propName.equals("selectionModel"))
 766:         {
 767:           ListSelectionModel oldModel = (ListSelectionModel) e.getOldValue();
 768:           oldModel.removeListSelectionListener(this);
 769:           ListSelectionModel newModel = (ListSelectionModel) e.getNewValue();
 770:           newModel.addListSelectionListener(this);
 771:         }
 772:       else if (propName.equals("cellEditor"))
 773:         {
 774:           CellEditor oldEd = (CellEditor) e.getOldValue();
 775:           oldEd.removeCellEditorListener(this);
 776:           CellEditor newEd = (CellEditor) e.getNewValue();
 777:           newEd.addCellEditorListener(this);
 778:         }
 779:     }
 780: 
 781:     public int getAccessibleRow(int index)
 782:     {
 783:       // TODO Auto-generated method stub
 784:       return 0;
 785:     }
 786: 
 787:     public int getAccessibleColumn(int index)
 788:     {
 789:       // TODO Auto-generated method stub
 790:       return 0;
 791:     }
 792: 
 793:     public int getAccessibleIndex(int r, int c)
 794:     {
 795:       // TODO Auto-generated method stub
 796:       return 0;
 797:     }
 798: 
 799:     public Accessible getAccessibleCaption()
 800:     {
 801:       // TODO Auto-generated method stub
 802:       return null;
 803:     }
 804: 
 805:     public void setAccessibleCaption(Accessible caption)
 806:     {
 807:       // TODO Auto-generated method stub
 808:       
 809:     }
 810: 
 811:     public Accessible getAccessibleSummary()
 812:     {
 813:       // TODO Auto-generated method stub
 814:       return null;
 815:     }
 816: 
 817:     public void setAccessibleSummary(Accessible summary)
 818:     {
 819:       // TODO Auto-generated method stub
 820:       
 821:     }
 822: 
 823:     public int getAccessibleRowCount()
 824:     {
 825:       // TODO Auto-generated method stub
 826:       return 0;
 827:     }
 828: 
 829:     public int getAccessibleColumnCount()
 830:     {
 831:       // TODO Auto-generated method stub
 832:       return 0;
 833:     }
 834: 
 835:     public Accessible getAccessibleAt(int r, int c)
 836:     {
 837:       // TODO Auto-generated method stub
 838:       return null;
 839:     }
 840: 
 841:     public int getAccessibleRowExtentAt(int r, int c)
 842:     {
 843:       // TODO Auto-generated method stub
 844:       return 0;
 845:     }
 846: 
 847:     public int getAccessibleColumnExtentAt(int r, int c)
 848:     {
 849:       // TODO Auto-generated method stub
 850:       return 0;
 851:     }
 852: 
 853:     public AccessibleTable getAccessibleRowHeader()
 854:     {
 855:       // TODO Auto-generated method stub
 856:       return null;
 857:     }
 858: 
 859:     public void setAccessibleRowHeader(AccessibleTable header)
 860:     {
 861:       // TODO Auto-generated method stub
 862:       
 863:     }
 864: 
 865:     public AccessibleTable getAccessibleColumnHeader()
 866:     {
 867:       // TODO Auto-generated method stub
 868:       return null;
 869:     }
 870: 
 871:     public void setAccessibleColumnHeader(AccessibleTable header)
 872:     {
 873:       // TODO Auto-generated method stub
 874:       
 875:     }
 876: 
 877:     public Accessible getAccessibleRowDescription(int r)
 878:     {
 879:       // TODO Auto-generated method stub
 880:       return null;
 881:     }
 882: 
 883:     public void setAccessibleRowDescription(int r, Accessible description)
 884:     {
 885:       // TODO Auto-generated method stub
 886:       
 887:     }
 888: 
 889:     public Accessible getAccessibleColumnDescription(int c)
 890:     {
 891:       // TODO Auto-generated method stub
 892:       return null;
 893:     }
 894: 
 895:     public void setAccessibleColumnDescription(int c, Accessible description)
 896:     {
 897:       // TODO Auto-generated method stub
 898:       
 899:     }
 900: 
 901:     public boolean isAccessibleSelected(int r, int c)
 902:     {
 903:       // TODO Auto-generated method stub
 904:       return false;
 905:     }
 906: 
 907:     public boolean isAccessibleRowSelected(int r)
 908:     {
 909:       // TODO Auto-generated method stub
 910:       return false;
 911:     }
 912: 
 913:     public boolean isAccessibleColumnSelected(int c)
 914:     {
 915:       // TODO Auto-generated method stub
 916:       return false;
 917:     }
 918: 
 919:     public int[] getSelectedAccessibleRows()
 920:     {
 921:       // TODO Auto-generated method stub
 922:       return null;
 923:     }
 924: 
 925:     public int[] getSelectedAccessibleColumns()
 926:     {
 927:       // TODO Auto-generated method stub
 928:       return null;
 929:     }
 930:       
 931:   }
 932:   /**
 933:    * Handles property changes from the <code>TableColumn</code>s of this
 934:    * <code>JTable</code>.
 935:    *
 936:    * More specifically, this triggers a {@link #revalidate()} call if the
 937:    * preferredWidth of one of the observed columns changes.
 938:    */
 939:   class TableColumnPropertyChangeHandler implements PropertyChangeListener
 940:   {
 941:     /**
 942:      * Receives notification that a property of the observed TableColumns
 943:      * has changed.
 944:      *
 945:      * @param ev the property change event
 946:      */
 947:     public void propertyChange(PropertyChangeEvent ev)
 948:     {
 949:       if (ev.getPropertyName().equals("preferredWidth"))
 950:         {
 951:           JTableHeader header = getTableHeader();
 952:           TableColumn col = (TableColumn) ev.getSource();
 953:           header.setResizingColumn(col);
 954:           doLayout();
 955:           header.setResizingColumn(null);
 956:         }
 957:     }
 958:   }
 959: 
 960:   /**
 961:    * A cell renderer for boolean values.
 962:    */
 963:   private class BooleanCellRenderer
 964:     extends DefaultTableCellRenderer
 965:   {
 966: 
 967:     /**
 968:      * The CheckBox that is used for rendering.
 969:      */
 970:     private JCheckBox checkBox = new JCheckBox();
 971: 
 972:     /**
 973:      * Returns the component that is used for rendering the value.
 974:      *
 975:      * @param table the JTable
 976:      * @param value the value of the object
 977:      * @param isSelected is the cell selected?
 978:      * @param hasFocus has the cell the focus?
 979:      * @param row the row to render
 980:      * @param column the cell to render
 981:      * 
 982:      * @return this component (the default table cell renderer)
 983:      */
 984:     public Component getTableCellRendererComponent(JTable table, Object value,
 985:                                                    boolean isSelected,
 986:                                                    boolean hasFocus, int row,
 987:                                                    int column)
 988:     {
 989:       Boolean boolValue = (Boolean) value;
 990:       checkBox.setSelected(boolValue.booleanValue());
 991:       return checkBox;
 992:     }
 993:   }
 994: 
 995:   /**
 996:    * A cell renderer for Date values.
 997:    */
 998:   private class DateCellRenderer
 999:     extends DefaultTableCellRenderer
1000:   {
1001:     /**
1002:      * Returns the component that is used for rendering the value.
1003:      *
1004:      * @param table the JTable
1005:      * @param value the value of the object
1006:      * @param isSelected is the cell selected?
1007:      * @param hasFocus has the cell the focus?
1008:      * @param row the row to render
1009:      * @param column the cell to render
1010:      * 
1011:      * @return this component (the default table cell renderer)
1012:      */
1013:     public Component getTableCellRendererComponent(JTable table, Object value,
1014:                                                    boolean isSelected,
1015:                                                    boolean hasFocus, int row,
1016:                                                    int column)
1017:     {
1018:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1019:                                           row, column);
1020:       if (value instanceof Date)
1021:         {
1022:           Date dateValue = (Date) value;
1023:           DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
1024:           setText(df.format(dateValue));
1025:         }
1026:       return this;
1027:     }
1028:   }
1029: 
1030:   /**
1031:    * A cell renderer for Double values.
1032:    */
1033:   private class DoubleCellRenderer
1034:     extends DefaultTableCellRenderer
1035:   {
1036:     /**
1037:      * Creates a new instance of NumberCellRenderer.
1038:      */
1039:     public DoubleCellRenderer()
1040:     {
1041:       setHorizontalAlignment(JLabel.RIGHT);
1042:     }
1043: 
1044:     /**
1045:      * Returns the component that is used for rendering the value.
1046:      *
1047:      * @param table the JTable
1048:      * @param value the value of the object
1049:      * @param isSelected is the cell selected?
1050:      * @param hasFocus has the cell the focus?
1051:      * @param row the row to render
1052:      * @param column the cell to render
1053:      * 
1054:      * @return this component (the default table cell renderer)
1055:      */
1056:     public Component getTableCellRendererComponent(JTable table, Object value,
1057:                                                    boolean isSelected,
1058:                                                    boolean hasFocus, int row,
1059:                                                    int column)
1060:     {
1061:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1062:                                           row, column);
1063:       if (value instanceof Double)
1064:         {
1065:           Double doubleValue = (Double) value;
1066:           NumberFormat nf = NumberFormat.getInstance();
1067:           setText(nf.format(doubleValue.doubleValue()));
1068:         }
1069:       return this;
1070:     }
1071:   }
1072: 
1073:   /**
1074:    * A cell renderer for Float values.
1075:    */
1076:   private class FloatCellRenderer
1077:     extends DefaultTableCellRenderer
1078:   {
1079:     /**
1080:      * Creates a new instance of NumberCellRenderer.
1081:      */
1082:     public FloatCellRenderer()
1083:     {
1084:       setHorizontalAlignment(JLabel.RIGHT);
1085:     }
1086: 
1087:     /**
1088:      * Returns the component that is used for rendering the value.
1089:      *
1090:      * @param table the JTable
1091:      * @param value the value of the object
1092:      * @param isSelected is the cell selected?
1093:      * @param hasFocus has the cell the focus?
1094:      * @param row the row to render
1095:      * @param column the cell to render
1096:      * 
1097:      * @return this component (the default table cell renderer)
1098:      */
1099:     public Component getTableCellRendererComponent(JTable table, Object value,
1100:                                                    boolean isSelected,
1101:                                                    boolean hasFocus, int row,
1102:                                                    int column)
1103:     {
1104:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1105:                                           row, column);
1106:       if (value instanceof Float)
1107:         {
1108:           Float floatValue = (Float) value;
1109:           NumberFormat nf = NumberFormat.getInstance();
1110:           setText(nf.format(floatValue.floatValue()));
1111:         }
1112:       return this;
1113:     }
1114:   }
1115: 
1116:   /**
1117:    * A cell renderer for Number values.
1118:    */
1119:   private class NumberCellRenderer
1120:     extends DefaultTableCellRenderer
1121:   {
1122:     /**
1123:      * Creates a new instance of NumberCellRenderer.
1124:      */
1125:     public NumberCellRenderer()
1126:     {
1127:       setHorizontalAlignment(JLabel.RIGHT);
1128:     }
1129:   }
1130: 
1131:   /**
1132:    * A cell renderer for Icon values.
1133:    */
1134:   private class IconCellRenderer
1135:     extends DefaultTableCellRenderer
1136:   {
1137:     /**
1138:      * Returns the component that is used for rendering the value.
1139:      *
1140:      * @param table the JTable
1141:      * @param value the value of the object
1142:      * @param isSelected is the cell selected?
1143:      * @param hasFocus has the cell the focus?
1144:      * @param row the row to render
1145:      * @param column the cell to render
1146:      * 
1147:      * @return this component (the default table cell renderer)
1148:      */
1149:     public Component getTableCellRendererComponent(JTable table, Object value,
1150:                                                    boolean isSelected,
1151:                                                    boolean hasFocus, int row,
1152:                                                    int column)
1153:     {
1154:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1155:                                           row, column);
1156:       if (value instanceof Icon)
1157:         {
1158:           Icon iconValue = (Icon) value;
1159:           setIcon(iconValue);
1160:         }
1161:       return this;
1162:     }
1163:   }
1164: 
1165:   private static final long serialVersionUID = 3876025080382781659L;
1166: 
1167: 
1168:   /**
1169:    * When resizing columns, do not automatically change any columns. In this
1170:    * case the table should be enclosed in a {@link JScrollPane} in order to
1171:    * accomodate cases in which the table size exceeds its visible area.
1172:    */
1173:   public static final int AUTO_RESIZE_OFF = 0;
1174: 
1175:   /**
1176:    * When resizing column <code>i</code>, automatically change only the
1177:    * single column <code>i+1</code> to provide or absorb excess space
1178:    * requirements.
1179:    */
1180:   public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
1181: 
1182:   /**
1183:    * When resizing column <code>i</code> in a table of <code>n</code>
1184:    * columns, automatically change all columns in the range <code>[i+1,
1185:    * n)</code>, uniformly, to provide or absorb excess space requirements.
1186:    */
1187:   public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
1188:   
1189:   /**
1190:    * When resizing column <code>i</code> in a table of <code>n</code>
1191:    * columns, automatically change all columns in the range <code>[0,
1192:    * n)</code> (with the exception of column i) uniformly, to provide or
1193:    * absorb excess space requirements.
1194:    */
1195:   public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
1196: 
1197:   /**
1198:    * When resizing column <code>i</code> in a table of <code>n</code>
1199:    * columns, automatically change column <code>n-1</code> (the last column
1200:    * in the table) to provide or absorb excess space requirements.
1201:    */
1202:   public static final int AUTO_RESIZE_LAST_COLUMN = 3;
1203: 
1204: 
1205:   /**
1206:    * A table mapping {@link java.lang.Class} objects to 
1207:    * {@link TableCellEditor} objects. This table is consulted by the 
1208:    * FIXME
1209:    */
1210:   protected Hashtable defaultEditorsByColumnClass;
1211: 
1212:   /**
1213:    * A table mapping {@link java.lang.Class} objects to 
1214:    * {@link TableCellEditor} objects. This table is consulted by the 
1215:    * FIXME
1216:    */
1217:   protected Hashtable defaultRenderersByColumnClass;
1218: 
1219:   /**
1220:    * The column that is edited, -1 if the table is not edited currently.
1221:    */
1222:   protected int editingColumn;
1223: 
1224:   /**
1225:    * The row that is edited, -1 if the table is not edited currently.
1226:    */
1227:   protected int editingRow;
1228: 
1229:   /**
1230:    * The component that is used for editing.
1231:    * <code>null</code> if the table is not editing currently.
1232:    *
1233:    */
1234:   protected transient Component editorComp;
1235: 
1236: 
1237:   /**
1238:    * Whether or not the table should automatically compute a matching
1239:    * {@link TableColumnModel} and assign it to the {@link #columnModel}
1240:    * property when the {@link #dataModel} property is changed. 
1241:    *
1242:    * @see #setModel(TableModel)
1243:    * @see #createDefaultColumnsFromModel()
1244:    * @see #setColumnModel(TableColumnModel)
1245:    * @see #setAutoCreateColumnsFromModel(boolean)
1246:    * @see #getAutoCreateColumnsFromModel()
1247:    */
1248:   protected boolean autoCreateColumnsFromModel;
1249: 
1250:   /**
1251:    * A numeric code specifying the resizing behavior of the table. Must be
1252:    * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link
1253:    * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link
1254:    * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}.
1255:    * 
1256:    * @see #doLayout()
1257:    * @see #setAutoResizeMode(int)
1258:    * @see #getAutoResizeMode()
1259:    */
1260:   protected int autoResizeMode;
1261: 
1262:   /**
1263:    * The height in pixels of any row of the table. All rows in a table are
1264:    * of uniform height. This differs from column width, which varies on a
1265:    * per-column basis, and is stored in the individual columns of the
1266:    * {@link #columnModel}.
1267:    * 
1268:    * @see #getRowHeight()
1269:    * @see #setRowHeight(int)
1270:    * @see TableColumn#getWidth()
1271:    * @see TableColumn#setWidth(int)
1272:    */
1273:   protected int rowHeight;
1274: 
1275:   /**
1276:    * The height in pixels of the gap left between any two rows of the table. 
1277:    * 
1278:    * @see #setRowMargin(int)
1279:    * @see #getRowHeight()
1280:    * @see #getIntercellSpacing()
1281:    * @see #setIntercellSpacing(Dimension)
1282:    * @see TableColumnModel#getColumnMargin()
1283:    * @see TableColumnModel#setColumnMargin(int)
1284:    */
1285:   protected int rowMargin;
1286: 
1287:   /**
1288:    * Whether or not the table should allow row selection. If the table
1289:    * allows both row <em>and</em> column selection, it is said to allow
1290:    * "cell selection". Previous versions of the JDK supported cell
1291:    * selection as an independent concept, but it is now represented solely
1292:    * in terms of simultaneous row and column selection.
1293:    *
1294:    * @see TableColumnModel#getColumnSelectionAllowed()
1295:    * @see #setRowSelectionAllowed(boolean)
1296:    * @see #getRowSelectionAllowed()
1297:    * @see #getCellSelectionEnabled()
1298:    * @see #setCellSelectionEnabled(boolean)
1299:    */
1300:   protected boolean rowSelectionAllowed;
1301: 
1302:   /**
1303:    * @deprecated Use {@link #rowSelectionAllowed}, {@link 
1304:    * #getColumnSelectionAllowed}, or the combined methods {@link
1305:    * #getCellSelectionEnabled} and {@link #setCellSelectionEnabled(boolean)}.
1306:    */
1307:   protected boolean cellSelectionEnabled;
1308:   
1309:   /**
1310:    * The model for data stored in the table. Confusingly, the published API
1311:    * requires that this field be called <code>dataModel</code>, despite its
1312:    * property name. The table listens to its model as a {@link
1313:    * TableModelListener}.
1314:    *
1315:    * @see #tableChanged(TableModelEvent)
1316:    * @see TableModel#addTableModelListener(TableModelListener)
1317:    */
1318:   protected TableModel dataModel;
1319: 
1320:   /**
1321:    * <p>A model of various aspects of the columns of the table, <em>not
1322:    * including</em> the data stored in them. The {@link TableColumnModel}
1323:    * is principally concerned with holding a set of {@link TableColumn}
1324:    * objects, each of which describes the display parameters of a column
1325:    * and the numeric index of the column from the data model which the
1326:    * column is presenting.</p>
1327:    *
1328:    * <p>The TableColumnModel also contains a {@link ListSelectionModel} which
1329:    * indicates which columns are currently selected. This selection model
1330:    * works in combination with the {@link #selectionModel} of the table
1331:    * itself to specify a <em>table selection</em>: a combination of row and
1332:    * column selections.</p>
1333:    *
1334:    * <p>Most application programmers do not need to work with this property
1335:    * at all: setting {@link #autoCreateColumnsFromModel} will construct the
1336:    * columnModel automatically, and the table acts as a facade for most of
1337:    * the interesting properties of the columnModel anyways.</p>
1338:    * 
1339:    * @see #setColumnModel(TableColumnModel)
1340:    * @see #getColumnModel()
1341:    */
1342:   protected TableColumnModel columnModel;
1343: 
1344:   /**
1345:    * A model of the rows of this table which are currently selected. This
1346:    * model is used in combination with the column selection model held as a
1347:    * member of the {@link #columnModel} property, to represent the rows and
1348:    * columns (or both: cells) of the table which are currently selected.
1349:    *
1350:    * @see #rowSelectionAllowed
1351:    * @see #setSelectionModel(ListSelectionModel)
1352:    * @see #getSelectionModel()
1353:    * @see TableColumnModel#getSelectionModel()
1354:    * @see ListSelectionModel#addListSelectionListener(ListSelectionListener)   
1355:    */
1356:   protected ListSelectionModel selectionModel;
1357: 
1358:   /**
1359:    * The current cell editor. 
1360:    */
1361:   protected TableCellEditor cellEditor;
1362: 
1363:   /**
1364:    * Whether or not drag-and-drop is enabled on this table.
1365:    *
1366:    * @see #setDragEnabled(boolean)
1367:    * @see #getDragEnabled()
1368:    */
1369:   private boolean dragEnabled;
1370: 
1371:   /**
1372:    * The color to paint the grid lines of the table, when either {@link
1373:    * #showHorizontalLines} or {@link #showVerticalLines} is set.
1374:    *
1375:    * @see #setGridColor(Color)
1376:    * @see #getGridColor()
1377:    */
1378:   protected Color gridColor;
1379: 
1380:   /**
1381:    * The size this table would prefer its viewport assume, if it is
1382:    * contained in a {@link JScrollPane}.
1383:    *
1384:    * @see #setPreferredScrollableViewportSize(Dimension)
1385:    * @see #getPreferredScrollableViewportSize()
1386:    */
1387:   protected Dimension preferredViewportSize;
1388: 
1389:   /**
1390:    * The color to paint the background of selected cells. Fires a property
1391:    * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY}
1392:    * when its value changes.
1393:    *
1394:    * @see #setSelectionBackground(Color)
1395:    * @see #getSelectionBackground()
1396:    */
1397:   protected Color selectionBackground;
1398: 
1399:   /**
1400:    * The name carried in property change events when the {@link
1401:    * #selectionBackground} property changes.
1402:    */
1403:   private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY = "selectionBackground";
1404: 
1405:   /**
1406:    * The color to paint the foreground of selected cells. Fires a property
1407:    * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY}
1408:    * when its value changes.
1409:    *
1410:    * @see #setSelectionForeground(Color)
1411:    * @see #getSelectionForeground()
1412:    */
1413:   protected Color selectionForeground;
1414: 
1415:   /**
1416:    * The name carried in property change events when the
1417:    * {@link #selectionForeground} property changes.
1418:    */
1419:   private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY = "selectionForeground";
1420: 
1421:   /**
1422:    * The showHorizontalLines property.
1423:    */
1424:   protected boolean showHorizontalLines;
1425: 
1426:   /**
1427:    * The showVerticalLines property.
1428:    */
1429:   protected boolean showVerticalLines;
1430: 
1431:   /**
1432:    * The tableHeader property.
1433:    */
1434:   protected JTableHeader tableHeader;
1435: 
1436:   /**
1437:    * The row of the cell being edited.
1438:    */
1439:   int rowBeingEdited = -1;
1440: 
1441:   /**
1442:    * The column of the cell being edited.
1443:    */
1444:   int columnBeingEdited = -1;
1445: 
1446:   /**
1447:    * The action listener for the editor's Timer.
1448:    */
1449:   Timer editorTimer = new EditorUpdateTimer();
1450: 
1451:   /**
1452:    * Stores the old value of a cell before it was edited, in case
1453:    * editing is cancelled
1454:    */
1455:   Object oldCellValue;
1456: 
1457:   /**
1458:    * The property handler for this table's columns.
1459:    */
1460:   TableColumnPropertyChangeHandler tableColumnPropertyChangeHandler =
1461:     new TableColumnPropertyChangeHandler();
1462: 
1463:   /**
1464:    * Creates a new <code>JTable</code> instance.
1465:    */
1466:   public JTable ()
1467:   {
1468:     this(null, null, null);
1469:   }
1470: 
1471:   /**
1472:    * Creates a new <code>JTable</code> instance.
1473:    *
1474:    * @param numRows an <code>int</code> value
1475:    * @param numColumns an <code>int</code> value
1476:    */
1477:   public JTable (int numRows, int numColumns)
1478:   {
1479:     this(new DefaultTableModel(numRows, numColumns));
1480:   }
1481: 
1482:   /**
1483:    * Creates a new <code>JTable</code> instance.
1484:    *
1485:    * @param data an <code>Object[][]</code> value
1486:    * @param columnNames an <code>Object[]</code> value
1487:    */
1488:   public JTable(Object[][] data, Object[] columnNames)
1489:   {
1490:     this(new DefaultTableModel(data, columnNames));
1491:   }
1492: 
1493:   /**
1494:    * Creates a new <code>JTable</code> instance.
1495:    *
1496:    * @param dm a <code>TableModel</code> value
1497:    */
1498:   public JTable (TableModel dm)
1499:   {
1500:     this(dm, null, null);
1501:   }
1502: 
1503:   /**
1504:    * Creates a new <code>JTable</code> instance.
1505:    *
1506:    * @param dm a <code>TableModel</code> value
1507:    * @param cm a <code>TableColumnModel</code> value
1508:    */
1509:   public JTable (TableModel dm, TableColumnModel cm)
1510:   {
1511:     this(dm, cm, null);
1512:   }
1513: 
1514:   /**
1515:    * Creates a new <code>JTable</code> instance.
1516:    *
1517:    * @param dm a <code>TableModel</code> value
1518:    * @param cm a <code>TableColumnModel</code> value
1519:    * @param sm a <code>ListSelectionModel</code> value
1520:    */
1521:   public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm)
1522:   {
1523:     boolean autoCreate = false;
1524:     if (cm != null)
1525:         setColumnModel(cm);
1526:     else 
1527:       {
1528:         setColumnModel(createDefaultColumnModel());
1529:         autoCreate = true;
1530:       }        
1531:     setSelectionModel(sm == null ? createDefaultSelectionModel() : sm);
1532:     setModel(dm == null ? createDefaultDataModel() : dm);
1533:     setAutoCreateColumnsFromModel(autoCreate);
1534:     initializeLocalVars();
1535:     // The following four lines properly set the lead selection indices.
1536:     // After this, the UI will handle the lead selection indices.
1537:     // FIXME: this should probably not be necessary, if the UI is installed
1538:     // before the TableModel is set then the UI will handle things on its
1539:     // own, but certain variables need to be set before the UI can be installed
1540:     // so we must get the correct order for all the method calls in this
1541:     // constructor.
1542:     selectionModel.setAnchorSelectionIndex(0);    
1543:     selectionModel.setLeadSelectionIndex(0);
1544:     columnModel.getSelectionModel().setAnchorSelectionIndex(0);
1545:     columnModel.getSelectionModel().setLeadSelectionIndex(0);
1546:     updateUI();
1547:   }    
1548: 
1549:   protected void initializeLocalVars()
1550:   {
1551:     setTableHeader(createDefaultTableHeader());
1552:     if (autoCreateColumnsFromModel)
1553:       createDefaultColumnsFromModel();
1554:     this.columnModel.addColumnModelListener(this);
1555:     
1556:     this.defaultRenderersByColumnClass = new Hashtable();
1557:     createDefaultRenderers();
1558: 
1559:     this.defaultEditorsByColumnClass = new Hashtable();
1560:     createDefaultEditors();
1561: 
1562:     this.autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS;
1563:     this.rowHeight = 16;
1564:     this.rowMargin = 1;
1565:     this.rowSelectionAllowed = true;
1566:     // this.accessibleContext = new AccessibleJTable();
1567:     this.cellEditor = null;
1568:     // COMPAT: Both Sun and IBM have drag enabled
1569:     this.dragEnabled = true;
1570:     this.preferredViewportSize = new Dimension(450,400);
1571:     this.showHorizontalLines = true;
1572:     this.showVerticalLines = true;
1573:     this.editingColumn = -1;
1574:     this.editingRow = -1;
1575:     setIntercellSpacing(new Dimension(1,1));
1576:   }
1577: 
1578:   /**
1579:    * Creates a new <code>JTable</code> instance.
1580:    *
1581:    * @param data a <code>Vector</code> value
1582:    * @param columnNames a <code>Vector</code> value
1583:    */
1584:   public JTable(Vector data, Vector columnNames)
1585:   {
1586:     this(new DefaultTableModel(data, columnNames));
1587:   }
1588: 
1589:   /**
1590:    * The timer that updates the editor component.
1591:    */
1592:   private class EditorUpdateTimer
1593:     extends Timer
1594:     implements ActionListener
1595:   {
1596:     /**
1597:      * Creates a new EditorUpdateTimer object with a default delay of 0.5 seconds.
1598:      */
1599:     public EditorUpdateTimer()
1600:     {
1601:       super(500, null);
1602:       addActionListener(this);
1603:     }
1604: 
1605:     /**
1606:      * Lets the caret blink and repaints the table.
1607:      */
1608:     public void actionPerformed(ActionEvent ev)
1609:     {
1610:       Caret c = ((JTextField)JTable.this.editorComp).getCaret();
1611:       if (c != null)
1612:         c.setVisible(!c.isVisible());
1613:       JTable.this.repaint();
1614:     }
1615: 
1616:     /**
1617:      * Updates the blink delay according to the current caret.
1618:      */
1619:     public void update()
1620:     {
1621:       stop();
1622:       Caret c = ((JTextField)JTable.this.editorComp).getCaret();
1623:       if (c != null)
1624:     {
1625:       setDelay(c.getBlinkRate());
1626:       if (((JTextField)JTable.this.editorComp).isEditable())
1627:         start();
1628:       else
1629:         c.setVisible(false);
1630:     }
1631:     }
1632:   }
1633: 
1634:   public void addColumn(TableColumn column)
1635:   {
1636:     if (column.getHeaderValue() == null)
1637:       {
1638:         String name = dataModel.getColumnName(column.getModelIndex());
1639:         column.setHeaderValue(name);
1640:       }
1641:     
1642:     columnModel.addColumn(column);
1643:     column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
1644:   }
1645: 
1646:   protected void createDefaultEditors()
1647:   {
1648:     //FIXME: Create the editor object.
1649:   }
1650: 
1651:   protected void createDefaultRenderers()
1652:   {
1653:     setDefaultRenderer(Boolean.class, new BooleanCellRenderer());
1654:     setDefaultRenderer(Number.class, new NumberCellRenderer());
1655:     setDefaultRenderer(Double.class, new DoubleCellRenderer());
1656:     setDefaultRenderer(Double.class, new FloatCellRenderer());
1657:     setDefaultRenderer(Date.class, new DateCellRenderer());
1658:     setDefaultRenderer(Icon.class, new IconCellRenderer());
1659:   }
1660:   
1661:   /**
1662:    * @deprecated 1.0.2, replaced by <code>new JScrollPane(JTable)</code>
1663:    */
1664:   public static JScrollPane createScrollPaneForTable(JTable table)
1665:   {
1666:     return new JScrollPane(table);
1667:   }
1668: 
1669:   protected TableColumnModel createDefaultColumnModel()
1670:   {
1671:     return new DefaultTableColumnModel();
1672:   }
1673: 
1674:   protected TableModel createDefaultDataModel()
1675:   {
1676:     return new DefaultTableModel();
1677:   }
1678: 
1679:   protected ListSelectionModel createDefaultSelectionModel()
1680:   {
1681:     return new DefaultListSelectionModel();
1682:   }
1683: 
1684:   protected JTableHeader createDefaultTableHeader()
1685:   {
1686:     return new JTableHeader(columnModel);
1687:   }
1688:  
1689:   // listener support 
1690: 
1691:   public void columnAdded (TableColumnModelEvent event)
1692:   {
1693:     revalidate();
1694:     repaint();
1695:   }
1696: 
1697:   public void columnMarginChanged (ChangeEvent event)
1698:   {
1699:     revalidate();
1700:     repaint();
1701:   }
1702: 
1703:   public void columnMoved (TableColumnModelEvent event)
1704:   {
1705:     revalidate();
1706:     repaint();
1707:   }
1708: 
1709:   public void columnRemoved (TableColumnModelEvent event)
1710:   {
1711:     revalidate();
1712:     repaint();
1713:   }
1714:   
1715:   public void columnSelectionChanged (ListSelectionEvent event)
1716:   {
1717:     repaint();
1718:   }
1719: 
1720:   public void editingCanceled (ChangeEvent event)
1721:   {
1722:     if (rowBeingEdited > -1 && columnBeingEdited > -1)
1723:       {
1724:         if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField)
1725:           {
1726:             remove ((Component)getValueAt(rowBeingEdited, columnBeingEdited));
1727:             setValueAt(oldCellValue, rowBeingEdited, columnBeingEdited);
1728:           }
1729:         rowBeingEdited = -1;
1730:         columnBeingEdited = -1;
1731:       }
1732:     editorTimer.stop();
1733:     editorComp = null;
1734:     cellEditor = null;
1735:     requestFocusInWindow(false);
1736:     repaint();
1737:   }
1738: 
1739:   public void editingStopped (ChangeEvent event)
1740:   {
1741:     if (rowBeingEdited > -1 && columnBeingEdited > -1)
1742:       {
1743:         if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField)
1744:           {
1745:             remove((Component)getValueAt(rowBeingEdited, columnBeingEdited));
1746:             setValueAt(((JTextField)editorComp).getText(), 
1747:                        rowBeingEdited, columnBeingEdited);
1748:           }
1749:         rowBeingEdited = -1;
1750:         columnBeingEdited = -1;
1751:       }
1752:     editorTimer.stop();
1753:     editorComp = null;
1754:     cellEditor = null;
1755:     requestFocusInWindow(false);
1756:     repaint();
1757:   }
1758: 
1759:   public void tableChanged (TableModelEvent event)
1760:   {
1761:     // update the column model from the table model if the structure has
1762:     // changed and the flag autoCreateColumnsFromModel is set
1763:     if ((event.getFirstRow() ==TableModelEvent.HEADER_ROW)
1764:         && autoCreateColumnsFromModel)
1765: 
1766:         createDefaultColumnsFromModel();
1767: 
1768:     // If the structure changes, we need to revalidate, since that might
1769:     // affect the size parameters of the JTable. Otherwise we only need
1770:     // to perform a repaint to update the view.
1771:     if (event.getType() == TableModelEvent.INSERT)
1772:       revalidate();
1773:     else if (event.getType() == TableModelEvent.DELETE)
1774:       {
1775:         if (dataModel.getRowCount() == 0)
1776:           clearSelection();
1777:         revalidate();
1778:       }
1779:     repaint();
1780:   }
1781: 
1782:   public void valueChanged (ListSelectionEvent event)
1783:   {
1784:     repaint();
1785:   }
1786: 
1787:  /**
1788:    * Returns index of the column that contains specified point 
1789:    * or -1 if this table doesn't contain this point.
1790:    *
1791:    * @param point point to identify the column
1792:    * @return index of the column that contains specified point or 
1793:    * -1 if this table doesn't contain this point.
1794:    */
1795:   public int columnAtPoint(Point point)
1796:   {
1797:     if (point != null)
1798:       {
1799:         int x0 = getLocation().x;
1800:         int ncols = getColumnCount();
1801:         Dimension gap = getIntercellSpacing();
1802:         TableColumnModel cols = getColumnModel();
1803:         int x = point.x;
1804: 
1805:         for (int i = 0; i < ncols; ++i)
1806:           {
1807:             int width = cols.getColumn(i).getWidth()
1808:                         + (gap == null ? 0 : gap.width);
1809:             if (0 <= x && x < width)
1810:               return i;
1811:             x -= width;
1812:           }
1813:       }
1814:     return -1;
1815:   }
1816: 
1817:   /**
1818:    * Returns index of the row that contains specified point or 
1819:    * -1 if this table doesn't contain this point.
1820:    *
1821:    * @param point point to identify the row
1822:    * @return index of the row that contains specified point or 
1823:    * -1 if this table doesn't contain this point.
1824:    */
1825:   public int rowAtPoint(Point point)
1826:   {
1827:     if (point != null)
1828:       {
1829:         int y0 = getLocation().y;
1830:         int nrows = getRowCount();
1831:         int height = getRowHeight();
1832:         int y = point.y;
1833: 
1834:         for (int i = 0; i < nrows; ++i)
1835:           {
1836:             if (0 <= y && y < height)
1837:               return i;
1838:             y -= height;
1839:           }
1840:       }
1841:     return -1;
1842:   }
1843: 
1844:   /** 
1845:    * Calculate the visible rectangle for a particular row and column. The
1846:    * row and column are specified in visual terms; the column may not match
1847:    * the {@link #dataModel} column.
1848:    *
1849:    * @param row the visible row to get the cell rectangle of
1850:    *
1851:    * @param column the visible column to get the cell rectangle of, which may
1852:    * differ from the {@link #dataModel} column
1853:    *
1854:    * @param includeSpacing whether or not to include the cell margins in the
1855:    * resulting cell. If <code>false</code>, the result will only contain the
1856:    * inner area of the target cell, not including its margins.
1857:    *
1858:    * @return a rectangle enclosing the specified cell
1859:    */
1860:   public Rectangle getCellRect(int row,
1861:                                int column,
1862:                                boolean includeSpacing)
1863:   {
1864:     int height = getRowHeight(row);
1865:     int width = columnModel.getColumn(column).getWidth();
1866:     int x_gap = columnModel.getColumnMargin();
1867:     int y_gap = rowMargin;
1868: 
1869:     column = Math.max(0, Math.min(column, getColumnCount() - 1));
1870:     row = Math.max(0, Math.min(row, getRowCount() - 1));
1871: 
1872:     int x = 0;
1873:     int y = (height + y_gap) * row;
1874: 
1875:     for (int i = 0; i < column; ++i)
1876:       x += columnModel.getColumn(i).getWidth();
1877: 
1878:     if (includeSpacing)
1879:       return new Rectangle(x, y, width, height);
1880:     else
1881:       return new Rectangle(x, y, width - x_gap, height - y_gap);
1882:   }
1883: 
1884:   public void clearSelection()
1885:   {
1886:     selectionModel.clearSelection();
1887:     getColumnModel().getSelectionModel().clearSelection();
1888:   }
1889: 
1890:   /**
1891:    * Get the value of the selectedRow property by delegation to
1892:    * the {@link ListSelectionModel#getMinSelectionIndex} method of the
1893:    * {@link #selectionModel} field.
1894:    *
1895:    * @return The current value of the selectedRow property
1896:    */
1897:   public int getSelectedRow ()
1898:   {    
1899:     return selectionModel.getMinSelectionIndex();
1900:   }
1901:   
1902:   /**
1903:    * Get the value of the {@link #selectionModel} property.
1904:    *
1905:    * @return The current value of the property
1906:    */
1907:   public ListSelectionModel getSelectionModel()
1908:   {
1909:     //Neither Sun nor IBM returns null if rowSelection not allowed
1910:     return selectionModel;
1911:   }
1912:   
1913:   public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
1914:   {
1915:     if (orientation == SwingConstants.VERTICAL)
1916:       return visibleRect.height * direction;
1917:     else
1918:       return visibleRect.width * direction;
1919:   }
1920: 
1921:   /**
1922:    * Get the value of the <code>scrollableTracksViewportHeight</code> property.
1923:    *
1924:    * @return The constant value <code>false</code>
1925:    */
1926:   public boolean getScrollableTracksViewportHeight()
1927:   {
1928:     return false;
1929:   }
1930:   
1931:   /**
1932:    * Get the value of the <code>scrollableTracksViewportWidth</code> property.
1933:    *
1934:    * @return <code>true</code> unless the {@link #autoResizeMode} property is
1935:    * <code>AUTO_RESIZE_OFF</code>
1936:    */
1937:   public boolean getScrollableTracksViewportWidth()
1938:   {
1939:     if (autoResizeMode == AUTO_RESIZE_OFF)
1940:       return false;
1941:     else
1942:       return true;
1943:   }
1944: 
1945:   public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
1946:   {
1947:     // FIXME: I don't exactly know what sun does here. in both cases they
1948:     // pick values which do *not* simply expose the next cell in a given
1949:     // scroll direction.
1950: 
1951:     if (orientation == SwingConstants.VERTICAL)
1952:       return direction * rowHeight;
1953:     else
1954:       {
1955:         int sum = 0;
1956:         for (int i = 0; i < getColumnCount(); ++i)
1957:           sum += columnModel.getColumn(0).getWidth();
1958:         int inc = getColumnCount() == 0 ? 10 : sum / getColumnCount();
1959:         return direction * inc;
1960:       }
1961:   }
1962: 
1963: 
1964:   public TableCellEditor getCellEditor(int row, int column)
1965:   {
1966:     TableCellEditor editor = columnModel.getColumn(column).getCellEditor();
1967: 
1968:     if (editor == null)
1969:       editor = getDefaultEditor(dataModel.getColumnClass(column));
1970:     
1971:     return editor;
1972:   }
1973: 
1974:   public TableCellEditor getDefaultEditor(Class columnClass)
1975:   {
1976:     if (defaultEditorsByColumnClass.containsKey(columnClass))
1977:       return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass);
1978:     else
1979:       {
1980:     // FIXME: We have at least an editor for Object.class in our defaults.
1981:         TableCellEditor r = new DefaultCellEditor(new JTextField());
1982:         defaultEditorsByColumnClass.put(columnClass, r);
1983:         return r;
1984:       }
1985:   }
1986: 
1987: 
1988: 
1989:   public TableCellRenderer getCellRenderer(int row, int column)
1990:   {
1991:     TableCellRenderer renderer =
1992:       columnModel.getColumn(column).getCellRenderer();
1993:     
1994:     if (renderer == null)
1995:       renderer = getDefaultRenderer(dataModel.getColumnClass(column));
1996:     
1997:     return renderer;
1998:   }
1999: 
2000:   public void setDefaultRenderer(Class columnClass, TableCellRenderer rend)
2001:   {
2002:     defaultRenderersByColumnClass.put(columnClass, rend);
2003:   }
2004: 
2005:   public TableCellRenderer getDefaultRenderer(Class columnClass)
2006:   {
2007:     if (defaultRenderersByColumnClass.containsKey(columnClass))
2008:       return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass);
2009:     else
2010:       {
2011:         TableCellRenderer r = new DefaultTableCellRenderer();
2012:         defaultRenderersByColumnClass.put(columnClass, r);
2013:         return r;
2014:       }
2015:   }
2016: 
2017:   public int convertColumnIndexToModel(int vc)
2018:   {
2019:     if (vc < 0)
2020:       return vc;
2021:     else
2022:       return columnModel.getColumn(vc).getModelIndex();
2023:   }
2024: 
2025:   public int convertColumnIndexToView(int mc)
2026:   {
2027:     if (mc < 0)
2028:       return mc;
2029:     int ncols = getColumnCount();
2030:     for (int vc = 0; vc < ncols; ++vc)
2031:       {
2032:         if (columnModel.getColumn(vc).getModelIndex() == mc)
2033:           return vc;
2034:       }
2035:     return -1;
2036:   }
2037: 
2038:   public Component prepareRenderer(TableCellRenderer renderer,
2039:                                    int row,
2040:                                    int column)
2041:   {
2042:     boolean rsa = getRowSelectionAllowed();
2043:     boolean csa = getColumnSelectionAllowed();
2044:     boolean rs = rsa ? getSelectionModel().isSelectedIndex(row) : false;
2045:     boolean cs = csa ? columnModel.getSelectionModel().isSelectedIndex(column) : false;
2046:     boolean isSelected = ((rsa && csa && rs && cs) 
2047:                           || (rsa && !csa && rs) 
2048:                           || (!rsa && csa && cs));
2049:     
2050:     return renderer.getTableCellRendererComponent(this,
2051:                                                   dataModel.getValueAt(row, 
2052:                                                convertColumnIndexToModel(column)),
2053:                                                   isSelected,
2054:                                                   false, // hasFocus
2055:                                                   row, column);
2056:   }
2057: 
2058: 
2059:   /**
2060:    * Get the value of the {@link #autoCreateColumnsFromModel} property.
2061:    *
2062:    * @return The current value of the property
2063:    */
2064:   public boolean getAutoCreateColumnsFromModel()
2065:   {
2066:     return autoCreateColumnsFromModel;
2067:   }
2068: 
2069:   /**
2070:    * Get the value of the {@link #autoResizeMode} property.
2071:    *
2072:    * @return The current value of the property
2073:    */
2074:   public int getAutoResizeMode()
2075:   {
2076:     return autoResizeMode;
2077:   }
2078: 
2079:   /**
2080:    * Get the value of the {@link #rowHeight} property.
2081:    *
2082:    * @return The current value of the property
2083:    */
2084:   public int getRowHeight()
2085:   {
2086:     return rowHeight;
2087:   }
2088: 
2089:   /**
2090:    * Get the height of the specified row.
2091:    *
2092:    * @param row the row whose height to return
2093:    */
2094:   public int getRowHeight(int row)
2095:   {
2096:     // FIXME: return the height of the specified row
2097:     // which may be different from the general rowHeight
2098:     return rowHeight;
2099:   }
2100: 
2101: 
2102:   /**
2103:    * Get the value of the {@link #rowMargin} property.
2104:    *
2105:    * @return The current value of the property
2106:    */
2107:   public int getRowMargin()
2108:   {
2109:     return rowMargin;
2110:   }
2111: 
2112:   /**
2113:    * Get the value of the {@link #rowSelectionAllowed} property.
2114:    *
2115:    * @return The current value of the property
2116:    */
2117:   public boolean getRowSelectionAllowed()
2118:   {
2119:     return rowSelectionAllowed;
2120:   }
2121: 
2122:   /**
2123:    * Get the value of the {@link #cellSelectionEnabled} property.
2124:    *
2125:    * @return The current value of the property
2126:    */
2127:   public boolean getCellSelectionEnabled()
2128:   {
2129:     return getColumnSelectionAllowed() && getRowSelectionAllowed();
2130:   }
2131: 
2132:   /**
2133:    * Get the value of the {@link #dataModel} property.
2134:    *
2135:    * @return The current value of the property
2136:    */
2137:   public TableModel getModel()
2138:   {
2139:     return dataModel;
2140:   }
2141: 
2142:   /**
2143:    * Get the value of the <code>columnCount</code> property by
2144:    * delegation to the @{link #columnModel} field.
2145:    *
2146:    * @return The current value of the columnCount property
2147:    */
2148:   public int getColumnCount()
2149:   {
2150:     return columnModel.getColumnCount();    
2151:   }
2152: 
2153:   /**
2154:    * Get the value of the <code>rowCount</code> property by
2155:    * delegation to the @{link #dataModel} field.
2156:    *
2157:    * @return The current value of the rowCount property
2158:    */
2159:   public int getRowCount()
2160:   {
2161:     return dataModel.getRowCount();
2162:   }
2163: 
2164:   /**
2165:    * Get the value of the {@link #columnModel} property.
2166:    *
2167:    * @return The current value of the property
2168:    */
2169:   public TableColumnModel getColumnModel()
2170:   {
2171:     return columnModel;
2172:   }
2173: 
2174:   /**
2175:    * Get the value of the <code>selectedColumn</code> property by
2176:    * delegation to the @{link #columnModel} field.
2177:    *
2178:    * @return The current value of the selectedColumn property
2179:    */
2180:   public int getSelectedColumn()
2181:   {
2182:     return columnModel.getSelectionModel().getMinSelectionIndex();
2183:   }
2184: 
2185:   private static int countSelections(ListSelectionModel lsm)
2186:   {
2187:     int lo = lsm.getMinSelectionIndex();
2188:     int hi = lsm.getMaxSelectionIndex();
2189:     int sum = 0;
2190:     if (lo != -1 && hi != -1)
2191:       {
2192:         switch (lsm.getSelectionMode())
2193:           {
2194:           case ListSelectionModel.SINGLE_SELECTION:
2195:             sum = 1;
2196:             break;
2197:             
2198:           case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
2199:             sum = hi - lo + 1;
2200:             break;
2201:             
2202:           case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
2203:             for (int i = lo; i <= hi; ++i)
2204:               if (lsm.isSelectedIndex(i))        
2205:                 ++sum;
2206:             break;
2207:           }
2208:       }
2209:     return sum;
2210:   }
2211: 
2212:   private static int[] getSelections(ListSelectionModel lsm)
2213:   {
2214:     int sz = countSelections(lsm);
2215:     int [] ret = new int[sz];
2216: 
2217:     int lo = lsm.getMinSelectionIndex();
2218:     int hi = lsm.getMaxSelectionIndex();
2219:     int j = 0;
2220:     java.util.ArrayList ls = new java.util.ArrayList();
2221:     if (lo != -1 && hi != -1)
2222:       {
2223:         switch (lsm.getSelectionMode())
2224:           {
2225:           case ListSelectionModel.SINGLE_SELECTION:
2226:             ret[0] = lo;
2227:             break;      
2228:       
2229:           case ListSelectionModel.SINGLE_INTERVAL_SELECTION:            
2230:             for (int i = lo; i <= hi; ++i)
2231:               ret[j++] = i;
2232:             break;
2233:             
2234:           case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
2235:             for (int i = lo; i <= hi; ++i)
2236:               if (lsm.isSelectedIndex(i))        
2237:                 ret[j++] = i;
2238:             break;
2239:           }
2240:       }
2241:     return ret;
2242:   }
2243: 
2244:   /**
2245:    * Get the value of the <code>selectedColumnCount</code> property by
2246:    * delegation to the @{link #columnModel} field.
2247:    *
2248:    * @return The current value of the selectedColumnCount property
2249:    */  
2250:   public int getSelectedColumnCount()
2251:   {
2252:     return countSelections(columnModel.getSelectionModel());
2253:   }
2254: 
2255:   /**
2256:    * Get the value of the <code>selectedColumns</code> property by
2257:    * delegation to the @{link #columnModel} field.
2258:    *
2259:    * @return The current value of the selectedColumns property
2260:    */
2261:   public int[] getSelectedColumns()
2262:   {
2263:     return getSelections(columnModel.getSelectionModel());
2264:   }
2265: 
2266:   /**
2267:    * Get the value of the <code>columnSelectionAllowed</code> property.
2268:    *
2269:    * @return The current value of the columnSelectionAllowed property
2270:    */
2271:   public boolean getColumnSelectionAllowed()
2272:   {
2273:     return getColumnModel().getColumnSelectionAllowed();
2274:   }
2275: 
2276:   /**
2277:    * Get the value of the <code>selectedRowCount</code> property by
2278:    * delegation to the @{link #selectionModel} field.
2279:    *
2280:    * @return The current value of the selectedRowCount property
2281:    */
2282:   public int getSelectedRowCount()
2283:   {
2284:     return countSelections(selectionModel);
2285:   }
2286: 
2287:   /**
2288:    * Get the value of the <code>selectedRows</code> property by
2289:    * delegation to the @{link #selectionModel} field.
2290:    *
2291:    * @return The current value of the selectedRows property
2292:    */
2293:   public int[] getSelectedRows()
2294:   {
2295:     return getSelections(selectionModel);
2296:   }
2297: 
2298:   /**
2299:    * Get the value of the {@link #accessibleContext} property.
2300:    *
2301:    * @return The current value of the property
2302:    */
2303:   public AccessibleContext getAccessibleContext()
2304:   {
2305:     return accessibleContext;
2306:   }
2307: 
2308:   /**
2309:    * Get the value of the {@link #cellEditor} property.
2310:    *
2311:    * @return The current value of the property
2312:    */
2313:   public TableCellEditor getCellEditor()
2314:   {
2315:     return cellEditor;
2316:   }
2317: 
2318:   /**
2319:    * Get the value of the {@link #dragEnabled} property.
2320:    *
2321:    * @return The current value of the property
2322:    */
2323:   public boolean getDragEnabled()
2324:   {
2325:     return dragEnabled;
2326:   }
2327: 
2328:   /**
2329:    * Get the value of the {@link #gridColor} property.
2330:    *
2331:    * @return The current value of the property
2332:    */
2333:   public Color getGridColor()
2334:   {
2335:     return gridColor;
2336:   }
2337: 
2338:   /**
2339:    * Get the value of the <code>intercellSpacing</code> property.
2340:    *
2341:    * @return The current value of the property
2342:    */
2343:   public Dimension getIntercellSpacing()
2344:   {
2345:     return new Dimension(columnModel.getColumnMargin(), rowMargin);
2346:   }
2347: 
2348:   /**
2349:    * Get the value of the {@link #preferredViewportSize} property.
2350:    *
2351:    * @return The current value of the property
2352:    */
2353:   public Dimension getPreferredScrollableViewportSize()
2354:   {
2355:     return preferredViewportSize;
2356:   }
2357: 
2358:   /**
2359:    * Get the value of the {@link #selectionBackground} property.
2360:    *
2361:    * @return The current value of the property
2362:    */
2363:   public Color getSelectionBackground()
2364:   {
2365:     return selectionBackground;
2366:   }
2367: 
2368:   /**
2369:    * Get the value of the {@link #selectionForeground} property.
2370:    *
2371:    * @return The current value of the property
2372:    */
2373:   public Color getSelectionForeground()
2374:   {
2375:     return selectionForeground;
2376:   }
2377: 
2378:   /**
2379:    * Get the value of the {@link #showHorizontalLines} property.
2380:    *
2381:    * @return The current value of the property
2382:    */
2383:   public boolean getShowHorizontalLines()
2384:   {
2385:     return showHorizontalLines;
2386:   }
2387: 
2388:   /**
2389:    * Get the value of the {@link #showVerticalLines} property.
2390:    *
2391:    * @return The current value of the property
2392:    */
2393:   public boolean getShowVerticalLines()
2394:   {
2395:     return showVerticalLines;
2396:   }
2397: 
2398:   /**
2399:    * Get the value of the {@link #tableHeader} property.
2400:    *
2401:    * @return The current value of the property
2402:    */
2403:   public JTableHeader getTableHeader()
2404:   {
2405:     return tableHeader;
2406:   }
2407: 
2408:   /**
2409:    * Removes specified column from displayable columns of this table.
2410:    *
2411:    * @param column column to removed
2412:    */
2413:   public void removeColumn(TableColumn column)
2414:   {    
2415:     columnModel.removeColumn(column);
2416:   }
2417: 
2418:   /**
2419:    * Moves column at the specified index to new given location.
2420:    *
2421:    * @param column index of the column to move
2422:    * @param targetColumn index specifying new location of the column
2423:    */ 
2424:   public void moveColumn(int column,int targetColumn) 
2425:   {
2426:     columnModel.moveColumn(column, targetColumn);
2427:   }
2428: 
2429:   /**
2430:    * Set the value of the {@link #autoCreateColumnsFromModel} flag.  If the
2431:    * flag changes from <code>false</code> to <code>true</code>, the
2432:    * {@link #createDefaultColumnsFromModel()} method is called.
2433:    *
2434:    * @param autoCreate  the new value of the flag.
2435:    */ 
2436:   public void setAutoCreateColumnsFromModel(boolean autoCreate)
2437:   {
2438:     if (autoCreateColumnsFromModel != autoCreate)
2439:     {
2440:       autoCreateColumnsFromModel = autoCreate;
2441:       if (autoCreate)
2442:         createDefaultColumnsFromModel();
2443:     }
2444:   }
2445: 
2446:   /**
2447:    * Set the value of the {@link #autoResizeMode} property.
2448:    *
2449:    * @param a The new value of the autoResizeMode property
2450:    */ 
2451:   public void setAutoResizeMode(int a)
2452:   {
2453:     autoResizeMode = a;
2454:     revalidate();
2455:     repaint();
2456:   }
2457: 
2458:   /**
2459:    * Set the value of the {@link #rowHeight} property.
2460:    *
2461:    * @param r The new value of the rowHeight property
2462:    */ 
2463:   public void setRowHeight(int r)
2464:   {
2465:     if (r < 1)
2466:       throw new IllegalArgumentException();
2467:     
2468:     rowHeight = r;
2469:     revalidate();
2470:     repaint();
2471:   }
2472:   
2473:   /**
2474:    * Sets the value of the rowHeight property for the specified
2475:    * row.
2476:    * 
2477:    * @param rh is the new rowHeight
2478:    * @param row is the row to change the rowHeight of
2479:    */
2480:   public void setRowHeight(int row, int rh)
2481:   {
2482:      setRowHeight(rh);
2483:      // FIXME: not implemented
2484:   }
2485:   
2486:   /**
2487:    * Set the value of the {@link #rowMargin} property.
2488:    *
2489:    * @param r The new value of the rowMargin property
2490:    */ 
2491:   public void setRowMargin(int r)
2492:   {
2493:     rowMargin = r;
2494:     revalidate();
2495:     repaint();
2496:   }
2497: 
2498:   /**
2499:    * Set the value of the {@link #rowSelectionAllowed} property.
2500:    *
2501:    * @param r The new value of the rowSelectionAllowed property
2502:    */ 
2503:   public void setRowSelectionAllowed(boolean r)
2504:   {
2505:     rowSelectionAllowed = r;
2506:     repaint();
2507:   }
2508: 
2509:   /**
2510:    * Set the value of the {@link #cellSelectionEnabled} property.
2511:    *
2512:    * @param c The new value of the cellSelectionEnabled property
2513:    */ 
2514:   public void setCellSelectionEnabled(boolean c)
2515:   {
2516:     setColumnSelectionAllowed(c);
2517:     setRowSelectionAllowed(c);
2518:     // for backward-compatibility sake:
2519:     cellSelectionEnabled = true;
2520:   }
2521: 
2522:   /**
2523:    * <p>Set the value of the {@link #dataModel} property.</p>
2524:    *
2525:    * <p>Unregister <code>this</code> as a {@link TableModelListener} from
2526:    * previous {@link #dataModel} and register it with new parameter
2527:    * <code>m</code>.</p>
2528:    *
2529:    * @param m The new value of the model property
2530:    */ 
2531:   public void setModel(TableModel m)
2532:   {
2533:     // Throw exception is m is null.
2534:     if (m == null)
2535:       throw new IllegalArgumentException();
2536:    
2537:     // Don't do anything if setting the current model again.
2538:     if (dataModel == m)
2539:       return;
2540: 
2541:     TableModel oldModel = dataModel;
2542: 
2543:     // Remove table as TableModelListener from old model.
2544:     if (dataModel != null)
2545:       dataModel.removeTableModelListener(this);
2546:     
2547:     if (m != null)
2548:       {
2549:         // Set property.
2550:         dataModel = m;
2551: 
2552:         // Add table as TableModelListener to new model.
2553:         dataModel.addTableModelListener(this);
2554: 
2555:         // Automatically create columns.
2556:         if (autoCreateColumnsFromModel)
2557:           createDefaultColumnsFromModel();
2558:       }
2559: 
2560:     // This property is bound, so we fire a property change event.
2561:     firePropertyChange("model", oldModel, dataModel);
2562: 
2563:     // Repaint table.
2564:     revalidate();
2565:     repaint();
2566:   }
2567: 
2568:   /**
2569:    * <p>Set the value of the {@link #columnModel} property.</p>
2570:    *
2571:    * <p>Unregister <code>this</code> as a {@link TableColumnModelListener}
2572:    * from previous {@link #columnModel} and register it with new parameter
2573:    * <code>c</code>.</p>
2574:    *
2575:    * @param c The new value of the columnModel property
2576:    */ 
2577:   public void setColumnModel(TableColumnModel c)
2578:   {
2579:     if (c == null)
2580:       throw new IllegalArgumentException();
2581:     TableColumnModel tmp = columnModel;
2582:     if (tmp != null)
2583:       tmp.removeColumnModelListener(this);
2584:     if (c != null)
2585:       c.addColumnModelListener(this);
2586:     columnModel = c;
2587:     if (dataModel != null && columnModel != null)
2588:       {
2589:         int ncols = getColumnCount();
2590:         for (int i = 0; i < ncols; ++i)
2591:           columnModel.getColumn(i).setHeaderValue(dataModel.getColumnName(i));
2592:       }
2593: 
2594:     // according to Sun's spec we also have to set the tableHeader's
2595:     // column model here
2596:     if (tableHeader != null)
2597:       tableHeader.setColumnModel(c);
2598: 
2599:     revalidate();
2600:     repaint();
2601:   }
2602: 
2603:   /**
2604:    * Set the value of the <code>columnSelectionAllowed</code> property.
2605:    *
2606:    * @param c The new value of the property
2607:    */ 
2608:   public void setColumnSelectionAllowed(boolean c)
2609:   {
2610:     getColumnModel().setColumnSelectionAllowed(c);
2611:     repaint();
2612:   }
2613: 
2614:   /**
2615:    * <p>Set the value of the {@link #selectionModel} property.</p>
2616:    *
2617:    * <p>Unregister <code>this</code> as a {@link ListSelectionListener}
2618:    * from previous {@link #selectionModel} and register it with new
2619:    * parameter <code>s</code>.</p>
2620:    *
2621:    * @param s The new value of the selectionModel property
2622:    */ 
2623:   public void setSelectionModel(ListSelectionModel s)
2624:   {
2625:     if (s == null)
2626:       throw new IllegalArgumentException();
2627:     ListSelectionModel tmp = selectionModel;
2628:     if (tmp != null)
2629:       tmp.removeListSelectionListener(this);
2630:     if (s != null)
2631:       s.addListSelectionListener(this);
2632:     selectionModel = s;
2633:   }
2634: 
2635:   /**
2636:    * Set the value of the <code>selectionMode</code> property by
2637:    * delegation to the {@link #selectionModel} field. The same selection
2638:    * mode is set for row and column selection models.
2639:    *
2640:    * @param s The new value of the property
2641:    */ 
2642:   public void setSelectionMode(int s)
2643:   { 
2644:     selectionModel.setSelectionMode(s);    
2645:     columnModel.getSelectionModel().setSelectionMode(s);
2646:     
2647:     repaint();
2648:   }
2649: 
2650:   /**
2651:    * <p>Set the value of the {@link #cellEditor} property.</p>
2652:    *
2653:    * <p>Unregister <code>this</code> as a {@link CellEditorListener} from
2654:    * previous {@link #cellEditor} and register it with new parameter
2655:    * <code>c</code>.</p>
2656:    *
2657:    * @param c The new value of the cellEditor property
2658:    */ 
2659:   public void setCellEditor(TableCellEditor c)
2660:   {
2661:     TableCellEditor tmp = cellEditor;
2662:     if (tmp != null)
2663:       tmp.removeCellEditorListener(this);
2664:     if (c != null)
2665:       c.addCellEditorListener(this);
2666:     cellEditor = c;
2667:   }
2668: 
2669:   /**
2670:    * Set the value of the {@link #dragEnabled} property.
2671:    *
2672:    * @param d The new value of the dragEnabled property
2673:    */ 
2674:   public void setDragEnabled(boolean d)
2675:   {
2676:     dragEnabled = d;
2677:   }
2678: 
2679:   /**
2680:    * Set the value of the {@link #gridColor} property.
2681:    *
2682:    * @param g The new value of the gridColor property
2683:    */ 
2684:   public void setGridColor(Color g)
2685:   {
2686:     gridColor = g;
2687:     repaint();
2688:   }
2689: 
2690:   /**
2691:    * Set the value of the <code>intercellSpacing</code> property.
2692:    *
2693:    * @param i The new value of the intercellSpacing property
2694:    */ 
2695:   public void setIntercellSpacing(Dimension i)
2696:   {
2697:     rowMargin = i.height;
2698:     columnModel.setColumnMargin(i.width);
2699:     repaint();
2700:   }
2701: 
2702:   /**
2703:    * Set the value of the {@link #preferredViewportSize} property.
2704:    *
2705:    * @param p The new value of the preferredViewportSize property
2706:    */ 
2707:   public void setPreferredScrollableViewportSize(Dimension p)
2708:   {
2709:     preferredViewportSize = p;
2710:     revalidate();
2711:     repaint();
2712:   }
2713: 
2714:   /**
2715:    * <p>Set the value of the {@link #selectionBackground} property.</p>
2716:    *
2717:    * <p>Fire a PropertyChangeEvent with name {@link
2718:    * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if
2719:    * selectionBackground changed.</p>
2720:    *
2721:    * @param s The new value of the selectionBackground property
2722:    */ 
2723:   public void setSelectionBackground(Color s)
2724:   {
2725:     Color tmp = selectionBackground;
2726:     selectionBackground = s;
2727:     if (((tmp == null && s != null)
2728:          || (s == null && tmp != null)
2729:          || (tmp != null && s != null && !tmp.equals(s))))
2730:       firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY, tmp, s);
2731:     repaint();
2732:   }
2733: 
2734:   /**
2735:    * <p>Set the value of the {@link #selectionForeground} property.</p>
2736:    *
2737:    * <p>Fire a PropertyChangeEvent with name {@link
2738:    * #SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if
2739:    * selectionForeground changed.</p>
2740:    *
2741:    * @param s The new value of the selectionForeground property
2742:    */ 
2743:   public void setSelectionForeground(Color s)
2744:   {
2745:     Color tmp = selectionForeground;
2746:     selectionForeground = s;
2747:     if (((tmp == null && s != null)
2748:          || (s == null && tmp != null)
2749:          || (tmp != null && s != null && !tmp.equals(s))))
2750:       firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY, tmp, s);
2751:     repaint();
2752:   }
2753: 
2754:   /**
2755:    * Set the value of the <code>showGrid</code> property.
2756:    *
2757:    * @param s The new value of the showGrid property
2758:    */ 
2759:   public void setShowGrid(boolean s)
2760:   {
2761:     setShowVerticalLines(s);
2762:     setShowHorizontalLines(s);
2763:   }
2764: 
2765:   /**
2766:    * Set the value of the {@link #showHorizontalLines} property.
2767:    *
2768:    * @param s The new value of the showHorizontalLines property
2769:    */ 
2770:   public void setShowHorizontalLines(boolean s)
2771:   {
2772:     showHorizontalLines = s;
2773:     repaint();
2774:   }
2775: 
2776:   /**
2777:    * Set the value of the {@link #showVerticalLines} property.
2778:    *
2779:    * @param s The new value of the showVerticalLines property
2780:    */ 
2781:   public void setShowVerticalLines(boolean s)
2782:   {
2783:     showVerticalLines = s;
2784:     repaint();
2785:   }
2786: 
2787:   /**
2788:    * Set the value of the {@link #tableHeader} property.
2789:    *
2790:    * @param t The new value of the tableHeader property
2791:    */ 
2792:   public void setTableHeader(JTableHeader t)
2793:   {
2794:     if (tableHeader != null)
2795:       tableHeader.setTable(null);
2796:     tableHeader = t;
2797:     if (tableHeader != null)
2798:       tableHeader.setTable(this);
2799:     revalidate();
2800:     repaint();
2801:   }
2802: 
2803:   protected void configureEnclosingScrollPane()
2804:   {
2805:     JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
2806:     if (jsp != null && tableHeader != null)
2807:       {
2808:         jsp.setColumnHeaderView(tableHeader);
2809:       }
2810:   }
2811: 
2812:   protected void unconfigureEnclosingScrollPane()
2813:   {
2814:     JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
2815:     if (jsp != null)
2816:       {
2817:         jsp.setColumnHeaderView(null);
2818:       }    
2819:   }
2820: 
2821: 
2822:   public void addNotify()
2823:   {
2824:     super.addNotify();
2825:     configureEnclosingScrollPane();
2826:   }
2827: 
2828:   public void removeNotify()
2829:   {
2830:     super.addNotify();
2831:     unconfigureEnclosingScrollPane();
2832:   }
2833: 
2834: 
2835:   /**
2836:    * This distributes the superfluous width in a table evenly on its columns.
2837:    *
2838:    * The implementation used here is different to that one described in
2839:    * the JavaDocs. It is much simpler, and seems to work very well.
2840:    *
2841:    * TODO: correctly implement the algorithm described in the JavaDoc
2842:    */
2843:   private void distributeSpill(TableColumn[] cols, int spill)
2844:   {
2845:     int average = spill / cols.length;
2846:     for (int i = 0; i < cols.length; i++)
2847:       {
2848:         if (cols[i] != null)
2849:           cols[i].setWidth(cols[i].getWidth() + average);
2850:       }
2851:   }
2852: 
2853:   public void doLayout()
2854:   {
2855:     TableColumn resizingColumn = null;
2856: 
2857:     int ncols = getColumnCount();
2858:     if (ncols < 1)
2859:       return;
2860: 
2861:     int[] pref = new int[ncols];
2862:     int prefSum = 0;
2863:     int rCol = -1;
2864: 
2865:     if (tableHeader != null)
2866:       resizingColumn = tableHeader.getResizingColumn();
2867: 
2868:     for (int i = 0; i < ncols; ++i)
2869:       {
2870:         TableColumn col = columnModel.getColumn(i);
2871:         int p = col.getWidth();
2872:         pref[i] = p;
2873:         prefSum += p;
2874:         if (resizingColumn == col)
2875:           rCol = i;
2876:       }
2877: 
2878:     int spill = getWidth() - prefSum;
2879: 
2880:     if (resizingColumn != null)
2881:       {
2882:         TableColumn col;
2883:         TableColumn [] cols;
2884: 
2885:         switch (getAutoResizeMode())
2886:           {
2887:           case AUTO_RESIZE_LAST_COLUMN:
2888:             col = columnModel.getColumn(ncols-1);
2889:             col.setWidth(col.getPreferredWidth() + spill);
2890:             break;
2891:             
2892:           case AUTO_RESIZE_NEXT_COLUMN:
2893:             col = columnModel.getColumn(ncols-1);
2894:             col.setWidth(col.getPreferredWidth() + spill);
2895:             break;
2896: 
2897:           case AUTO_RESIZE_ALL_COLUMNS:
2898:             cols = new TableColumn[ncols];
2899:             for (int i = 0; i < ncols; ++i)
2900:               cols[i] = columnModel.getColumn(i);
2901:             distributeSpill(cols, spill);
2902:             break;
2903: 
2904:           case AUTO_RESIZE_SUBSEQUENT_COLUMNS:
2905:             cols = new TableColumn[ncols];
2906:             for (int i = rCol; i < ncols; ++i)
2907:               cols[i] = columnModel.getColumn(i);
2908:             distributeSpill(cols, spill);
2909:             break;
2910: 
2911:           case AUTO_RESIZE_OFF:
2912:           default:
2913:             int prefWidth = resizingColumn.getPreferredWidth();
2914:             resizingColumn.setWidth(prefWidth);
2915:           }
2916:       }
2917:     else
2918:       {
2919:         TableColumn [] cols = new TableColumn[ncols];
2920:         for (int i = 0; i < ncols; ++i)
2921:           cols[i] = columnModel.getColumn(i);
2922:         distributeSpill(cols, spill);        
2923:       }
2924:   }
2925:   
2926:   /**
2927:    * @deprecated Replaced by <code>doLayout()</code>
2928:    */
2929:   public void sizeColumnsToFit(boolean lastColumnOnly)
2930:   {
2931:     doLayout();
2932:   }
2933: 
2934:   /**
2935:    * Obsolete since JDK 1.4. Please use <code>doLayout()</code>.
2936:    */
2937:   public void sizeColumnsToFit(int resizingColumn)
2938:   {
2939:     doLayout();
2940:   }
2941: 
2942:   public String getUIClassID()
2943:   {
2944:     return "TableUI";
2945:   }
2946: 
2947:   /**
2948:    * This method returns the table's UI delegate.
2949:    *
2950:    * @return The table's UI delegate.
2951:    */
2952:   public TableUI getUI()
2953:   {
2954:     return (TableUI) ui;
2955:   }
2956: 
2957:   /**
2958:    * This method sets the table's UI delegate.
2959:    *
2960:    * @param ui The table's UI delegate.
2961:    */
2962:   public void setUI(TableUI ui)
2963:   {
2964:     super.setUI(ui);
2965:   }
2966: 
2967:   public void updateUI()
2968:   {
2969:     setUI((TableUI) UIManager.getUI(this));
2970:     revalidate();
2971:     repaint();
2972:   }
2973: 
2974:   public Class getColumnClass(int column)
2975:   {
2976:     return dataModel.getColumnClass(column);
2977:   }
2978:   
2979:   public String getColumnName(int column)
2980:   {
2981:     int modelColumn = columnModel.getColumn(column).getModelIndex();
2982:     return dataModel.getColumnName(modelColumn);
2983:   }
2984: 
2985:   public int getEditingColumn()
2986:   {
2987:     return editingColumn;
2988:   }
2989: 
2990:   public void setEditingColumn(int column)
2991:   {
2992:     editingColumn = column;
2993:   }
2994:   
2995:   public int getEditingRow()
2996:   {
2997:     return editingRow;
2998:   }
2999: 
3000:   public void setEditingRow(int column)
3001:   {
3002:     editingRow = column;
3003:   }
3004:   
3005:   public Component getEditorComponent()
3006:   {
3007:     return editorComp;
3008:   }
3009:   
3010:   public boolean isEditing()
3011:   {
3012:     return editorComp != null;
3013:   }
3014: 
3015:   public void setDefaultEditor(Class columnClass, TableCellEditor editor)
3016:   {
3017:     if (editor != null)
3018:       defaultEditorsByColumnClass.put(columnClass, editor);
3019:     else
3020:       defaultEditorsByColumnClass.remove(columnClass);
3021:   }
3022: 
3023:   public void addColumnSelectionInterval(int index0, int index1)
3024:   {
3025:     if ((index0 < 0 || index0 > (getColumnCount()-1)
3026:          || index1 < 0 || index1 > (getColumnCount()-1)))
3027:       throw new IllegalArgumentException("Column index out of range.");
3028:     
3029:     getColumnModel().getSelectionModel().addSelectionInterval(index0, index1);
3030:   }
3031:   
3032:   public void addRowSelectionInterval(int index0, int index1)
3033:   {            
3034:     if ((index0 < 0 || index0 > (getRowCount()-1)
3035:          || index1 < 0 || index1 > (getRowCount()-1)))
3036:       throw new IllegalArgumentException("Row index out of range.");
3037:           
3038:     getSelectionModel().addSelectionInterval(index0, index1);
3039:   }
3040:   
3041:   public void setColumnSelectionInterval(int index0, int index1)
3042:   {
3043:     if ((index0 < 0 || index0 > (getColumnCount()-1)
3044:          || index1 < 0 || index1 > (getColumnCount()-1)))
3045:       throw new IllegalArgumentException("Column index out of range.");
3046: 
3047:     getColumnModel().getSelectionModel().setSelectionInterval(index0, index1);
3048:   }
3049:   
3050:   public void setRowSelectionInterval(int index0, int index1)
3051:   {    
3052:     if ((index0 < 0 || index0 > (getRowCount()-1)
3053:          || index1 < 0 || index1 > (getRowCount()-1)))
3054:       throw new IllegalArgumentException("Row index out of range.");
3055: 
3056:     getSelectionModel().setSelectionInterval(index0, index1);
3057:   }
3058:   
3059:   public void removeColumnSelectionInterval(int index0, int index1)  
3060:   {
3061:     if ((index0 < 0 || index0 > (getColumnCount()-1)
3062:          || index1 < 0 || index1 > (getColumnCount()-1)))
3063:       throw new IllegalArgumentException("Column index out of range.");
3064: 
3065:     getColumnModel().getSelectionModel().removeSelectionInterval(index0, index1);
3066:   }
3067:   
3068:   public void removeRowSelectionInterval(int index0, int index1)
3069:   {
3070:     if ((index0 < 0 || index0 > (getRowCount()-1)
3071:          || index1 < 0 || index1 > (getRowCount()-1)))
3072:       throw new IllegalArgumentException("Row index out of range.");
3073: 
3074:     getSelectionModel().removeSelectionInterval(index0, index1);
3075:   }
3076:   
3077:   public boolean isColumnSelected(int column)
3078:   {
3079:     return getColumnModel().getSelectionModel().isSelectedIndex(column);
3080:   }
3081: 
3082:   public boolean isRowSelected(int row)
3083:   {
3084:     return getSelectionModel().isSelectedIndex(row);
3085:   }
3086: 
3087:   public boolean isCellSelected(int row, int column)
3088:   {
3089:     return isRowSelected(row) && isColumnSelected(column);
3090:   }
3091:   
3092:   public void selectAll()
3093:   {
3094:     // rowLead and colLead store the current lead selection indices
3095:     int rowLead = selectionModel.getLeadSelectionIndex();
3096:     int colLead = getColumnModel().getSelectionModel().getLeadSelectionIndex();
3097:     // the following calls to setSelectionInterval change the lead selection
3098:     // indices
3099:     setColumnSelectionInterval(0, getColumnCount() - 1);
3100:     setRowSelectionInterval(0, getRowCount() - 1);
3101:     // the following addSelectionInterval calls restore the lead selection
3102:     // indices to their previous values
3103:     addColumnSelectionInterval(colLead,colLead);
3104:     addRowSelectionInterval(rowLead, rowLead);
3105:   }
3106: 
3107:   public Object getValueAt(int row, int column)
3108:   {
3109:     return dataModel.getValueAt(row, convertColumnIndexToModel(column));
3110:   }
3111: 
3112:   public void setValueAt(Object value, int row, int column)
3113:   {
3114:     if (!isCellEditable(row, column))
3115:       return;
3116: 
3117:     if (value instanceof Component)
3118:       add((Component)value);
3119:     dataModel.setValueAt(value, row, convertColumnIndexToModel(column));
3120:   }
3121: 
3122:   public TableColumn getColumn(Object identifier)
3123:   {
3124:     return columnModel.getColumn(columnModel.getColumnIndex(identifier));
3125:   }
3126: 
3127:   /**
3128:    * Returns <code>true</code> if the specified cell is editable, and
3129:    * <code>false</code> otherwise.
3130:    *
3131:    * @param row  the row index.
3132:    * @param column  the column index.
3133:    *
3134:    * @return A boolean.
3135:    */
3136:   public boolean isCellEditable(int row, int column)
3137:   {
3138:     return dataModel.isCellEditable(row, convertColumnIndexToModel(column));
3139:   }
3140: 
3141:   /**
3142:    * Clears any existing columns from the <code>JTable</code>'s
3143:    * {@link TableColumnModel} and creates new columns to match the values in
3144:    * the data ({@link TableModel}) used by the table.
3145:    *
3146:    * @see #setAutoCreateColumnsFromModel(boolean)
3147:    */
3148:   public void createDefaultColumnsFromModel()
3149:   {
3150:     assert columnModel != null : "The columnModel must not be null.";
3151: 
3152:     // remove existing columns
3153:     int columnIndex = columnModel.getColumnCount() - 1;
3154:     while (columnIndex >= 0)
3155:     {
3156:       columnModel.removeColumn(columnModel.getColumn(columnIndex));
3157:       columnIndex--;
3158:     }
3159:   
3160:     // add new columns to match the TableModel
3161:     int columnCount = dataModel.getColumnCount();
3162:     for (int c = 0; c < columnCount; c++)
3163:     {
3164:       TableColumn column = new TableColumn(c);
3165:       column.setIdentifier(dataModel.getColumnName(c));
3166:       column.setHeaderValue(dataModel.getColumnName(c));
3167:       columnModel.addColumn(column);
3168:       column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
3169:     }
3170:   }
3171: 
3172:   public void changeSelection (int rowIndex, int columnIndex, boolean toggle, boolean extend)
3173:   {
3174:     if (toggle && extend)
3175:       {
3176:         // Leave the selection state as is, but move the anchor
3177:         //   index to the specified location
3178:         selectionModel.setAnchorSelectionIndex(rowIndex);
3179:         getColumnModel().getSelectionModel().setAnchorSelectionIndex(columnIndex);
3180:       }
3181:     else if (toggle)
3182:       {
3183:         // Toggle the state of the specified cell
3184:         if (isCellSelected(rowIndex,columnIndex))
3185:           {
3186:             selectionModel.removeSelectionInterval(rowIndex,rowIndex);
3187:             getColumnModel().getSelectionModel().removeSelectionInterval(columnIndex,columnIndex);
3188:           }
3189:         else
3190:           {
3191:             selectionModel.addSelectionInterval(rowIndex,rowIndex);
3192:             getColumnModel().getSelectionModel().addSelectionInterval(columnIndex,columnIndex);
3193:           }
3194:       }
3195:     else if (extend)
3196:       {
3197:         // Extend the previous selection from the anchor to the 
3198:         // specified cell, clearing all other selections
3199:         selectionModel.setLeadSelectionIndex(rowIndex);
3200:         getColumnModel().getSelectionModel().setLeadSelectionIndex(columnIndex);
3201:       }
3202:     else
3203:       {
3204:         // Clear the previous selection and ensure the new cell
3205:         // is selected
3206:          selectionModel.clearSelection();
3207:         selectionModel.setSelectionInterval(rowIndex,rowIndex);
3208:         getColumnModel().getSelectionModel().clearSelection();
3209:         getColumnModel().getSelectionModel().setSelectionInterval(columnIndex, columnIndex);
3210:         
3211:         
3212:       }
3213:   }
3214: 
3215:   /**
3216:    * Programmatically starts editing the specified cell.
3217:    *
3218:    * @param row the row of the cell to edit.
3219:    * @param column the column of the cell to edit.
3220:    */
3221:   public boolean editCellAt (int row, int column)
3222:   {
3223:     oldCellValue = getValueAt(row, column);
3224:     setCellEditor(getCellEditor(row, column));
3225:     editorComp = prepareEditor(cellEditor, row, column);
3226:     cellEditor.addCellEditorListener(this);
3227:     rowBeingEdited = row;
3228:     columnBeingEdited = column;
3229:     setValueAt(editorComp, row, column);
3230:     ((JTextField)editorComp).requestFocusInWindow(false);
3231:     editorTimer.start();
3232:     return true;
3233:   }
3234: 
3235:   /**
3236:    * Programmatically starts editing the specified cell.
3237:    *
3238:    * @param row the row of the cell to edit.
3239:    * @param column the column of the cell to edit.
3240:    */
3241:   public boolean editCellAt (int row, int column, EventObject e)
3242:   {
3243:     return editCellAt(row, column);
3244:   }
3245: 
3246:   /**
3247:    * Discards the editor object.
3248:    */
3249:   public void removeEditor()
3250:   {
3251:     editingStopped(new ChangeEvent(this));
3252:   }
3253: 
3254:   /**
3255:    * Prepares the editor by querying for the value and selection state of the
3256:    * cell at (row, column).
3257:    *
3258:    * @param editor the TableCellEditor to set up
3259:    * @param row the row of the cell to edit
3260:    * @param column the column of the cell to edit
3261:    * @return the Component being edited
3262:    */
3263:   public Component prepareEditor (TableCellEditor editor, int row, int column)
3264:   {
3265:     return editor.getTableCellEditorComponent
3266:       (this, getValueAt(row, column), isCellSelected(row, column), row, column);
3267:   }
3268: 
3269:   /**
3270:    * This revalidates the <code>JTable</code> and queues a repaint.
3271:    */
3272:   protected void resizeAndRepaint()
3273:   {
3274:     revalidate();
3275:     repaint();
3276:   }
3277: }