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:      * Returns the accessible row at the specified index.
 933:      *
 934:      * @param index the index for which to query the row
 935:      *
 936:      * @return the row number at the specified table index
 937:      */
 938:     public int getAccessibleRowAtIndex(int index)
 939:     {
 940:       // TODO: Back this up by a Mauve test and update API docs accordingly.
 941:       return index / getColumnCount();
 942:     }
 943: 
 944:     /**
 945:      * Returns the accessible column at the specified index.
 946:      *
 947:      * @param index the index for which to query the column
 948:      *
 949:      * @return the column number at the specified table index
 950:      */
 951:     public int getAccessibleColumnAtIndex(int index)
 952:     {
 953:       // TODO: Back this up by a Mauve test and update API docs accordingly.
 954:       return index % getColumnCount();
 955:     }
 956: 
 957:     /**
 958:      * Returns the accessible child index at the specified column and row.
 959:      *
 960:      * @param row the row
 961:      * @param column the column
 962:      *
 963:      * @return the index of the accessible child at the specified row and
 964:      *         column
 965:      */
 966:     public int getAccessibleIndexAt(int row, int column)
 967:     {
 968:       // TODO: Back this up by a Mauve test and update API docs accordingly.
 969:       return row * getColumnCount() + column;
 970:     }
 971:   }
 972:   /**
 973:    * Handles property changes from the <code>TableColumn</code>s of this
 974:    * <code>JTable</code>.
 975:    *
 976:    * More specifically, this triggers a {@link #revalidate()} call if the
 977:    * preferredWidth of one of the observed columns changes.
 978:    */
 979:   class TableColumnPropertyChangeHandler implements PropertyChangeListener
 980:   {
 981:     /**
 982:      * Receives notification that a property of the observed TableColumns
 983:      * has changed.
 984:      *
 985:      * @param ev the property change event
 986:      */
 987:     public void propertyChange(PropertyChangeEvent ev)
 988:     {
 989:       if (ev.getPropertyName().equals("preferredWidth"))
 990:         {
 991:           JTableHeader header = getTableHeader();
 992:       if (header != null)
 993:         {
 994:           TableColumn col = (TableColumn) ev.getSource();
 995:           header.setResizingColumn(col);
 996:           doLayout();
 997:           header.setResizingColumn(null);
 998:         }
 999:         }
1000:     }
1001:   }
1002: 
1003:   /**
1004:    * A cell renderer for boolean values.
1005:    */
1006:   private class BooleanCellRenderer
1007:     extends DefaultTableCellRenderer
1008:   {
1009: 
1010:     /**
1011:      * The CheckBox that is used for rendering.
1012:      */
1013:     private JCheckBox checkBox = new JCheckBox();
1014: 
1015:     /**
1016:      * Returns the component that is used for rendering the value.
1017:      *
1018:      * @param table the JTable
1019:      * @param value the value of the object
1020:      * @param isSelected is the cell selected?
1021:      * @param hasFocus has the cell the focus?
1022:      * @param row the row to render
1023:      * @param column the cell to render
1024:      * 
1025:      * @return this component (the default table cell renderer)
1026:      */
1027:     public Component getTableCellRendererComponent(JTable table, Object value,
1028:                                                    boolean isSelected,
1029:                                                    boolean hasFocus, int row,
1030:                                                    int column)
1031:     {
1032:       Boolean boolValue = (Boolean) value;
1033:       checkBox.setSelected(boolValue.booleanValue());
1034:       return checkBox;
1035:     }
1036:   }
1037: 
1038:   /**
1039:    * A cell renderer for Date values.
1040:    */
1041:   private class DateCellRenderer
1042:     extends DefaultTableCellRenderer
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 Date)
1064:         {
1065:           Date dateValue = (Date) value;
1066:           DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
1067:           setText(df.format(dateValue));
1068:         }
1069:       return this;
1070:     }
1071:   }
1072: 
1073:   /**
1074:    * A cell renderer for Double values.
1075:    */
1076:   private class DoubleCellRenderer
1077:     extends DefaultTableCellRenderer
1078:   {
1079:     /**
1080:      * Creates a new instance of NumberCellRenderer.
1081:      */
1082:     public DoubleCellRenderer()
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 Double)
1107:         {
1108:           Double doubleValue = (Double) value;
1109:           NumberFormat nf = NumberFormat.getInstance();
1110:           setText(nf.format(doubleValue.doubleValue()));
1111:         }
1112:       return this;
1113:     }
1114:   }
1115: 
1116:   /**
1117:    * A cell renderer for Float values.
1118:    */
1119:   private class FloatCellRenderer
1120:     extends DefaultTableCellRenderer
1121:   {
1122:     /**
1123:      * Creates a new instance of NumberCellRenderer.
1124:      */
1125:     public FloatCellRenderer()
1126:     {
1127:       setHorizontalAlignment(JLabel.RIGHT);
1128:     }
1129: 
1130:     /**
1131:      * Returns the component that is used for rendering the value.
1132:      *
1133:      * @param table the JTable
1134:      * @param value the value of the object
1135:      * @param isSelected is the cell selected?
1136:      * @param hasFocus has the cell the focus?
1137:      * @param row the row to render
1138:      * @param column the cell to render
1139:      * 
1140:      * @return this component (the default table cell renderer)
1141:      */
1142:     public Component getTableCellRendererComponent(JTable table, Object value,
1143:                                                    boolean isSelected,
1144:                                                    boolean hasFocus, int row,
1145:                                                    int column)
1146:     {
1147:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1148:                                           row, column);
1149:       if (value instanceof Float)
1150:         {
1151:           Float floatValue = (Float) value;
1152:           NumberFormat nf = NumberFormat.getInstance();
1153:           setText(nf.format(floatValue.floatValue()));
1154:         }
1155:       return this;
1156:     }
1157:   }
1158: 
1159:   /**
1160:    * A cell renderer for Number values.
1161:    */
1162:   private class NumberCellRenderer
1163:     extends DefaultTableCellRenderer
1164:   {
1165:     /**
1166:      * Creates a new instance of NumberCellRenderer.
1167:      */
1168:     public NumberCellRenderer()
1169:     {
1170:       setHorizontalAlignment(JLabel.RIGHT);
1171:     }
1172:   }
1173: 
1174:   /**
1175:    * A cell renderer for Icon values.
1176:    */
1177:   private class IconCellRenderer
1178:     extends DefaultTableCellRenderer
1179:   {
1180:     /**
1181:      * Returns the component that is used for rendering the value.
1182:      *
1183:      * @param table the JTable
1184:      * @param value the value of the object
1185:      * @param isSelected is the cell selected?
1186:      * @param hasFocus has the cell the focus?
1187:      * @param row the row to render
1188:      * @param column the cell to render
1189:      * 
1190:      * @return this component (the default table cell renderer)
1191:      */
1192:     public Component getTableCellRendererComponent(JTable table, Object value,
1193:                                                    boolean isSelected,
1194:                                                    boolean hasFocus, int row,
1195:                                                    int column)
1196:     {
1197:       super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
1198:                                           row, column);
1199:       if (value instanceof Icon)
1200:         {
1201:           Icon iconValue = (Icon) value;
1202:           setIcon(iconValue);
1203:         }
1204:       return this;
1205:     }
1206:   }
1207: 
1208:   private static final long serialVersionUID = 3876025080382781659L;
1209: 
1210: 
1211:   /**
1212:    * When resizing columns, do not automatically change any columns. In this
1213:    * case the table should be enclosed in a {@link JScrollPane} in order to
1214:    * accomodate cases in which the table size exceeds its visible area.
1215:    */
1216:   public static final int AUTO_RESIZE_OFF = 0;
1217: 
1218:   /**
1219:    * When resizing column <code>i</code>, automatically change only the
1220:    * single column <code>i+1</code> to provide or absorb excess space
1221:    * requirements.
1222:    */
1223:   public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
1224: 
1225:   /**
1226:    * When resizing column <code>i</code> in a table of <code>n</code>
1227:    * columns, automatically change all columns in the range <code>[i+1,
1228:    * n)</code>, uniformly, to provide or absorb excess space requirements.
1229:    */
1230:   public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
1231:   
1232:   /**
1233:    * When resizing column <code>i</code> in a table of <code>n</code>
1234:    * columns, automatically change all columns in the range <code>[0,
1235:    * n)</code> (with the exception of column i) uniformly, to provide or
1236:    * absorb excess space requirements.
1237:    */
1238:   public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
1239: 
1240:   /**
1241:    * When resizing column <code>i</code> in a table of <code>n</code>
1242:    * columns, automatically change column <code>n-1</code> (the last column
1243:    * in the table) to provide or absorb excess space requirements.
1244:    */
1245:   public static final int AUTO_RESIZE_LAST_COLUMN = 3;
1246: 
1247: 
1248:   /**
1249:    * A table mapping {@link java.lang.Class} objects to 
1250:    * {@link TableCellEditor} objects. This table is consulted by the 
1251:    * FIXME
1252:    */
1253:   protected Hashtable defaultEditorsByColumnClass;
1254: 
1255:   /**
1256:    * A table mapping {@link java.lang.Class} objects to 
1257:    * {@link TableCellEditor} objects. This table is consulted by the 
1258:    * FIXME
1259:    */
1260:   protected Hashtable defaultRenderersByColumnClass;
1261: 
1262:   /**
1263:    * The column that is edited, -1 if the table is not edited currently.
1264:    */
1265:   protected int editingColumn;
1266: 
1267:   /**
1268:    * The row that is edited, -1 if the table is not edited currently.
1269:    */
1270:   protected int editingRow;
1271: 
1272:   /**
1273:    * The component that is used for editing.
1274:    * <code>null</code> if the table is not editing currently.
1275:    *
1276:    */
1277:   protected transient Component editorComp;
1278: 
1279: 
1280:   /**
1281:    * Whether or not the table should automatically compute a matching
1282:    * {@link TableColumnModel} and assign it to the {@link #columnModel}
1283:    * property when the {@link #dataModel} property is changed. 
1284:    *
1285:    * @see #setModel(TableModel)
1286:    * @see #createDefaultColumnsFromModel()
1287:    * @see #setColumnModel(TableColumnModel)
1288:    * @see #setAutoCreateColumnsFromModel(boolean)
1289:    * @see #getAutoCreateColumnsFromModel()
1290:    */
1291:   protected boolean autoCreateColumnsFromModel;
1292: 
1293:   /**
1294:    * A numeric code specifying the resizing behavior of the table. Must be
1295:    * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link
1296:    * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link
1297:    * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}.
1298:    * 
1299:    * @see #doLayout()
1300:    * @see #setAutoResizeMode(int)
1301:    * @see #getAutoResizeMode()
1302:    */
1303:   protected int autoResizeMode;
1304: 
1305:   /**
1306:    * The height in pixels of any row of the table. All rows in a table are
1307:    * of uniform height. This differs from column width, which varies on a
1308:    * per-column basis, and is stored in the individual columns of the
1309:    * {@link #columnModel}.
1310:    * 
1311:    * @see #getRowHeight()
1312:    * @see #setRowHeight(int)
1313:    * @see TableColumn#getWidth()
1314:    * @see TableColumn#setWidth(int)
1315:    */
1316:   protected int rowHeight;
1317: 
1318:   /**
1319:    * The height in pixels of the gap left between any two rows of the table. 
1320:    * 
1321:    * @see #setRowMargin(int)
1322:    * @see #getRowHeight()
1323:    * @see #getIntercellSpacing()
1324:    * @see #setIntercellSpacing(Dimension)
1325:    * @see TableColumnModel#getColumnMargin()
1326:    * @see TableColumnModel#setColumnMargin(int)
1327:    */
1328:   protected int rowMargin;
1329: 
1330:   /**
1331:    * Whether or not the table should allow row selection. If the table
1332:    * allows both row <em>and</em> column selection, it is said to allow
1333:    * "cell selection". Previous versions of the JDK supported cell
1334:    * selection as an independent concept, but it is now represented solely
1335:    * in terms of simultaneous row and column selection.
1336:    *
1337:    * @see TableColumnModel#getColumnSelectionAllowed()
1338:    * @see #setRowSelectionAllowed(boolean)
1339:    * @see #getRowSelectionAllowed()
1340:    * @see #getCellSelectionEnabled()
1341:    * @see #setCellSelectionEnabled(boolean)
1342:    */
1343:   protected boolean rowSelectionAllowed;
1344: 
1345:   /**
1346:    * @deprecated Use {@link #rowSelectionAllowed}, {@link 
1347:    * #getColumnSelectionAllowed}, or the combined methods {@link
1348:    * #getCellSelectionEnabled} and {@link #setCellSelectionEnabled(boolean)}.
1349:    */
1350:   protected boolean cellSelectionEnabled;
1351:   
1352:   /**
1353:    * The model for data stored in the table. Confusingly, the published API
1354:    * requires that this field be called <code>dataModel</code>, despite its
1355:    * property name. The table listens to its model as a {@link
1356:    * TableModelListener}.
1357:    *
1358:    * @see #tableChanged(TableModelEvent)
1359:    * @see TableModel#addTableModelListener(TableModelListener)
1360:    */
1361:   protected TableModel dataModel;
1362: 
1363:   /**
1364:    * <p>A model of various aspects of the columns of the table, <em>not
1365:    * including</em> the data stored in them. The {@link TableColumnModel}
1366:    * is principally concerned with holding a set of {@link TableColumn}
1367:    * objects, each of which describes the display parameters of a column
1368:    * and the numeric index of the column from the data model which the
1369:    * column is presenting.</p>
1370:    *
1371:    * <p>The TableColumnModel also contains a {@link ListSelectionModel} which
1372:    * indicates which columns are currently selected. This selection model
1373:    * works in combination with the {@link #selectionModel} of the table
1374:    * itself to specify a <em>table selection</em>: a combination of row and
1375:    * column selections.</p>
1376:    *
1377:    * <p>Most application programmers do not need to work with this property
1378:    * at all: setting {@link #autoCreateColumnsFromModel} will construct the
1379:    * columnModel automatically, and the table acts as a facade for most of
1380:    * the interesting properties of the columnModel anyways.</p>
1381:    * 
1382:    * @see #setColumnModel(TableColumnModel)
1383:    * @see #getColumnModel()
1384:    */
1385:   protected TableColumnModel columnModel;
1386: 
1387:   /**
1388:    * A model of the rows of this table which are currently selected. This
1389:    * model is used in combination with the column selection model held as a
1390:    * member of the {@link #columnModel} property, to represent the rows and
1391:    * columns (or both: cells) of the table which are currently selected.
1392:    *
1393:    * @see #rowSelectionAllowed
1394:    * @see #setSelectionModel(ListSelectionModel)
1395:    * @see #getSelectionModel()
1396:    * @see TableColumnModel#getSelectionModel()
1397:    * @see ListSelectionModel#addListSelectionListener(ListSelectionListener)   
1398:    */
1399:   protected ListSelectionModel selectionModel;
1400: 
1401:   /**
1402:    * The current cell editor. 
1403:    */
1404:   protected TableCellEditor cellEditor;
1405: 
1406:   /**
1407:    * Whether or not drag-and-drop is enabled on this table.
1408:    *
1409:    * @see #setDragEnabled(boolean)
1410:    * @see #getDragEnabled()
1411:    */
1412:   private boolean dragEnabled;
1413: 
1414:   /**
1415:    * The color to paint the grid lines of the table, when either {@link
1416:    * #showHorizontalLines} or {@link #showVerticalLines} is set.
1417:    *
1418:    * @see #setGridColor(Color)
1419:    * @see #getGridColor()
1420:    */
1421:   protected Color gridColor;
1422: 
1423:   /**
1424:    * The size this table would prefer its viewport assume, if it is
1425:    * contained in a {@link JScrollPane}.
1426:    *
1427:    * @see #setPreferredScrollableViewportSize(Dimension)
1428:    * @see #getPreferredScrollableViewportSize()
1429:    */
1430:   protected Dimension preferredViewportSize;
1431: 
1432:   /**
1433:    * The color to paint the background of selected cells. Fires a property
1434:    * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY}
1435:    * when its value changes.
1436:    *
1437:    * @see #setSelectionBackground(Color)
1438:    * @see #getSelectionBackground()
1439:    */
1440:   protected Color selectionBackground;
1441: 
1442:   /**
1443:    * The name carried in property change events when the {@link
1444:    * #selectionBackground} property changes.
1445:    */
1446:   private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY = "selectionBackground";
1447: 
1448:   /**
1449:    * The color to paint the foreground of selected cells. Fires a property
1450:    * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY}
1451:    * when its value changes.
1452:    *
1453:    * @see #setSelectionForeground(Color)
1454:    * @see #getSelectionForeground()
1455:    */
1456:   protected Color selectionForeground;
1457: 
1458:   /**
1459:    * The name carried in property change events when the
1460:    * {@link #selectionForeground} property changes.
1461:    */
1462:   private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY = "selectionForeground";
1463: 
1464:   /**
1465:    * The showHorizontalLines property.
1466:    */
1467:   protected boolean showHorizontalLines;
1468: 
1469:   /**
1470:    * The showVerticalLines property.
1471:    */
1472:   protected boolean showVerticalLines;
1473: 
1474:   /**
1475:    * The tableHeader property.
1476:    */
1477:   protected JTableHeader tableHeader;
1478: 
1479:   /**
1480:    * The row of the cell being edited.
1481:    */
1482:   int rowBeingEdited = -1;
1483: 
1484:   /**
1485:    * The column of the cell being edited.
1486:    */
1487:   int columnBeingEdited = -1;
1488: 
1489:   /**
1490:    * The action listener for the editor's Timer.
1491:    */
1492:   Timer editorTimer = new EditorUpdateTimer();
1493: 
1494:   /**
1495:    * Stores the old value of a cell before it was edited, in case
1496:    * editing is cancelled
1497:    */
1498:   Object oldCellValue;
1499: 
1500:   /**
1501:    * The property handler for this table's columns.
1502:    */
1503:   TableColumnPropertyChangeHandler tableColumnPropertyChangeHandler =
1504:     new TableColumnPropertyChangeHandler();
1505: 
1506:   /**
1507:    * Whether cell editors should receive keyboard focus when the table is
1508:    * activated.
1509:    */
1510:   private boolean surrendersFocusOnKeystroke = false;
1511: 
1512:   /**
1513:    * Creates a new <code>JTable</code> instance.
1514:    */
1515:   public JTable ()
1516:   {
1517:     this(null, null, null);
1518:   }
1519: 
1520:   /**
1521:    * Creates a new <code>JTable</code> instance.
1522:    *
1523:    * @param numRows an <code>int</code> value
1524:    * @param numColumns an <code>int</code> value
1525:    */
1526:   public JTable (int numRows, int numColumns)
1527:   {
1528:     this(new DefaultTableModel(numRows, numColumns));
1529:   }
1530: 
1531:   /**
1532:    * Creates a new <code>JTable</code> instance.
1533:    *
1534:    * @param data an <code>Object[][]</code> value
1535:    * @param columnNames an <code>Object[]</code> value
1536:    */
1537:   public JTable(Object[][] data, Object[] columnNames)
1538:   {
1539:     this(new DefaultTableModel(data, columnNames));
1540:   }
1541: 
1542:   /**
1543:    * Creates a new <code>JTable</code> instance.
1544:    *
1545:    * @param dm a <code>TableModel</code> value
1546:    */
1547:   public JTable (TableModel dm)
1548:   {
1549:     this(dm, null, null);
1550:   }
1551: 
1552:   /**
1553:    * Creates a new <code>JTable</code> instance.
1554:    *
1555:    * @param dm a <code>TableModel</code> value
1556:    * @param cm a <code>TableColumnModel</code> value
1557:    */
1558:   public JTable (TableModel dm, TableColumnModel cm)
1559:   {
1560:     this(dm, cm, null);
1561:   }
1562: 
1563:   /**
1564:    * Creates a new <code>JTable</code> instance.
1565:    *
1566:    * @param dm a <code>TableModel</code> value
1567:    * @param cm a <code>TableColumnModel</code> value
1568:    * @param sm a <code>ListSelectionModel</code> value
1569:    */
1570:   public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm)
1571:   {
1572:     boolean autoCreate = false;
1573:     if (cm != null)
1574:         setColumnModel(cm);
1575:     else 
1576:       {
1577:         setColumnModel(createDefaultColumnModel());
1578:         autoCreate = true;
1579:       }        
1580:     setSelectionModel(sm == null ? createDefaultSelectionModel() : sm);
1581:     setModel(dm == null ? createDefaultDataModel() : dm);
1582:     setAutoCreateColumnsFromModel(autoCreate);
1583:     initializeLocalVars();
1584:     // The following four lines properly set the lead selection indices.
1585:     // After this, the UI will handle the lead selection indices.
1586:     // FIXME: this should probably not be necessary, if the UI is installed
1587:     // before the TableModel is set then the UI will handle things on its
1588:     // own, but certain variables need to be set before the UI can be installed
1589:     // so we must get the correct order for all the method calls in this
1590:     // constructor.
1591:     selectionModel.setAnchorSelectionIndex(0);    
1592:     selectionModel.setLeadSelectionIndex(0);
1593:     columnModel.getSelectionModel().setAnchorSelectionIndex(0);
1594:     columnModel.getSelectionModel().setLeadSelectionIndex(0);
1595:     updateUI();
1596:   }    
1597: 
1598:   protected void initializeLocalVars()
1599:   {
1600:     setTableHeader(createDefaultTableHeader());
1601:     if (autoCreateColumnsFromModel)
1602:       createDefaultColumnsFromModel();
1603:     this.columnModel.addColumnModelListener(this);
1604:     
1605:     this.defaultRenderersByColumnClass = new Hashtable();
1606:     createDefaultRenderers();
1607: 
1608:     this.defaultEditorsByColumnClass = new Hashtable();
1609:     createDefaultEditors();
1610: 
1611:     this.autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS;
1612:     this.rowHeight = 16;
1613:     this.rowMargin = 1;
1614:     this.rowSelectionAllowed = true;
1615:     // this.accessibleContext = new AccessibleJTable();
1616:     this.cellEditor = null;
1617:     // COMPAT: Both Sun and IBM have drag enabled
1618:     this.dragEnabled = true;
1619:     this.preferredViewportSize = new Dimension(450,400);
1620:     this.showHorizontalLines = true;
1621:     this.showVerticalLines = true;
1622:     this.editingColumn = -1;
1623:     this.editingRow = -1;
1624:     setIntercellSpacing(new Dimension(1,1));
1625:   }
1626: 
1627:   /**
1628:    * Creates a new <code>JTable</code> instance.
1629:    *
1630:    * @param data a <code>Vector</code> value
1631:    * @param columnNames a <code>Vector</code> value
1632:    */
1633:   public JTable(Vector data, Vector columnNames)
1634:   {
1635:     this(new DefaultTableModel(data, columnNames));
1636:   }
1637: 
1638:   /**
1639:    * The timer that updates the editor component.
1640:    */
1641:   private class EditorUpdateTimer
1642:     extends Timer
1643:     implements ActionListener
1644:   {
1645:     /**
1646:      * Creates a new EditorUpdateTimer object with a default delay of 0.5 seconds.
1647:      */
1648:     public EditorUpdateTimer()
1649:     {
1650:       super(500, null);
1651:       addActionListener(this);
1652:     }
1653: 
1654:     /**
1655:      * Lets the caret blink and repaints the table.
1656:      */
1657:     public void actionPerformed(ActionEvent ev)
1658:     {
1659:       Caret c = ((JTextField)JTable.this.editorComp).getCaret();
1660:       if (c != null)
1661:         c.setVisible(!c.isVisible());
1662:       JTable.this.repaint();
1663:     }
1664: 
1665:     /**
1666:      * Updates the blink delay according to the current caret.
1667:      */
1668:     public void update()
1669:     {
1670:       stop();
1671:       Caret c = ((JTextField)JTable.this.editorComp).getCaret();
1672:       if (c != null)
1673:     {
1674:       setDelay(c.getBlinkRate());
1675:       if (((JTextField)JTable.this.editorComp).isEditable())
1676:         start();
1677:       else
1678:         c.setVisible(false);
1679:     }
1680:     }
1681:   }
1682: 
1683:   public void addColumn(TableColumn column)
1684:   {
1685:     if (column.getHeaderValue() == null)
1686:       {
1687:         String name = dataModel.getColumnName(column.getModelIndex());
1688:         column.setHeaderValue(name);
1689:       }
1690:     
1691:     columnModel.addColumn(column);
1692:     column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
1693:   }
1694: 
1695:   protected void createDefaultEditors()
1696:   {
1697:     //FIXME: Create the editor object.
1698:   }
1699: 
1700:   protected void createDefaultRenderers()
1701:   {
1702:     setDefaultRenderer(Boolean.class, new BooleanCellRenderer());
1703:     setDefaultRenderer(Number.class, new NumberCellRenderer());
1704:     setDefaultRenderer(Double.class, new DoubleCellRenderer());
1705:     setDefaultRenderer(Double.class, new FloatCellRenderer());
1706:     setDefaultRenderer(Date.class, new DateCellRenderer());
1707:     setDefaultRenderer(Icon.class, new IconCellRenderer());
1708:   }
1709:   
1710:   /**
1711:    * @deprecated 1.0.2, replaced by <code>new JScrollPane(JTable)</code>
1712:    */
1713:   public static JScrollPane createScrollPaneForTable(JTable table)
1714:   {
1715:     return new JScrollPane(table);
1716:   }
1717: 
1718:   protected TableColumnModel createDefaultColumnModel()
1719:   {
1720:     return new DefaultTableColumnModel();
1721:   }
1722: 
1723:   protected TableModel createDefaultDataModel()
1724:   {
1725:     return new DefaultTableModel();
1726:   }
1727: 
1728:   protected ListSelectionModel createDefaultSelectionModel()
1729:   {
1730:     return new DefaultListSelectionModel();
1731:   }
1732: 
1733:   protected JTableHeader createDefaultTableHeader()
1734:   {
1735:     return new JTableHeader(columnModel);
1736:   }
1737:  
1738:   // listener support 
1739: 
1740:   public void columnAdded (TableColumnModelEvent event)
1741:   {
1742:     revalidate();
1743:     repaint();
1744:   }
1745: 
1746:   public void columnMarginChanged (ChangeEvent event)
1747:   {
1748:     revalidate();
1749:     repaint();
1750:   }
1751: 
1752:   public void columnMoved (TableColumnModelEvent event)
1753:   {
1754:     revalidate();
1755:     repaint();
1756:   }
1757: 
1758:   public void columnRemoved (TableColumnModelEvent event)
1759:   {
1760:     revalidate();
1761:     repaint();
1762:   }
1763:   
1764:   public void columnSelectionChanged (ListSelectionEvent event)
1765:   {
1766:     repaint();
1767:   }
1768: 
1769:   public void editingCanceled (ChangeEvent event)
1770:   {
1771:     if (rowBeingEdited > -1 && columnBeingEdited > -1)
1772:       {
1773:         if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField)
1774:           {
1775:             remove ((Component)getValueAt(rowBeingEdited, columnBeingEdited));
1776:             setValueAt(oldCellValue, rowBeingEdited, columnBeingEdited);
1777:           }
1778:         rowBeingEdited = -1;
1779:         columnBeingEdited = -1;
1780:       }
1781:     editorTimer.stop();
1782:     editorComp = null;
1783:     cellEditor = null;
1784:     requestFocusInWindow(false);
1785:     repaint();
1786:   }
1787: 
1788:   public void editingStopped (ChangeEvent event)
1789:   {
1790:     if (rowBeingEdited > -1 && columnBeingEdited > -1)
1791:       {
1792:         if (getValueAt(rowBeingEdited, columnBeingEdited) instanceof JTextField)
1793:           {
1794:             remove((Component)getValueAt(rowBeingEdited, columnBeingEdited));
1795:             setValueAt(((JTextField)editorComp).getText(), 
1796:                        rowBeingEdited, columnBeingEdited);
1797:           }
1798:         rowBeingEdited = -1;
1799:         columnBeingEdited = -1;
1800:       }
1801:     editorTimer.stop();
1802:     editorComp = null;
1803:     cellEditor = null;
1804:     requestFocusInWindow(false);
1805:     repaint();
1806:   }
1807: 
1808:   public void tableChanged (TableModelEvent event)
1809:   {
1810:     // update the column model from the table model if the structure has
1811:     // changed and the flag autoCreateColumnsFromModel is set
1812:     if ((event.getFirstRow() ==TableModelEvent.HEADER_ROW)
1813:         && autoCreateColumnsFromModel)
1814: 
1815:       createDefaultColumnsFromModel();
1816: 
1817:     // If the structure changes, we need to revalidate, since that might
1818:     // affect the size parameters of the JTable. Otherwise we only need
1819:     // to perform a repaint to update the view.
1820:     if (event.getType() == TableModelEvent.INSERT)
1821:       revalidate();
1822:     else if (event.getType() == TableModelEvent.DELETE)
1823:       {
1824:         if (dataModel.getRowCount() == 0)
1825:           clearSelection();
1826:         revalidate();
1827:       }
1828:     repaint();
1829:   }
1830: 
1831:   public void valueChanged (ListSelectionEvent event)
1832:   {
1833:     repaint();
1834:   }
1835: 
1836:  /**
1837:    * Returns index of the column that contains specified point 
1838:    * or -1 if this table doesn't contain this point.
1839:    *
1840:    * @param point point to identify the column
1841:    * @return index of the column that contains specified point or 
1842:    * -1 if this table doesn't contain this point.
1843:    */
1844:   public int columnAtPoint(Point point)
1845:   {
1846:     if (point != null)
1847:       {
1848:         int ncols = getColumnCount();
1849:         Dimension gap = getIntercellSpacing();
1850:         TableColumnModel cols = getColumnModel();
1851:         int x = point.x;
1852: 
1853:         for (int i = 0; i < ncols; ++i)
1854:           {
1855:             int width = cols.getColumn(i).getWidth()
1856:                         + (gap == null ? 0 : gap.width);
1857:             if (0 <= x && x < width)
1858:               return i;
1859:             x -= width;
1860:           }
1861:       }
1862:     return -1;
1863:   }
1864: 
1865:   /**
1866:    * Returns index of the row that contains specified point or 
1867:    * -1 if this table doesn't contain this point.
1868:    *
1869:    * @param point point to identify the row
1870:    * @return index of the row that contains specified point or 
1871:    * -1 if this table doesn't contain this point.
1872:    */
1873:   public int rowAtPoint(Point point)
1874:   {
1875:     if (point != null)
1876:       {
1877:         int nrows = getRowCount();
1878:         int height = getRowHeight();
1879:         int y = point.y;
1880: 
1881:         for (int i = 0; i < nrows; ++i)
1882:           {
1883:             if (0 <= y && y < height)
1884:               return i;
1885:             y -= height;
1886:           }
1887:       }
1888:     return -1;
1889:   }
1890: 
1891:   /** 
1892:    * Calculate the visible rectangle for a particular row and column. The
1893:    * row and column are specified in visual terms; the column may not match
1894:    * the {@link #dataModel} column.
1895:    *
1896:    * @param row the visible row to get the cell rectangle of
1897:    *
1898:    * @param column the visible column to get the cell rectangle of, which may
1899:    * differ from the {@link #dataModel} column
1900:    *
1901:    * @param includeSpacing whether or not to include the cell margins in the
1902:    * resulting cell. If <code>false</code>, the result will only contain the
1903:    * inner area of the target cell, not including its margins.
1904:    *
1905:    * @return a rectangle enclosing the specified cell
1906:    */
1907:   public Rectangle getCellRect(int row,
1908:                                int column,
1909:                                boolean includeSpacing)
1910:   {
1911:     int height = getRowHeight(row);
1912:     int width = columnModel.getColumn(column).getWidth();
1913:     int x_gap = columnModel.getColumnMargin();
1914:     int y_gap = rowMargin;
1915: 
1916:     column = Math.max(0, Math.min(column, getColumnCount() - 1));
1917:     row = Math.max(0, Math.min(row, getRowCount() - 1));
1918: 
1919:     int x = 0;
1920:     int y = (height + y_gap) * row;
1921: 
1922:     for (int i = 0; i < column; ++i)
1923:       x += columnModel.getColumn(i).getWidth();
1924: 
1925:     if (includeSpacing)
1926:       return new Rectangle(x, y, width, height);
1927:     else
1928:       return new Rectangle(x, y, width - x_gap, height - y_gap);
1929:   }
1930: 
1931:   public void clearSelection()
1932:   {
1933:     selectionModel.clearSelection();
1934:     getColumnModel().getSelectionModel().clearSelection();
1935:   }
1936: 
1937:   /**
1938:    * Get the value of the selectedRow property by delegation to
1939:    * the {@link ListSelectionModel#getMinSelectionIndex} method of the
1940:    * {@link #selectionModel} field.
1941:    *
1942:    * @return The current value of the selectedRow property
1943:    */
1944:   public int getSelectedRow ()
1945:   {    
1946:     return selectionModel.getMinSelectionIndex();
1947:   }
1948:   
1949:   /**
1950:    * Get the value of the {@link #selectionModel} property.
1951:    *
1952:    * @return The current value of the property
1953:    */
1954:   public ListSelectionModel getSelectionModel()
1955:   {
1956:     //Neither Sun nor IBM returns null if rowSelection not allowed
1957:     return selectionModel;
1958:   }
1959:   
1960:   public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
1961:   {
1962:     if (orientation == SwingConstants.VERTICAL)
1963:       return visibleRect.height * direction;
1964:     else
1965:       return visibleRect.width * direction;
1966:   }
1967: 
1968:   /**
1969:    * Get the value of the <code>scrollableTracksViewportHeight</code> property.
1970:    *
1971:    * @return The constant value <code>false</code>
1972:    */
1973:   public boolean getScrollableTracksViewportHeight()
1974:   {
1975:     return false;
1976:   }
1977:   
1978:   /**
1979:    * Get the value of the <code>scrollableTracksViewportWidth</code> property.
1980:    *
1981:    * @return <code>true</code> unless the {@link #autoResizeMode} property is
1982:    * <code>AUTO_RESIZE_OFF</code>
1983:    */
1984:   public boolean getScrollableTracksViewportWidth()
1985:   {
1986:     if (autoResizeMode == AUTO_RESIZE_OFF)
1987:       return false;
1988:     else
1989:       return true;
1990:   }
1991: 
1992:   public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
1993:   {
1994:     // FIXME: I don't exactly know what sun does here. in both cases they
1995:     // pick values which do *not* simply expose the next cell in a given
1996:     // scroll direction.
1997: 
1998:     if (orientation == SwingConstants.VERTICAL)
1999:       return direction * rowHeight;
2000:     else
2001:       {
2002:         int sum = 0;
2003:         for (int i = 0; i < getColumnCount(); ++i)
2004:           sum += columnModel.getColumn(0).getWidth();
2005:         int inc = getColumnCount() == 0 ? 10 : sum / getColumnCount();
2006:         return direction * inc;
2007:       }
2008:   }
2009: 
2010: 
2011:   public TableCellEditor getCellEditor(int row, int column)
2012:   {
2013:     TableCellEditor editor = columnModel.getColumn(column).getCellEditor();
2014: 
2015:     if (editor == null)
2016:       editor = getDefaultEditor(dataModel.getColumnClass(column));
2017:     
2018:     return editor;
2019:   }
2020: 
2021:   public TableCellEditor getDefaultEditor(Class columnClass)
2022:   {
2023:     if (defaultEditorsByColumnClass.containsKey(columnClass))
2024:       return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass);
2025:     else
2026:       {
2027:     // FIXME: We have at least an editor for Object.class in our defaults.
2028:         TableCellEditor r = new DefaultCellEditor(new JTextField());
2029:         defaultEditorsByColumnClass.put(columnClass, r);
2030:         return r;
2031:       }
2032:   }
2033: 
2034:   public TableCellRenderer getCellRenderer(int row, int column)
2035:   {
2036:     TableCellRenderer renderer =
2037:       columnModel.getColumn(column).getCellRenderer();
2038:     if (renderer == null)
2039:       renderer = getDefaultRenderer(getColumnClass(column));
2040: 
2041:     return renderer;
2042:   }
2043: 
2044:   public void setDefaultRenderer(Class columnClass, TableCellRenderer rend)
2045:   {
2046:     defaultRenderersByColumnClass.put(columnClass, rend);
2047:   }
2048: 
2049:   public TableCellRenderer getDefaultRenderer(Class columnClass)
2050:   {
2051:     if (defaultRenderersByColumnClass.containsKey(columnClass))
2052:       return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass);
2053:     else
2054:       {
2055:         TableCellRenderer r = new DefaultTableCellRenderer();
2056:         defaultRenderersByColumnClass.put(columnClass, r);
2057:         return r;
2058:       }
2059:   }
2060: 
2061:   public int convertColumnIndexToModel(int vc)
2062:   {
2063:     if (vc < 0)
2064:       return vc;
2065:     else
2066:       return columnModel.getColumn(vc).getModelIndex();
2067:   }
2068: 
2069:   public int convertColumnIndexToView(int mc)
2070:   {
2071:     if (mc < 0)
2072:       return mc;
2073:     int ncols = getColumnCount();
2074:     for (int vc = 0; vc < ncols; ++vc)
2075:       {
2076:         if (columnModel.getColumn(vc).getModelIndex() == mc)
2077:           return vc;
2078:       }
2079:     return -1;
2080:   }
2081: 
2082:   public Component prepareRenderer(TableCellRenderer renderer,
2083:                                    int row,
2084:                                    int column)
2085:   {
2086: 
2087:     boolean rowSelAllowed = getRowSelectionAllowed();
2088:     boolean colSelAllowed = getColumnSelectionAllowed();
2089:     boolean isSel = false;
2090:     if (rowSelAllowed && colSelAllowed || !rowSelAllowed && !colSelAllowed)
2091:       isSel = isCellSelected(row, column);
2092:     else
2093:       isSel = isRowSelected(row) && getRowSelectionAllowed()
2094:            || isColumnSelected(column) && getColumnSelectionAllowed();
2095: 
2096:     // Determine the focused cell. The focused cell is the cell at the
2097:     // leadSelectionIndices of the row and column selection model.
2098:     ListSelectionModel rowSel = getSelectionModel();
2099:     ListSelectionModel colSel = getColumnModel().getSelectionModel();
2100:     boolean hasFocus = hasFocus() && isEnabled()
2101:                        && rowSel.getLeadSelectionIndex() == row
2102:                        && colSel.getLeadSelectionIndex() == column;
2103: 
2104:     return renderer.getTableCellRendererComponent(this,
2105:                                                   dataModel.getValueAt(row, 
2106:                                                convertColumnIndexToModel(column)),
2107:                                                   isSel,
2108:                                                   hasFocus,
2109:                                                   row, column);
2110:   }
2111: 
2112: 
2113:   /**
2114:    * Get the value of the {@link #autoCreateColumnsFromModel} property.
2115:    *
2116:    * @return The current value of the property
2117:    */
2118:   public boolean getAutoCreateColumnsFromModel()
2119:   {
2120:     return autoCreateColumnsFromModel;
2121:   }
2122: 
2123:   /**
2124:    * Get the value of the {@link #autoResizeMode} property.
2125:    *
2126:    * @return The current value of the property
2127:    */
2128:   public int getAutoResizeMode()
2129:   {
2130:     return autoResizeMode;
2131:   }
2132: 
2133:   /**
2134:    * Get the value of the {@link #rowHeight} property.
2135:    *
2136:    * @return The current value of the property
2137:    */
2138:   public int getRowHeight()
2139:   {
2140:     return rowHeight;
2141:   }
2142: 
2143:   /**
2144:    * Get the height of the specified row.
2145:    *
2146:    * @param row the row whose height to return
2147:    */
2148:   public int getRowHeight(int row)
2149:   {
2150:     // FIXME: return the height of the specified row
2151:     // which may be different from the general rowHeight
2152:     return rowHeight;
2153:   }
2154: 
2155: 
2156:   /**
2157:    * Get the value of the {@link #rowMargin} property.
2158:    *
2159:    * @return The current value of the property
2160:    */
2161:   public int getRowMargin()
2162:   {
2163:     return rowMargin;
2164:   }
2165: 
2166:   /**
2167:    * Get the value of the {@link #rowSelectionAllowed} property.
2168:    *
2169:    * @return The current value of the property
2170:    */
2171:   public boolean getRowSelectionAllowed()
2172:   {
2173:     return rowSelectionAllowed;
2174:   }
2175: 
2176:   /**
2177:    * Get the value of the {@link #cellSelectionEnabled} property.
2178:    *
2179:    * @return The current value of the property
2180:    */
2181:   public boolean getCellSelectionEnabled()
2182:   {
2183:     return getColumnSelectionAllowed() && getRowSelectionAllowed();
2184:   }
2185: 
2186:   /**
2187:    * Get the value of the {@link #dataModel} property.
2188:    *
2189:    * @return The current value of the property
2190:    */
2191:   public TableModel getModel()
2192:   {
2193:     return dataModel;
2194:   }
2195: 
2196:   /**
2197:    * Get the value of the <code>columnCount</code> property by
2198:    * delegation to the @{link #columnModel} field.
2199:    *
2200:    * @return The current value of the columnCount property
2201:    */
2202:   public int getColumnCount()
2203:   {
2204:     return columnModel.getColumnCount();    
2205:   }
2206: 
2207:   /**
2208:    * Get the value of the <code>rowCount</code> property by
2209:    * delegation to the @{link #dataModel} field.
2210:    *
2211:    * @return The current value of the rowCount property
2212:    */
2213:   public int getRowCount()
2214:   {
2215:     return dataModel.getRowCount();
2216:   }
2217: 
2218:   /**
2219:    * Get the value of the {@link #columnModel} property.
2220:    *
2221:    * @return The current value of the property
2222:    */
2223:   public TableColumnModel getColumnModel()
2224:   {
2225:     return columnModel;
2226:   }
2227: 
2228:   /**
2229:    * Get the value of the <code>selectedColumn</code> property by
2230:    * delegation to the @{link #columnModel} field.
2231:    *
2232:    * @return The current value of the selectedColumn property
2233:    */
2234:   public int getSelectedColumn()
2235:   {
2236:     return columnModel.getSelectionModel().getMinSelectionIndex();
2237:   }
2238: 
2239:   private static int countSelections(ListSelectionModel lsm)
2240:   {
2241:     int lo = lsm.getMinSelectionIndex();
2242:     int hi = lsm.getMaxSelectionIndex();
2243:     int sum = 0;
2244:     if (lo != -1 && hi != -1)
2245:       {
2246:         switch (lsm.getSelectionMode())
2247:           {
2248:           case ListSelectionModel.SINGLE_SELECTION:
2249:             sum = 1;
2250:             break;
2251:             
2252:           case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
2253:             sum = hi - lo + 1;
2254:             break;
2255:             
2256:           case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
2257:             for (int i = lo; i <= hi; ++i)
2258:               if (lsm.isSelectedIndex(i))        
2259:                 ++sum;
2260:             break;
2261:           }
2262:       }
2263:     return sum;
2264:   }
2265: 
2266:   private static int[] getSelections(ListSelectionModel lsm)
2267:   {
2268:     int sz = countSelections(lsm);
2269:     int [] ret = new int[sz];
2270: 
2271:     int lo = lsm.getMinSelectionIndex();
2272:     int hi = lsm.getMaxSelectionIndex();
2273:     int j = 0;
2274:     if (lo != -1 && hi != -1)
2275:       {
2276:         switch (lsm.getSelectionMode())
2277:           {
2278:           case ListSelectionModel.SINGLE_SELECTION:
2279:             ret[0] = lo;
2280:             break;      
2281:       
2282:           case ListSelectionModel.SINGLE_INTERVAL_SELECTION:            
2283:             for (int i = lo; i <= hi; ++i)
2284:               ret[j++] = i;
2285:             break;
2286:             
2287:           case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
2288:             for (int i = lo; i <= hi; ++i)
2289:               if (lsm.isSelectedIndex(i))        
2290:                 ret[j++] = i;
2291:             break;
2292:           }
2293:       }
2294:     return ret;
2295:   }
2296: 
2297:   /**
2298:    * Get the value of the <code>selectedColumnCount</code> property by
2299:    * delegation to the @{link #columnModel} field.
2300:    *
2301:    * @return The current value of the selectedColumnCount property
2302:    */  
2303:   public int getSelectedColumnCount()
2304:   {
2305:     return countSelections(columnModel.getSelectionModel());
2306:   }
2307: 
2308:   /**
2309:    * Get the value of the <code>selectedColumns</code> property by
2310:    * delegation to the @{link #columnModel} field.
2311:    *
2312:    * @return The current value of the selectedColumns property
2313:    */
2314:   public int[] getSelectedColumns()
2315:   {
2316:     return getSelections(columnModel.getSelectionModel());
2317:   }
2318: 
2319:   /**
2320:    * Get the value of the <code>columnSelectionAllowed</code> property.
2321:    *
2322:    * @return The current value of the columnSelectionAllowed property
2323:    */
2324:   public boolean getColumnSelectionAllowed()
2325:   {
2326:     return getColumnModel().getColumnSelectionAllowed();
2327:   }
2328: 
2329:   /**
2330:    * Get the value of the <code>selectedRowCount</code> property by
2331:    * delegation to the @{link #selectionModel} field.
2332:    *
2333:    * @return The current value of the selectedRowCount property
2334:    */
2335:   public int getSelectedRowCount()
2336:   {
2337:     return countSelections(selectionModel);
2338:   }
2339: 
2340:   /**
2341:    * Get the value of the <code>selectedRows</code> property by
2342:    * delegation to the @{link #selectionModel} field.
2343:    *
2344:    * @return The current value of the selectedRows property
2345:    */
2346:   public int[] getSelectedRows()
2347:   {
2348:     return getSelections(selectionModel);
2349:   }
2350: 
2351:   /**
2352:    * Get the value of the {@link #accessibleContext} property.
2353:    *
2354:    * @return The current value of the property
2355:    */
2356:   public AccessibleContext getAccessibleContext()
2357:   {
2358:     return accessibleContext;
2359:   }
2360: 
2361:   /**
2362:    * Get the value of the {@link #cellEditor} property.
2363:    *
2364:    * @return The current value of the property
2365:    */
2366:   public TableCellEditor getCellEditor()
2367:   {
2368:     return cellEditor;
2369:   }
2370: 
2371:   /**
2372:    * Get the value of the {@link #dragEnabled} property.
2373:    *
2374:    * @return The current value of the property
2375:    */
2376:   public boolean getDragEnabled()
2377:   {
2378:     return dragEnabled;
2379:   }
2380: 
2381:   /**
2382:    * Get the value of the {@link #gridColor} property.
2383:    *
2384:    * @return The current value of the property
2385:    */
2386:   public Color getGridColor()
2387:   {
2388:     return gridColor;
2389:   }
2390: 
2391:   /**
2392:    * Get the value of the <code>intercellSpacing</code> property.
2393:    *
2394:    * @return The current value of the property
2395:    */
2396:   public Dimension getIntercellSpacing()
2397:   {
2398:     return new Dimension(columnModel.getColumnMargin(), rowMargin);
2399:   }
2400: 
2401:   /**
2402:    * Get the value of the {@link #preferredViewportSize} property.
2403:    *
2404:    * @return The current value of the property
2405:    */
2406:   public Dimension getPreferredScrollableViewportSize()
2407:   {
2408:     return preferredViewportSize;
2409:   }
2410: 
2411:   /**
2412:    * Get the value of the {@link #selectionBackground} property.
2413:    *
2414:    * @return The current value of the property
2415:    */
2416:   public Color getSelectionBackground()
2417:   {
2418:     return selectionBackground;
2419:   }
2420: 
2421:   /**
2422:    * Get the value of the {@link #selectionForeground} property.
2423:    *
2424:    * @return The current value of the property
2425:    */
2426:   public Color getSelectionForeground()
2427:   {
2428:     return selectionForeground;
2429:   }
2430: 
2431:   /**
2432:    * Get the value of the {@link #showHorizontalLines} property.
2433:    *
2434:    * @return The current value of the property
2435:    */
2436:   public boolean getShowHorizontalLines()
2437:   {
2438:     return showHorizontalLines;
2439:   }
2440: 
2441:   /**
2442:    * Get the value of the {@link #showVerticalLines} property.
2443:    *
2444:    * @return The current value of the property
2445:    */
2446:   public boolean getShowVerticalLines()
2447:   {
2448:     return showVerticalLines;
2449:   }
2450: 
2451:   /**
2452:    * Get the value of the {@link #tableHeader} property.
2453:    *
2454:    * @return The current value of the property
2455:    */
2456:   public JTableHeader getTableHeader()
2457:   {
2458:     return tableHeader;
2459:   }
2460: 
2461:   /**
2462:    * Removes specified column from displayable columns of this table.
2463:    *
2464:    * @param column column to removed
2465:    */
2466:   public void removeColumn(TableColumn column)
2467:   {    
2468:     columnModel.removeColumn(column);
2469:   }
2470: 
2471:   /**
2472:    * Moves column at the specified index to new given location.
2473:    *
2474:    * @param column index of the column to move
2475:    * @param targetColumn index specifying new location of the column
2476:    */ 
2477:   public void moveColumn(int column,int targetColumn) 
2478:   {
2479:     columnModel.moveColumn(column, targetColumn);
2480:   }
2481: 
2482:   /**
2483:    * Set the value of the {@link #autoCreateColumnsFromModel} flag.  If the
2484:    * flag changes from <code>false</code> to <code>true</code>, the
2485:    * {@link #createDefaultColumnsFromModel()} method is called.
2486:    *
2487:    * @param autoCreate  the new value of the flag.
2488:    */ 
2489:   public void setAutoCreateColumnsFromModel(boolean autoCreate)
2490:   {
2491:     if (autoCreateColumnsFromModel != autoCreate)
2492:     {
2493:       autoCreateColumnsFromModel = autoCreate;
2494:       if (autoCreate)
2495:         createDefaultColumnsFromModel();
2496:     }
2497:   }
2498: 
2499:   /**
2500:    * Set the value of the {@link #autoResizeMode} property.
2501:    *
2502:    * @param a The new value of the autoResizeMode property
2503:    */ 
2504:   public void setAutoResizeMode(int a)
2505:   {
2506:     autoResizeMode = a;
2507:     revalidate();
2508:     repaint();
2509:   }
2510: 
2511:   /**
2512:    * Set the value of the {@link #rowHeight} property.
2513:    *
2514:    * @param r The new value of the rowHeight property
2515:    */ 
2516:   public void setRowHeight(int r)
2517:   {
2518:     if (r < 1)
2519:       throw new IllegalArgumentException();
2520:     
2521:     rowHeight = r;
2522:     revalidate();
2523:     repaint();
2524:   }
2525:   
2526:   /**
2527:    * Sets the value of the rowHeight property for the specified
2528:    * row.
2529:    * 
2530:    * @param rh is the new rowHeight
2531:    * @param row is the row to change the rowHeight of
2532:    */
2533:   public void setRowHeight(int row, int rh)
2534:   {
2535:      setRowHeight(rh);
2536:      // FIXME: not implemented
2537:   }
2538:   
2539:   /**
2540:    * Set the value of the {@link #rowMargin} property.
2541:    *
2542:    * @param r The new value of the rowMargin property
2543:    */ 
2544:   public void setRowMargin(int r)
2545:   {
2546:     rowMargin = r;
2547:     revalidate();
2548:     repaint();
2549:   }
2550: 
2551:   /**
2552:    * Set the value of the {@link #rowSelectionAllowed} property.
2553:    *
2554:    * @param r The new value of the rowSelectionAllowed property
2555:    */ 
2556:   public void setRowSelectionAllowed(boolean r)
2557:   {
2558:     rowSelectionAllowed = r;
2559:     repaint();
2560:   }
2561: 
2562:   /**
2563:    * Set the value of the {@link #cellSelectionEnabled} property.
2564:    *
2565:    * @param c The new value of the cellSelectionEnabled property
2566:    */ 
2567:   public void setCellSelectionEnabled(boolean c)
2568:   {
2569:     setColumnSelectionAllowed(c);
2570:     setRowSelectionAllowed(c);
2571:     // for backward-compatibility sake:
2572:     cellSelectionEnabled = true;
2573:   }
2574: 
2575:   /**
2576:    * <p>Set the value of the {@link #dataModel} property.</p>
2577:    *
2578:    * <p>Unregister <code>this</code> as a {@link TableModelListener} from
2579:    * previous {@link #dataModel} and register it with new parameter
2580:    * <code>m</code>.</p>
2581:    *
2582:    * @param m The new value of the model property
2583:    */ 
2584:   public void setModel(TableModel m)
2585:   {
2586:     // Throw exception is m is null.
2587:     if (m == null)
2588:       throw new IllegalArgumentException();
2589:    
2590:     // Don't do anything if setting the current model again.
2591:     if (dataModel == m)
2592:       return;
2593: 
2594:     TableModel oldModel = dataModel;
2595: 
2596:     // Remove table as TableModelListener from old model.
2597:     if (dataModel != null)
2598:       dataModel.removeTableModelListener(this);
2599:     
2600:     if (m != null)
2601:       {
2602:         // Set property.
2603:         dataModel = m;
2604: 
2605:         // Add table as TableModelListener to new model.
2606:         dataModel.addTableModelListener(this);
2607: 
2608:         // Automatically create columns.
2609:         if (autoCreateColumnsFromModel)
2610:           createDefaultColumnsFromModel();
2611:       }
2612: 
2613:     // This property is bound, so we fire a property change event.
2614:     firePropertyChange("model", oldModel, dataModel);
2615: 
2616:     // Repaint table.
2617:     revalidate();
2618:     repaint();
2619:   }
2620: 
2621:   /**
2622:    * <p>Set the value of the {@link #columnModel} property.</p>
2623:    *
2624:    * <p>Unregister <code>this</code> as a {@link TableColumnModelListener}
2625:    * from previous {@link #columnModel} and register it with new parameter
2626:    * <code>c</code>.</p>
2627:    *
2628:    * @param c The new value of the columnModel property
2629:    */ 
2630:   public void setColumnModel(TableColumnModel c)
2631:   {
2632:     if (c == null)
2633:       throw new IllegalArgumentException();
2634:     TableColumnModel tmp = columnModel;
2635:     if (tmp != null)
2636:       tmp.removeColumnModelListener(this);
2637:     if (c != null)
2638:       c.addColumnModelListener(this);
2639:     columnModel = c;
2640:     if (dataModel != null && columnModel != null)
2641:       {
2642:         int ncols = getColumnCount();
2643:         for (int i = 0; i < ncols; ++i)
2644:           columnModel.getColumn(i).setHeaderValue(dataModel.getColumnName(i));
2645:       }
2646: 
2647:     // according to Sun's spec we also have to set the tableHeader's
2648:     // column model here
2649:     if (tableHeader != null)
2650:       tableHeader.setColumnModel(c);
2651: 
2652:     revalidate();
2653:     repaint();
2654:   }
2655: 
2656:   /**
2657:    * Set the value of the <code>columnSelectionAllowed</code> property.
2658:    *
2659:    * @param c The new value of the property
2660:    */ 
2661:   public void setColumnSelectionAllowed(boolean c)
2662:   {
2663:     getColumnModel().setColumnSelectionAllowed(c);
2664:     repaint();
2665:   }
2666: 
2667:   /**
2668:    * <p>Set the value of the {@link #selectionModel} property.</p>
2669:    *
2670:    * <p>Unregister <code>this</code> as a {@link ListSelectionListener}
2671:    * from previous {@link #selectionModel} and register it with new
2672:    * parameter <code>s</code>.</p>
2673:    *
2674:    * @param s The new value of the selectionModel property
2675:    */ 
2676:   public void setSelectionModel(ListSelectionModel s)
2677:   {
2678:     if (s == null)
2679:       throw new IllegalArgumentException();
2680:     ListSelectionModel tmp = selectionModel;
2681:     if (tmp != null)
2682:       tmp.removeListSelectionListener(this);
2683:     if (s != null)
2684:       s.addListSelectionListener(this);
2685:     selectionModel = s;
2686:   }
2687: 
2688:   /**
2689:    * Set the value of the <code>selectionMode</code> property by
2690:    * delegation to the {@link #selectionModel} field. The same selection
2691:    * mode is set for row and column selection models.
2692:    *
2693:    * @param s The new value of the property
2694:    */ 
2695:   public void setSelectionMode(int s)
2696:   { 
2697:     selectionModel.setSelectionMode(s);    
2698:     columnModel.getSelectionModel().setSelectionMode(s);
2699:     
2700:     repaint();
2701:   }
2702: 
2703:   /**
2704:    * <p>Set the value of the {@link #cellEditor} property.</p>
2705:    *
2706:    * <p>Unregister <code>this</code> as a {@link CellEditorListener} from
2707:    * previous {@link #cellEditor} and register it with new parameter
2708:    * <code>c</code>.</p>
2709:    *
2710:    * @param c The new value of the cellEditor property
2711:    */ 
2712:   public void setCellEditor(TableCellEditor c)
2713:   {
2714:     TableCellEditor tmp = cellEditor;
2715:     if (tmp != null)
2716:       tmp.removeCellEditorListener(this);
2717:     if (c != null)
2718:       c.addCellEditorListener(this);
2719:     cellEditor = c;
2720:   }
2721: 
2722:   /**
2723:    * Set the value of the {@link #dragEnabled} property.
2724:    *
2725:    * @param d The new value of the dragEnabled property
2726:    */ 
2727:   public void setDragEnabled(boolean d)
2728:   {
2729:     dragEnabled = d;
2730:   }
2731: 
2732:   /**
2733:    * Set the value of the {@link #gridColor} property.
2734:    *
2735:    * @param g The new value of the gridColor property
2736:    */ 
2737:   public void setGridColor(Color g)
2738:   {
2739:     gridColor = g;
2740:     repaint();
2741:   }
2742: 
2743:   /**
2744:    * Set the value of the <code>intercellSpacing</code> property.
2745:    *
2746:    * @param i The new value of the intercellSpacing property
2747:    */ 
2748:   public void setIntercellSpacing(Dimension i)
2749:   {
2750:     rowMargin = i.height;
2751:     columnModel.setColumnMargin(i.width);
2752:     repaint();
2753:   }
2754: 
2755:   /**
2756:    * Set the value of the {@link #preferredViewportSize} property.
2757:    *
2758:    * @param p The new value of the preferredViewportSize property
2759:    */ 
2760:   public void setPreferredScrollableViewportSize(Dimension p)
2761:   {
2762:     preferredViewportSize = p;
2763:     revalidate();
2764:     repaint();
2765:   }
2766: 
2767:   /**
2768:    * <p>Set the value of the {@link #selectionBackground} property.</p>
2769:    *
2770:    * <p>Fire a PropertyChangeEvent with name {@link
2771:    * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if
2772:    * selectionBackground changed.</p>
2773:    *
2774:    * @param s The new value of the selectionBackground property
2775:    */ 
2776:   public void setSelectionBackground(Color s)
2777:   {
2778:     Color tmp = selectionBackground;
2779:     selectionBackground = s;
2780:     if (((tmp == null && s != null)
2781:          || (s == null && tmp != null)
2782:          || (tmp != null && s != null && !tmp.equals(s))))
2783:       firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY, tmp, s);
2784:     repaint();
2785:   }
2786: 
2787:   /**
2788:    * <p>Set the value of the {@link #selectionForeground} property.</p>
2789:    *
2790:    * <p>Fire a PropertyChangeEvent with name {@link
2791:    * #SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if
2792:    * selectionForeground changed.</p>
2793:    *
2794:    * @param s The new value of the selectionForeground property
2795:    */ 
2796:   public void setSelectionForeground(Color s)
2797:   {
2798:     Color tmp = selectionForeground;
2799:     selectionForeground = s;
2800:     if (((tmp == null && s != null)
2801:          || (s == null && tmp != null)
2802:          || (tmp != null && s != null && !tmp.equals(s))))
2803:       firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY, tmp, s);
2804:     repaint();
2805:   }
2806: 
2807:   /**
2808:    * Set the value of the <code>showGrid</code> property.
2809:    *
2810:    * @param s The new value of the showGrid property
2811:    */ 
2812:   public void setShowGrid(boolean s)
2813:   {
2814:     setShowVerticalLines(s);
2815:     setShowHorizontalLines(s);
2816:   }
2817: 
2818:   /**
2819:    * Set the value of the {@link #showHorizontalLines} property.
2820:    *
2821:    * @param s The new value of the showHorizontalLines property
2822:    */ 
2823:   public void setShowHorizontalLines(boolean s)
2824:   {
2825:     showHorizontalLines = s;
2826:     repaint();
2827:   }
2828: 
2829:   /**
2830:    * Set the value of the {@link #showVerticalLines} property.
2831:    *
2832:    * @param s The new value of the showVerticalLines property
2833:    */ 
2834:   public void setShowVerticalLines(boolean s)
2835:   {
2836:     showVerticalLines = s;
2837:     repaint();
2838:   }
2839: 
2840:   /**
2841:    * Set the value of the {@link #tableHeader} property.
2842:    *
2843:    * @param t The new value of the tableHeader property
2844:    */ 
2845:   public void setTableHeader(JTableHeader t)
2846:   {
2847:     if (tableHeader != null)
2848:       tableHeader.setTable(null);
2849:     tableHeader = t;
2850:     if (tableHeader != null)
2851:       tableHeader.setTable(this);
2852:     revalidate();
2853:     repaint();
2854:   }
2855: 
2856:   protected void configureEnclosingScrollPane()
2857:   {
2858:     JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
2859:     if (jsp != null && tableHeader != null)
2860:       {
2861:         jsp.setColumnHeaderView(tableHeader);
2862:       }
2863:   }
2864: 
2865:   protected void unconfigureEnclosingScrollPane()
2866:   {
2867:     JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
2868:     if (jsp != null)
2869:       {
2870:         jsp.setColumnHeaderView(null);
2871:       }    
2872:   }
2873: 
2874: 
2875:   public void addNotify()
2876:   {
2877:     super.addNotify();
2878:     configureEnclosingScrollPane();
2879:   }
2880: 
2881:   public void removeNotify()
2882:   {
2883:     super.addNotify();
2884:     unconfigureEnclosingScrollPane();
2885:   }
2886: 
2887: 
2888:   /**
2889:    * This distributes the superfluous width in a table evenly on its columns.
2890:    *
2891:    * The implementation used here is different to that one described in
2892:    * the JavaDocs. It is much simpler, and seems to work very well.
2893:    *
2894:    * TODO: correctly implement the algorithm described in the JavaDoc
2895:    */
2896:   private void distributeSpill(TableColumn[] cols, int spill)
2897:   {
2898:     int average = spill / cols.length;
2899:     for (int i = 0; i < cols.length; i++)
2900:       {
2901:         if (cols[i] != null)
2902:           cols[i].setWidth(cols[i].getWidth() + average);
2903:       }
2904:   }
2905: 
2906:   public void doLayout()
2907:   {
2908:     TableColumn resizingColumn = null;
2909: 
2910:     int ncols = getColumnCount();
2911:     if (ncols < 1)
2912:       return;
2913: 
2914:     int[] pref = new int[ncols];
2915:     int prefSum = 0;
2916:     int rCol = -1;
2917: 
2918:     if (tableHeader != null)
2919:       resizingColumn = tableHeader.getResizingColumn();
2920: 
2921:     for (int i = 0; i < ncols; ++i)
2922:       {
2923:         TableColumn col = columnModel.getColumn(i);
2924:         int p = col.getWidth();
2925:         pref[i] = p;
2926:         prefSum += p;
2927:         if (resizingColumn == col)
2928:           rCol = i;
2929:       }
2930: 
2931:     int spill = getWidth() - prefSum;
2932: 
2933:     if (resizingColumn != null)
2934:       {
2935:         TableColumn col;
2936:         TableColumn [] cols;
2937: 
2938:         switch (getAutoResizeMode())
2939:           {
2940:           case AUTO_RESIZE_LAST_COLUMN:
2941:             col = columnModel.getColumn(ncols-1);
2942:             col.setWidth(col.getPreferredWidth() + spill);
2943:             break;
2944:             
2945:           case AUTO_RESIZE_NEXT_COLUMN:
2946:             col = columnModel.getColumn(ncols-1);
2947:             col.setWidth(col.getPreferredWidth() + spill);
2948:             break;
2949: 
2950:           case AUTO_RESIZE_ALL_COLUMNS:
2951:             cols = new TableColumn[ncols];
2952:             for (int i = 0; i < ncols; ++i)
2953:               cols[i] = columnModel.getColumn(i);
2954:             distributeSpill(cols, spill);
2955:             break;
2956: 
2957:           case AUTO_RESIZE_SUBSEQUENT_COLUMNS:
2958:             cols = new TableColumn[ncols];
2959:             for (int i = rCol; i < ncols; ++i)
2960:               cols[i] = columnModel.getColumn(i);
2961:             distributeSpill(cols, spill);
2962:             break;
2963: 
2964:           case AUTO_RESIZE_OFF:
2965:           default:
2966:             int prefWidth = resizingColumn.getPreferredWidth();
2967:             resizingColumn.setWidth(prefWidth);
2968:           }
2969:       }
2970:     else
2971:       {
2972:         TableColumn [] cols = new TableColumn[ncols];
2973:         for (int i = 0; i < ncols; ++i)
2974:           cols[i] = columnModel.getColumn(i);
2975:         distributeSpill(cols, spill);        
2976:       }
2977:   }
2978:   
2979:   /**
2980:    * @deprecated Replaced by <code>doLayout()</code>
2981:    */
2982:   public void sizeColumnsToFit(boolean lastColumnOnly)
2983:   {
2984:     doLayout();
2985:   }
2986: 
2987:   /**
2988:    * Obsolete since JDK 1.4. Please use <code>doLayout()</code>.
2989:    */
2990:   public void sizeColumnsToFit(int resizingColumn)
2991:   {
2992:     doLayout();
2993:   }
2994: 
2995:   public String getUIClassID()
2996:   {
2997:     return "TableUI";
2998:   }
2999: 
3000:   /**
3001:    * This method returns the table's UI delegate.
3002:    *
3003:    * @return The table's UI delegate.
3004:    */
3005:   public TableUI getUI()
3006:   {
3007:     return (TableUI) ui;
3008:   }
3009: 
3010:   /**
3011:    * This method sets the table's UI delegate.
3012:    *
3013:    * @param ui The table's UI delegate.
3014:    */
3015:   public void setUI(TableUI ui)
3016:   {
3017:     super.setUI(ui);
3018:   }
3019: 
3020:   public void updateUI()
3021:   {
3022:     setUI((TableUI) UIManager.getUI(this));
3023:     revalidate();
3024:     repaint();
3025:   }
3026: 
3027:   public Class getColumnClass(int column)
3028:   {
3029:     return getModel().getColumnClass(column);
3030:   }
3031:   
3032:   public String getColumnName(int column)
3033:   {
3034:     int modelColumn = columnModel.getColumn(column).getModelIndex();
3035:     return dataModel.getColumnName(modelColumn);
3036:   }
3037: 
3038:   public int getEditingColumn()
3039:   {
3040:     return editingColumn;
3041:   }
3042: 
3043:   public void setEditingColumn(int column)
3044:   {
3045:     editingColumn = column;
3046:   }
3047:   
3048:   public int getEditingRow()
3049:   {
3050:     return editingRow;
3051:   }
3052: 
3053:   public void setEditingRow(int column)
3054:   {
3055:     editingRow = column;
3056:   }
3057:   
3058:   public Component getEditorComponent()
3059:   {
3060:     return editorComp;
3061:   }
3062:   
3063:   public boolean isEditing()
3064:   {
3065:     return editorComp != null;
3066:   }
3067: 
3068:   public void setDefaultEditor(Class columnClass, TableCellEditor editor)
3069:   {
3070:     if (editor != null)
3071:       defaultEditorsByColumnClass.put(columnClass, editor);
3072:     else
3073:       defaultEditorsByColumnClass.remove(columnClass);
3074:   }
3075: 
3076:   public void addColumnSelectionInterval(int index0, int index1)
3077:   {
3078:     if ((index0 < 0 || index0 > (getColumnCount()-1)
3079:          || index1 < 0 || index1 > (getColumnCount()-1)))
3080:       throw new IllegalArgumentException("Column index out of range.");
3081:     
3082:     getColumnModel().getSelectionModel().addSelectionInterval(index0, index1);
3083:   }
3084:   
3085:   public void addRowSelectionInterval(int index0, int index1)
3086:   {            
3087:     if ((index0 < 0 || index0 > (getRowCount()-1)
3088:          || index1 < 0 || index1 > (getRowCount()-1)))
3089:       throw new IllegalArgumentException("Row index out of range.");
3090:           
3091:     getSelectionModel().addSelectionInterval(index0, index1);
3092:   }
3093:   
3094:   public void setColumnSelectionInterval(int index0, int index1)
3095:   {
3096:     if ((index0 < 0 || index0 > (getColumnCount()-1)
3097:          || index1 < 0 || index1 > (getColumnCount()-1)))
3098:       throw new IllegalArgumentException("Column index out of range.");
3099: 
3100:     getColumnModel().getSelectionModel().setSelectionInterval(index0, index1);
3101:   }
3102:   
3103:   public void setRowSelectionInterval(int index0, int index1)
3104:   {    
3105:     if ((index0 < 0 || index0 > (getRowCount()-1)
3106:          || index1 < 0 || index1 > (getRowCount()-1)))
3107:       throw new IllegalArgumentException("Row index out of range.");
3108: 
3109:     getSelectionModel().setSelectionInterval(index0, index1);
3110:   }
3111:   
3112:   public void removeColumnSelectionInterval(int index0, int index1)  
3113:   {
3114:     if ((index0 < 0 || index0 > (getColumnCount()-1)
3115:          || index1 < 0 || index1 > (getColumnCount()-1)))
3116:       throw new IllegalArgumentException("Column index out of range.");
3117: 
3118:     getColumnModel().getSelectionModel().removeSelectionInterval(index0, index1);
3119:   }
3120:   
3121:   public void removeRowSelectionInterval(int index0, int index1)
3122:   {
3123:     if ((index0 < 0 || index0 > (getRowCount()-1)
3124:          || index1 < 0 || index1 > (getRowCount()-1)))
3125:       throw new IllegalArgumentException("Row index out of range.");
3126: 
3127:     getSelectionModel().removeSelectionInterval(index0, index1);
3128:   }
3129:   
3130:   public boolean isColumnSelected(int column)
3131:   {
3132:     return getColumnModel().getSelectionModel().isSelectedIndex(column);
3133:   }
3134: 
3135:   public boolean isRowSelected(int row)
3136:   {
3137:     return getSelectionModel().isSelectedIndex(row);
3138:   }
3139: 
3140:   public boolean isCellSelected(int row, int column)
3141:   {
3142:     return isRowSelected(row) && isColumnSelected(column);
3143:   }
3144:   
3145:   public void selectAll()
3146:   {
3147:     // rowLead and colLead store the current lead selection indices
3148:     int rowLead = selectionModel.getLeadSelectionIndex();
3149:     int colLead = getColumnModel().getSelectionModel().getLeadSelectionIndex();
3150:     // the following calls to setSelectionInterval change the lead selection
3151:     // indices
3152:     setColumnSelectionInterval(0, getColumnCount() - 1);
3153:     setRowSelectionInterval(0, getRowCount() - 1);
3154:     // the following addSelectionInterval calls restore the lead selection
3155:     // indices to their previous values
3156:     addColumnSelectionInterval(colLead,colLead);
3157:     addRowSelectionInterval(rowLead, rowLead);
3158:   }
3159: 
3160:   public Object getValueAt(int row, int column)
3161:   {
3162:     return dataModel.getValueAt(row, convertColumnIndexToModel(column));
3163:   }
3164: 
3165:   public void setValueAt(Object value, int row, int column)
3166:   {
3167:     if (!isCellEditable(row, column))
3168:       return;
3169: 
3170:     if (value instanceof Component)
3171:       add((Component)value);
3172:     dataModel.setValueAt(value, row, convertColumnIndexToModel(column));
3173:   }
3174: 
3175:   public TableColumn getColumn(Object identifier)
3176:   {
3177:     return columnModel.getColumn(columnModel.getColumnIndex(identifier));
3178:   }
3179: 
3180:   /**
3181:    * Returns <code>true</code> if the specified cell is editable, and
3182:    * <code>false</code> otherwise.
3183:    *
3184:    * @param row  the row index.
3185:    * @param column  the column index.
3186:    *
3187:    * @return A boolean.
3188:    */
3189:   public boolean isCellEditable(int row, int column)
3190:   {
3191:     return dataModel.isCellEditable(row, convertColumnIndexToModel(column));
3192:   }
3193: 
3194:   /**
3195:    * Clears any existing columns from the <code>JTable</code>'s
3196:    * {@link TableColumnModel} and creates new columns to match the values in
3197:    * the data ({@link TableModel}) used by the table.
3198:    *
3199:    * @see #setAutoCreateColumnsFromModel(boolean)
3200:    */
3201:   public void createDefaultColumnsFromModel()
3202:   {
3203:     assert columnModel != null : "The columnModel must not be null.";
3204: 
3205:     // remove existing columns
3206:     int columnIndex = columnModel.getColumnCount() - 1;
3207:     while (columnIndex >= 0)
3208:     {
3209:       columnModel.removeColumn(columnModel.getColumn(columnIndex));
3210:       columnIndex--;
3211:     }
3212:   
3213:     // add new columns to match the TableModel
3214:     int columnCount = dataModel.getColumnCount();
3215:     for (int c = 0; c < columnCount; c++)
3216:     {
3217:       TableColumn column = new TableColumn(c);
3218:       column.setIdentifier(dataModel.getColumnName(c));
3219:       column.setHeaderValue(dataModel.getColumnName(c));
3220:       columnModel.addColumn(column);
3221:       column.addPropertyChangeListener(tableColumnPropertyChangeHandler);
3222:     }
3223:   }
3224: 
3225:   public void changeSelection (int rowIndex, int columnIndex, boolean toggle, boolean extend)
3226:   {
3227:     if (toggle && extend)
3228:       {
3229:         // Leave the selection state as is, but move the anchor
3230:         //   index to the specified location
3231:         selectionModel.setAnchorSelectionIndex(rowIndex);
3232:         getColumnModel().getSelectionModel().setAnchorSelectionIndex(columnIndex);
3233:       }
3234:     else if (toggle)
3235:       {
3236:         // Toggle the state of the specified cell
3237:         if (isCellSelected(rowIndex,columnIndex))
3238:           {
3239:             selectionModel.removeSelectionInterval(rowIndex,rowIndex);
3240:             getColumnModel().getSelectionModel().removeSelectionInterval(columnIndex,columnIndex);
3241:           }
3242:         else
3243:           {
3244:             selectionModel.addSelectionInterval(rowIndex,rowIndex);
3245:             getColumnModel().getSelectionModel().addSelectionInterval(columnIndex,columnIndex);
3246:           }
3247:       }
3248:     else if (extend)
3249:       {
3250:         // Extend the previous selection from the anchor to the 
3251:         // specified cell, clearing all other selections
3252:         selectionModel.setLeadSelectionIndex(rowIndex);
3253:         getColumnModel().getSelectionModel().setLeadSelectionIndex(columnIndex);
3254:       }
3255:     else
3256:       {
3257:         // Clear the previous selection and ensure the new cell
3258:         // is selected
3259:          selectionModel.clearSelection();
3260:         selectionModel.setSelectionInterval(rowIndex,rowIndex);
3261:         getColumnModel().getSelectionModel().clearSelection();
3262:         getColumnModel().getSelectionModel().setSelectionInterval(columnIndex, columnIndex);
3263:         
3264:         
3265:       }
3266:   }
3267: 
3268:   /**
3269:    * Programmatically starts editing the specified cell.
3270:    *
3271:    * @param row the row of the cell to edit.
3272:    * @param column the column of the cell to edit.
3273:    */
3274:   public boolean editCellAt (int row, int column)
3275:   {
3276:     oldCellValue = getValueAt(row, column);
3277:     setCellEditor(getCellEditor(row, column));
3278:     editorComp = prepareEditor(cellEditor, row, column);
3279:     cellEditor.addCellEditorListener(this);
3280:     rowBeingEdited = row;
3281:     columnBeingEdited = column;
3282:     setValueAt(editorComp, row, column);
3283:     ((JTextField)editorComp).requestFocusInWindow(false);
3284:     editorTimer.start();
3285:     return true;
3286:   }
3287: 
3288:   /**
3289:    * Programmatically starts editing the specified cell.
3290:    *
3291:    * @param row the row of the cell to edit.
3292:    * @param column the column of the cell to edit.
3293:    */
3294:   public boolean editCellAt (int row, int column, EventObject e)
3295:   {
3296:     return editCellAt(row, column);
3297:   }
3298: 
3299:   /**
3300:    * Discards the editor object.
3301:    */
3302:   public void removeEditor()
3303:   {
3304:     editingStopped(new ChangeEvent(this));
3305:   }
3306: 
3307:   /**
3308:    * Prepares the editor by querying for the value and selection state of the
3309:    * cell at (row, column).
3310:    *
3311:    * @param editor the TableCellEditor to set up
3312:    * @param row the row of the cell to edit
3313:    * @param column the column of the cell to edit
3314:    * @return the Component being edited
3315:    */
3316:   public Component prepareEditor (TableCellEditor editor, int row, int column)
3317:   {
3318:     return editor.getTableCellEditorComponent
3319:       (this, getValueAt(row, column), isCellSelected(row, column), row, column);
3320:   }
3321: 
3322:   /**
3323:    * This revalidates the <code>JTable</code> and queues a repaint.
3324:    */
3325:   protected void resizeAndRepaint()
3326:   {
3327:     revalidate();
3328:     repaint();
3329:   }
3330: 
3331:   /**
3332:    * Sets whether cell editors of this table should receive keyboard focus
3333:    * when the editor is activated by a keystroke. The default setting is
3334:    * <code>false</code> which means that the table should keep the keyboard
3335:    * focus until the cell is selected by a mouse click.
3336:    *
3337:    * @param value the value to set
3338:    *
3339:    * @since 1.4
3340:    */
3341:   public void setSurrendersFocusOnKeystroke(boolean value)
3342:   {
3343:     // TODO: Implement functionality of this property (in UI impl).
3344:     surrendersFocusOnKeystroke = value;
3345:   }
3346: 
3347:   /**
3348:    * Returns whether cell editors of this table should receive keyboard focus
3349:    * when the editor is activated by a keystroke. The default setting is
3350:    * <code>false</code> which means that the table should keep the keyboard
3351:    * focus until the cell is selected by a mouse click.
3352:    *
3353:    * @return whether cell editors of this table should receive keyboard focus
3354:    *         when the editor is activated by a keystroke
3355:    *
3356:    * @since 1.4
3357:    */
3358:   public boolean getSurrendersFocusOnKeystroke()
3359:   {
3360:     // TODO: Implement functionality of this property (in UI impl).
3361:     return surrendersFocusOnKeystroke;
3362:   }
3363: }