Source for javax.swing.JTable

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