OSDN Git Service

2005-04-19 Roman Kennke <roman@kennke.org>
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / JTable.java
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package javax.swing;
40
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Dimension;
44 import java.awt.Point;
45 import java.awt.Rectangle;
46 import java.util.Hashtable;
47 import java.util.Vector;
48
49 import javax.accessibility.Accessible;
50 import javax.accessibility.AccessibleContext;
51 import javax.swing.event.CellEditorListener;
52 import javax.swing.event.ChangeEvent;
53 import javax.swing.event.ListSelectionEvent;
54 import javax.swing.event.ListSelectionListener;
55 import javax.swing.event.TableColumnModelEvent;
56 import javax.swing.event.TableColumnModelListener;
57 import javax.swing.event.TableModelEvent;
58 import javax.swing.event.TableModelListener;
59 import javax.swing.plaf.TableUI;
60 import javax.swing.table.DefaultTableCellRenderer;
61 import javax.swing.table.DefaultTableColumnModel;
62 import javax.swing.table.DefaultTableModel;
63 import javax.swing.table.JTableHeader;
64 import javax.swing.table.TableCellEditor;
65 import javax.swing.table.TableCellRenderer;
66 import javax.swing.table.TableColumn;
67 import javax.swing.table.TableColumnModel;
68 import javax.swing.table.TableModel;
69
70 public class JTable extends JComponent
71   implements TableModelListener, Scrollable, TableColumnModelListener,
72              ListSelectionListener, CellEditorListener, Accessible
73 {
74   private static final long serialVersionUID = 3876025080382781659L;
75
76
77   /**
78    * When resizing columns, do not automatically change any columns. In this
79    * case the table should be enclosed in a {@link JScrollPane} in order to
80    * accomodate cases in which the table size exceeds its visible area.
81    */
82   public static final int AUTO_RESIZE_OFF = 0;
83
84   /**
85    * When resizing column <code>i</code>, automatically change only the
86    * single column <code>i+1</code> to provide or absorb excess space
87    * requirements.
88    */
89   public static final int AUTO_RESIZE_NEXT_COLUMN = 1;
90
91   /**
92    * When resizing column <code>i</code> in a table of <code>n</code>
93    * columns, automatically change all columns in the range <code>[i+1,
94    * n)</code>, uniformly, to provide or absorb excess space requirements.
95    */
96   public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2;
97   
98   /**
99    * When resizing column <code>i</code> in a table of <code>n</code>
100    * columns, automatically change all columns in the range <code>[0,
101    * n)</code> (with the exception of column i) uniformly, to provide or
102    * absorb excess space requirements.
103    */
104   public static final int AUTO_RESIZE_ALL_COLUMNS = 4;
105
106   /**
107    * When resizing column <code>i</code> in a table of <code>n</code>
108    * columns, automatically change column <code>n-1</code> (the last column
109    * in the table) to provide or absorb excess space requirements.
110    */
111   public static final int AUTO_RESIZE_LAST_COLUMN = 3;
112
113
114   /**
115    * A table mapping {@link java.lang.Class} objects to 
116    * {@link TableCellEditor} objects. This table is consulted by the 
117    * FIXME
118    */
119   protected Hashtable defaultEditorsByColumnClass;
120
121   /**
122    * A table mapping {@link java.lang.Class} objects to 
123    * {@link TableCellEditor} objects. This table is consulted by the 
124    * FIXME
125    */
126   protected Hashtable defaultRenderersByColumnClass;
127
128   /**
129    * The column that is edited, -1 if the table is not edited currently.
130    */
131   protected int editingColumn;
132
133   /**
134    * The row that is edited, -1 if the table is not edited currently.
135    */
136   protected int editingRow;
137
138   /**
139    * The component that is used for editing.
140    * <code>null</code> if the table is not editing currently.
141    *
142    */
143   protected transient Component editorComp;
144
145   /**
146    * Whether or not the table should automatically compute a matching
147    * {@link TableColumnModel} and assign it to the {@link #columnModel}
148    * property when the {@link #dataModel} property is changed. 
149    *
150    * @see #setModel()
151    * @see #createColumnsFromModel()
152    * @see #setColumnModel()
153    * @see #setAutoCreateColumnsFromModel()
154    * @see #getAutoCreateColumnsFromModel()
155    */
156   protected boolean autoCreateColumnsFromModel;
157
158   /**
159    * A numeric code specifying the resizing behavior of the table. Must be
160    * one of {@link #AUTO_RESIZE_ALL_COLUMNS} (the default), {@link
161    * #AUTO_RESIZE_LAST_COLUMN}, {@link #AUTO_RESIZE_NEXT_COLUMN}, {@link
162    * #AUTO_RESIZE_SUBSEQUENT_COLUMNS}, or {@link #AUTO_RESIZE_OFF}.
163    * 
164    * @see #doLayout()
165    * @see #setAutoResizeMode()
166    * @see #getAutoResizeMode()
167    */
168   protected int autoResizeMode;
169
170   /**
171    * The height in pixels of any row of the table. All rows in a table are
172    * of uniform height. This differs from column width, which varies on a
173    * per-column basis, and is stored in the individual columns of the
174    * {@link #columnModel}.
175    * 
176    * @see #getRowHeight()
177    * @see #setRowHeight()
178    * @see TableColumn#getWidth()
179    * @see TableColumn#setWidth()
180    */
181   protected int rowHeight;
182
183   /**
184    * The height in pixels of the gap left between any two rows of the table. 
185    * 
186    * @see #setRowMargin()
187    * @see #getRowHeight()
188    * @see #getIntercellSpacing()
189    * @see #setIntercellSpacing()
190    * @see TableColumnModel#getColumnMargin()
191    * @see TableColumnModel#setColumnMargin()
192    */
193   protected int rowMargin;
194
195   /**
196    * Whether or not the table should allow row selection. If the table
197    * allows both row <em>and</em> column selection, it is said to allow
198    * "cell selection". Previous versions of the JDK supported cell
199    * selection as an independent concept, but it is now represented solely
200    * in terms of simultaneous row and column selection.
201    *
202    * @see TableColumnModel#columnSelectionAllowed()
203    * @see #setRowSelectionAllowed()
204    * @see #getRowSelectionAllowed()
205    * @see #getCellSelectionEnabled()
206    * @see #setCellSelectionEnabled()
207    */
208   protected boolean rowSelectionAllowed;
209
210   /**
211    * @deprecated Use {@link #rowSelectionAllowed}, {@link
212    * #columnSelectionAllowed}, or the combined methods {@link
213    * getCellSelectionEnabled} and {@link setCellSelectionEnabled}.
214    */
215   protected boolean cellSelectionEnabled;
216   
217   /**
218    * The model for data stored in the table. Confusingly, the published API
219    * requires that this field be called <code>dataModel</code>, despite its
220    * property name. The table listens to its model as a {@link
221    * TableModelListener}.
222    *
223    * @see #tableChanged()
224    * @see TableModel#addTableModelListener()
225    */
226   protected TableModel dataModel;
227
228   /**
229    * <p>A model of various aspects of the columns of the table, <em>not
230    * including</em> the data stored in them. The {@link TableColumnModel}
231    * is principally concerned with holding a set of {@link TableColumn}
232    * objects, each of which describes the display parameters of a column
233    * and the numeric index of the column from the data model which the
234    * column is presenting.</p>
235    *
236    * <p>The TableColumnModel also contains a {@link ListSelectionModel} which
237    * indicates which columns are currently selected. This selection model
238    * works in combination with the {@link selectionModel} of the table
239    * itself to specify a <em>table selection</em>: a combination of row and
240    * column selections.</p>
241    *
242    * <p>Most application programmers do not need to work with this property
243    * at all: setting {@link #autoCreateColumnsFromModel} will construct the
244    * columnModel automatically, and the table acts as a facade for most of
245    * the interesting properties of the columnModel anyways.</p>
246    * 
247    * @see #setColumnModel()
248    * @see #getColumnModel()
249    */
250   protected TableColumnModel columnModel;
251
252   /**
253    * A model of the rows of this table which are currently selected. This
254    * model is used in combination with the column selection model held as a
255    * member of the {@link columnModel} property, to represent the rows and
256    * columns (or both: cells) of the table which are currently selected.
257    *
258    * @see #rowSelectionAllowed
259    * @see #setSelectionModel()
260    * @see #getSelectionModel()
261    * @see TableColumnModel#getSelectionModel()
262    * @see ListSelectionModel#addListSelectionListener()   
263    */
264   protected ListSelectionModel selectionModel;
265
266   /**
267    * The accessibleContext property.
268    */
269   protected AccessibleContext accessibleContext;
270
271   /**
272    * The current cell editor. 
273    */
274   protected TableCellEditor cellEditor;
275
276   /**
277    * Whether or not drag-and-drop is enabled on this table.
278    *
279    * @see #setDragEnabled()
280    * @see #getDragEnabled()
281    */
282   private boolean dragEnabled;
283
284   /**
285    * The color to paint the grid lines of the table, when either {@link
286    * #showHorizontalLines} or {@link #showVerticalLines} is set.
287    *
288    * @see #setGridColor()
289    * @see #getGridColor()
290    */
291   protected Color gridColor;
292
293   /**
294    * The size this table would prefer its viewport assume, if it is
295    * contained in a {@link JScrollPane}.
296    *
297    * @see #setPreferredScrollableViewportSize()
298    * @see #getPreferredScrollableViewportSize()
299    */
300   protected Dimension preferredViewportSize;
301
302   /**
303    * The color to paint the background of selected cells. Fires a property
304    * change event with name {@link #SELECTION_BACKGROUND_CHANGED_PROPERTY}
305    * when its value changes.
306    *
307    * @see #setSelectionBackground()
308    * @see #getSelectionBackground()
309    */
310   protected Color selectionBackground;
311
312   /**
313    * The name carried in property change events when the {@link
314    * #selectionBackground} property changes.
315    */
316   private static final String SELECTION_BACKGROUND_CHANGED_PROPERTY = "selectionBackground";
317
318   /**
319    * The color to paint the foreground of selected cells. Fires a property
320    * change event with name {@link #SELECTION_FOREGROUND_CHANGED_PROPERTY}
321    * when its value changes.
322    *
323    * @see #setSelectionForeground()
324    * @see #getSelectionForeground()
325    */
326   protected Color selectionForeground;
327
328   /**
329    * The name carried in property change events when the
330    * {@link #selectionForeground} property changes.
331    */
332   private static final String SELECTION_FOREGROUND_CHANGED_PROPERTY = "selectionForeground";
333
334   /**
335    * The showHorizontalLines property.
336    */
337   protected boolean showHorizontalLines;
338
339   /**
340    * The showVerticalLines property.
341    */
342   protected boolean showVerticalLines;
343
344   /**
345    * The tableHeader property.
346    */
347   protected JTableHeader tableHeader;
348
349   
350   /**
351    * Creates a new <code>JTable</code> instance.
352    */
353   public JTable ()
354   {
355     this(null, null, null);
356   }
357
358   /**
359    * Creates a new <code>JTable</code> instance.
360    *
361    * @param numRows an <code>int</code> value
362    * @param numColumns an <code>int</code> value
363    */
364   public JTable (int numRows, int numColumns)
365   {
366     this(new DefaultTableModel(numRows, numColumns));
367   }
368
369   /**
370    * Creates a new <code>JTable</code> instance.
371    *
372    * @param data an <code>Object[][]</code> value
373    * @param columnNames an <code>Object[]</code> value
374    */
375   public JTable(Object[][] data, Object[] columnNames)
376   {
377     this(new DefaultTableModel(data, columnNames));
378   }
379
380   /**
381    * Creates a new <code>JTable</code> instance.
382    *
383    * @param dm a <code>TableModel</code> value
384    */
385   public JTable (TableModel dm)
386   {
387     this(dm, null, null);
388   }
389
390   /**
391    * Creates a new <code>JTable</code> instance.
392    *
393    * @param dm a <code>TableModel</code> value
394    * @param cm a <code>TableColumnModel</code> value
395    */
396   public JTable (TableModel dm, TableColumnModel cm)
397   {
398     this(dm, cm, null);
399   }
400
401   /**
402    * Creates a new <code>JTable</code> instance.
403    *
404    * @param dm a <code>TableModel</code> value
405    * @param cm a <code>TableColumnModel</code> value
406    * @param sm a <code>ListSelectionModel</code> value
407    */
408   public JTable (TableModel dm, TableColumnModel cm, ListSelectionModel sm)
409   {
410     this.dataModel = dm == null ? createDefaultDataModel() : dm;
411     setSelectionModel(sm == null ? createDefaultSelectionModel() : sm);
412
413     this.columnModel = cm;
414     initializeLocalVars();
415     updateUI();
416   }    
417
418   protected void initializeLocalVars()
419   {
420     this.autoCreateColumnsFromModel = false;
421     if (columnModel == null)
422       {
423         this.autoCreateColumnsFromModel = true;
424         createColumnsFromModel();
425       }
426     this.columnModel.addColumnModelListener(this);
427     
428     this.defaultRenderersByColumnClass = new Hashtable();
429     createDefaultRenderers();
430
431     this.defaultEditorsByColumnClass = new Hashtable();
432     createDefaultEditors();
433
434     this.autoResizeMode = AUTO_RESIZE_ALL_COLUMNS;
435     this.rowHeight = 16;
436     this.rowMargin = 1;
437     this.rowSelectionAllowed = true;
438     // this.accessibleContext = new AccessibleJTable();
439     this.cellEditor = null;
440     this.dragEnabled = false;
441     this.preferredViewportSize = new Dimension(450,400);
442     this.showHorizontalLines = true;
443     this.showVerticalLines = true;
444     this.editingColumn = -1;
445     this.editingRow = -1;
446     setIntercellSpacing(new Dimension(1,1));
447     setTableHeader(createDefaultTableHeader());
448   }
449
450   /**
451    * Creates a new <code>JTable</code> instance.
452    *
453    * @param data a <code>Vector</code> value
454    * @param columnNames a <code>Vector</code> value
455    */
456   public JTable(Vector data, Vector columnNames)
457   {
458     this(new DefaultTableModel(data, columnNames));
459   }
460
461   public void addColumn(TableColumn column)
462   {
463     if (column.getHeaderValue() == null)
464       {
465         String name = getColumnName(column.getModelIndex());
466         column.setHeaderValue(name);
467       }
468     
469     columnModel.addColumn(column);
470   }
471
472   protected void createDefaultEditors()
473   {
474     //FIXME: Create the editor object.
475   }
476
477   protected void createDefaultRenderers()
478   {
479     //FIXME: Create the renderer object.
480   }
481   
482   /**
483    * @deprecated 1.0.2, replaced by <code>new JScrollPane(JTable)</code>
484    */
485   public static JScrollPane createScrollPaneForTable(JTable table)
486   {
487     return new JScrollPane(table);
488   }
489
490   protected TableColumnModel createDefaultColumnModel()
491   {
492     return new DefaultTableColumnModel();
493   }
494
495   protected TableModel createDefaultDataModel()
496   {
497     return new DefaultTableModel();
498   }
499
500   protected ListSelectionModel createDefaultSelectionModel()
501   {
502     return new DefaultListSelectionModel();
503   }
504
505   protected JTableHeader createDefaultTableHeader()
506   {
507     return new JTableHeader(columnModel);
508   }
509  
510   private void createColumnsFromModel()
511   {
512     if (dataModel == null)
513       return;
514
515     TableColumnModel cm = createDefaultColumnModel();
516
517     for (int i = 0; i < dataModel.getColumnCount(); ++i)
518       {
519         cm.addColumn(new TableColumn(i));
520       }
521     this.setColumnModel(cm);
522   }
523
524   // listener support 
525
526   public void columnAdded (TableColumnModelEvent event)
527   {
528     revalidate();
529     repaint();
530   }
531
532   public void columnMarginChanged (ChangeEvent event)
533   {
534     revalidate();
535     repaint();
536   }
537
538   public void columnMoved (TableColumnModelEvent event)
539   {
540     revalidate();
541     repaint();
542   }
543
544   public void columnRemoved (TableColumnModelEvent event)
545   {
546     revalidate();
547     repaint();
548   }
549   
550   public void columnSelectionChanged (ListSelectionEvent event)
551   {
552     repaint();
553   }
554
555   public void editingCanceled (ChangeEvent event)
556   {
557     repaint();
558   }
559
560   public void editingStopped (ChangeEvent event)
561   {
562     repaint();
563   }
564
565   public void tableChanged (TableModelEvent event)
566   {
567     repaint();
568   }
569
570   public void valueChanged (ListSelectionEvent event)
571   {
572     repaint();
573   }
574
575  /**
576    * Returns index of the column that contains specified point 
577    * or -1 if this table doesn't contain this point.
578    *
579    * @param point point to identify the column
580    * @return index of the column that contains specified point or 
581    * -1 if this table doesn't contain this point.
582    */
583   public int columnAtPoint(Point point)
584   {
585     int x0 = getLocation().x;
586     int ncols = getColumnCount();
587     Dimension gap = getIntercellSpacing();
588     TableColumnModel cols = getColumnModel();
589     int x = point.x;
590     
591     for (int i = 0; i < ncols; ++i)
592       {
593         int width = cols.getColumn(i).getWidth() + (gap == null ? 0 : gap.width);
594         if (0 <= x && x < width)
595           return i;
596         x -= width;  
597       }
598     
599     return -1;
600   }
601
602   /**
603    * Returns index of the row that contains specified point or 
604    * -1 if this table doesn't contain this point.
605    *
606    * @param point point to identify the row
607    * @return index of the row that contains specified point or 
608    * -1 if this table doesn't contain this point.
609    */
610   public int rowAtPoint(Point point)
611   {
612     int y0 = getLocation().y;
613     int nrows = getRowCount();
614     Dimension gap = getIntercellSpacing();
615     int height = getRowHeight() + (gap == null ? 0 : gap.height);
616     int y = point.y;
617     
618     for (int i = 0; i < nrows; ++i)
619       {
620         if (0 <= y && y < height)
621           return i;
622         y -= height;
623       }
624       
625     return -1;
626   }
627
628   /** 
629    * Calculate the visible rectangle for a particular row and column. The
630    * row and column are specified in visual terms; the column may not match
631    * the {@link #dataModel} column.
632    *
633    * @param row the visible row to get the cell rectangle of
634    *
635    * @param column the visible column to get the cell rectangle of, which may
636    * differ from the {@link #dataModel} column
637    *
638    * @param includeSpacing whether or not to include the cell margins in the
639    * resulting cell. If <code>false</code>, the result will only contain the
640    * inner area of the target cell, not including its margins.
641    *
642    * @return a rectangle enclosing the specified cell
643    */
644   public Rectangle getCellRect(int row,
645                                int column,
646                                boolean includeSpacing)
647   {
648     int height = getHeight();
649     int width = columnModel.getColumn(column).getWidth();
650     int x_gap = columnModel.getColumnMargin();
651     int y_gap = rowMargin;
652
653     column = Math.max(0, Math.min(column, getColumnCount() - 1));
654     row = Math.max(0, Math.min(row, getRowCount() - 1));
655
656     int x = 0;
657     int y = (height + y_gap) * row;
658
659     for (int i = 0; i < column; ++i)
660       {        
661         x += columnModel.getColumn(i).getWidth();
662         x += x_gap;
663       }
664
665     if (includeSpacing)
666       return new Rectangle(x, y, width, height);
667     else
668       return new Rectangle(x, y, width - x_gap, height - y_gap);
669   }
670
671   public void clearSelection()
672   {
673     selectionModel.clearSelection();
674   }
675
676   /**
677    * Get the value of the {@link #selectedRow} property by delegation to
678    * the {@link ListSelectionModel#getMinSelectionIndex} method of the
679    * {@link #selectionModel} field.
680    *
681    * @return The current value of the selectedRow property
682    */
683   public int getSelectedRow ()
684   {
685     return selectionModel.getMinSelectionIndex();
686   }
687   
688   /**
689    * Get the value of the {@link #selectionModel} property.
690    *
691    * @return The current value of the property
692    */
693   public ListSelectionModel getSelectionModel()
694   {
695     if (! rowSelectionAllowed)
696       return null;
697
698     return selectionModel;
699   }
700   
701   public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
702   {
703     if (orientation == SwingConstants.VERTICAL)
704       return visibleRect.height * direction;
705     else
706       return visibleRect.width * direction;
707   }
708
709   /**
710    * Get the value of the {@link #scrollableTracksViewportHeight} property.
711    *
712    * @return The constant value <code>false</code>
713    */
714
715   public boolean getScrollableTracksViewportHeight()
716   {
717     return false;
718   }
719   
720   /**
721    * Get the value of the {@link #scrollableTracksViewportWidth} property.
722    *
723    * @return <code>true</code> unless the {@link autoResizeMode} prperty is
724    * <code>AUTO_RESIZE_OFF</code>
725    */
726
727   public boolean getScrollableTracksViewportWidth()
728   {
729     if (autoResizeMode == AUTO_RESIZE_OFF)
730       return false;
731     else
732       return true;
733   }
734
735   public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
736   {
737     // FIXME: I don't exactly know what sun does here. in both cases they
738     // pick values which do *not* simply expose the next cell in a given
739     // scroll direction.
740
741     if (orientation == SwingConstants.VERTICAL)
742       return rowHeight;
743     else
744       {
745         int sum = 0;
746         for (int i = 0; i < getColumnCount(); ++i)
747           sum += columnModel.getColumn(0).getWidth();
748         return getColumnCount() == 0 ? 10 : sum / getColumnCount();
749       }
750   }
751
752
753   public TableCellEditor getCellEditor(int row, int column)
754   {
755     TableCellEditor editor = columnModel.getColumn(column).getCellEditor();
756
757     if (editor == null)
758       editor = getDefaultEditor(dataModel.getColumnClass(column));
759
760     return editor;
761   }
762
763   public TableCellEditor getDefaultEditor(Class columnClass)
764   {
765     if (defaultEditorsByColumnClass.containsKey(columnClass))
766       return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass);
767     else
768       {
769         // FIXME: We have at least an editor for Object.class in our defaults.
770         TableCellEditor r = new DefaultCellEditor(new JTextField());
771         defaultEditorsByColumnClass.put(columnClass, r);
772         return r;
773       }
774   }
775
776
777
778   public TableCellRenderer getCellRenderer(int row, int column)
779   {
780     TableCellRenderer renderer =
781       columnModel.getColumn(column).getCellRenderer();
782     
783     if (renderer == null)
784       renderer = getDefaultRenderer(dataModel.getColumnClass(column));
785     
786     return renderer;
787   }
788
789   public void setDefaultRenderer(Class columnClass, TableCellRenderer rend)
790   {
791     defaultRenderersByColumnClass.put(columnClass, rend);
792   }
793
794   public TableCellRenderer getDefaultRenderer(Class columnClass)
795   {
796     if (defaultRenderersByColumnClass.containsKey(columnClass))
797       return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass);
798     else
799       {
800         TableCellRenderer r = new DefaultTableCellRenderer();
801         defaultRenderersByColumnClass.put(columnClass, r);
802         return r;
803       }
804   }
805
806   public int convertColumnIndexToModel(int vc)
807   {
808     if (vc < 0)
809       return vc;
810     else if (vc > getColumnCount())
811       return -1;
812     else
813       return columnModel.getColumn(vc).getModelIndex();
814   }
815
816   public int convertColumnIndexToView(int mc)
817   {
818     if (mc < 0)
819       return mc;
820     int ncols = getColumnCount();
821     for (int vc = 0; vc < ncols; ++vc)
822       {
823         if (columnModel.getColumn(vc).getModelIndex() == mc)
824           return vc;
825       }
826     return -1;
827   }
828
829   public Component prepareRenderer(TableCellRenderer renderer,
830                                    int row,
831                                    int column)
832   {
833     boolean rsa = getRowSelectionAllowed();
834     boolean csa = getColumnSelectionAllowed();
835     boolean rs = rsa ? getSelectionModel().isSelectedIndex(row) : false;
836     boolean cs = csa ? columnModel.getSelectionModel().isSelectedIndex(column) : false;
837     boolean isSelected = ((rsa && csa && rs && cs) 
838                           || (rsa && !csa && rs) 
839                           || (!rsa && csa && cs));
840     
841     return renderer.getTableCellRendererComponent(this,
842                                                   dataModel.getValueAt(row, 
843                                                                        convertColumnIndexToModel(column)),
844                                                   isSelected,
845                                                   false, // hasFocus
846                                                   row, column);
847   }
848
849
850   /**
851    * Get the value of the {@link #autoCreateColumnsFromModel} property.
852    *
853    * @return The current value of the property
854    */
855   public boolean getAutoCreateColumnsFromModel()
856   {
857     return autoCreateColumnsFromModel;
858   }
859
860   /**
861    * Get the value of the {@link #autoResizeMode} property.
862    *
863    * @return The current value of the property
864    */
865   public int getAutoResizeMode()
866   {
867     return autoResizeMode;
868   }
869
870   /**
871    * Get the value of the {@link #rowHeight} property.
872    *
873    * @return The current value of the property
874    */
875   public int getRowHeight()
876   {
877     return rowHeight;
878   }
879
880   /**
881    * Get the value of the {@link #rowMargin} property.
882    *
883    * @return The current value of the property
884    */
885   public int getRowMargin()
886   {
887     return rowMargin;
888   }
889
890   /**
891    * Get the value of the {@link #rowSelectionAllowed} property.
892    *
893    * @return The current value of the property
894    */
895   public boolean getRowSelectionAllowed()
896   {
897     return rowSelectionAllowed;
898   }
899
900   /**
901    * Get the value of the {@link #cellSelectionEnabled} property.
902    *
903    * @return The current value of the property
904    */
905   public boolean getCellSelectionEnabled()
906   {
907     return getColumnSelectionAllowed() && getRowSelectionAllowed();
908   }
909
910   /**
911    * Get the value of the {@link #dataModel} property.
912    *
913    * @return The current value of the property
914    */
915   public TableModel getModel()
916   {
917     return dataModel;
918   }
919
920   /**
921    * Get the value of the {@link #columnCount} property by
922    * delegation to the @{link #columnModel} field.
923    *
924    * @return The current value of the columnCount property
925    */
926   public int getColumnCount()
927   {
928     return columnModel.getColumnCount();    
929   }
930
931   /**
932    * Get the value of the {@link #rowCount} property by
933    * delegation to the @{link #dataModel} field.
934    *
935    * @return The current value of the rowCount property
936    */
937   public int getRowCount()
938   {
939     return dataModel.getRowCount();
940   }
941
942   /**
943    * Get the value of the {@link #columnModel} property.
944    *
945    * @return The current value of the property
946    */
947   public TableColumnModel getColumnModel()
948   {
949     return columnModel;
950   }
951
952   /**
953    * Get the value of the {@link #selectedColumn} property by
954    * delegation to the @{link #columnModel} field.
955    *
956    * @return The current value of the selectedColumn property
957    */
958   public int getSelectedColumn()
959   {
960     return columnModel.getSelectionModel().getMinSelectionIndex();
961   }
962
963   private static int countSelections(ListSelectionModel lsm)
964   {
965     int lo = lsm.getMinSelectionIndex();
966     int hi = lsm.getMaxSelectionIndex();
967     int sum = 0;
968     if (lo != -1 && hi != -1)
969       {
970         switch (lsm.getSelectionMode())
971           {
972           case ListSelectionModel.SINGLE_SELECTION:
973             sum = 1;
974             break;
975             
976           case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
977             sum = hi - lo + 1;
978             break;
979             
980           case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
981             for (int i = lo; i <= hi; ++i)
982               if (lsm.isSelectedIndex(i))        
983                 ++sum;
984             break;
985           }
986       }
987     return sum;
988   }
989
990   private static int[] getSelections(ListSelectionModel lsm)
991   {
992     int sz = countSelections(lsm);
993     int [] ret = new int[sz];
994
995     int lo = lsm.getMinSelectionIndex();
996     int hi = lsm.getMaxSelectionIndex();
997     int j = 0;
998     java.util.ArrayList ls = new java.util.ArrayList();
999     if (lo != -1 && hi != -1)
1000       {
1001         switch (lsm.getSelectionMode())
1002           {
1003           case ListSelectionModel.SINGLE_SELECTION:
1004             ret[0] = lo;
1005             break;      
1006       
1007           case ListSelectionModel.SINGLE_INTERVAL_SELECTION:            
1008             for (int i = lo; i <= hi; ++i)
1009               ret[j++] = i;
1010             break;
1011             
1012           case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:        
1013             for (int i = lo; i <= hi; ++i)
1014               if (lsm.isSelectedIndex(i))        
1015                 ret[j++] = i;
1016             break;
1017           }
1018       }
1019     return ret;
1020   }
1021
1022   /**
1023    * Get the value of the {@link #selectedColumnCount} property by
1024    * delegation to the @{link #columnModel} field.
1025    *
1026    * @return The current value of the selectedColumnCount property
1027    */  
1028   public int getSelectedColumnCount()
1029   {
1030     return countSelections(columnModel.getSelectionModel());
1031   }
1032
1033   /**
1034    * Get the value of the {@link #selectedColumns} property by
1035    * delegation to the @{link #columnModel} field.
1036    *
1037    * @return The current value of the selectedColumns property
1038    */
1039   public int[] getSelectedColumns()
1040   {
1041     return getSelections(columnModel.getSelectionModel());
1042   }
1043
1044   /**
1045    * Get the value of the {@link #columnSelectionAllowed} property.
1046    *
1047    * @return The current value of the columnSelectionAllowed property
1048    */
1049   public boolean getColumnSelectionAllowed()
1050   {
1051     return getColumnModel().getColumnSelectionAllowed();
1052   }
1053
1054   /**
1055    * Get the value of the {@link #selectedRowCount} property by
1056    * delegation to the @{link #selectionModel} field.
1057    *
1058    * @return The current value of the selectedRowCount property
1059    */
1060   public int getSelectedRowCount()
1061   {
1062     return countSelections(selectionModel);
1063   }
1064
1065   /**
1066    * Get the value of the {@link #selectedRows} property by
1067    * delegation to the @{link #selectionModel} field.
1068    *
1069    * @return The current value of the selectedRows property
1070    */
1071   public int[] getSelectedRows()
1072   {
1073     return getSelections(selectionModel);
1074   }
1075
1076   /**
1077    * Get the value of the {@link #accessibleContext} property.
1078    *
1079    * @return The current value of the property
1080    */
1081   public AccessibleContext getAccessibleContext()
1082   {
1083     return accessibleContext;
1084   }
1085
1086   /**
1087    * Get the value of the {@link #cellEditor} property.
1088    *
1089    * @return The current value of the property
1090    */
1091   public TableCellEditor getCellEditor()
1092   {
1093     return cellEditor;
1094   }
1095
1096   /**
1097    * Get the value of the {@link #dragEnabled} property.
1098    *
1099    * @return The current value of the property
1100    */
1101   public boolean getDragEnabled()
1102   {
1103     return dragEnabled;
1104   }
1105
1106   /**
1107    * Get the value of the {@link #gridColor} property.
1108    *
1109    * @return The current value of the property
1110    */
1111   public Color getGridColor()
1112   {
1113     return gridColor;
1114   }
1115
1116   /**
1117    * Get the value of the {@link #intercellSpacing} property.
1118    *
1119    * @return The current value of the property
1120    */
1121   public Dimension getIntercellSpacing()
1122   {
1123     return new Dimension(columnModel.getColumnMargin(), rowMargin);
1124   }
1125
1126   /**
1127    * Get the value of the {@link #preferredViewportSize} property.
1128    *
1129    * @return The current value of the property
1130    */
1131   public Dimension getPreferredScrollableViewportSize()
1132   {
1133     return preferredViewportSize;
1134   }
1135
1136   /**
1137    * Get the value of the {@link #selectionBackground} property.
1138    *
1139    * @return The current value of the property
1140    */
1141   public Color getSelectionBackground()
1142   {
1143     return selectionBackground;
1144   }
1145
1146   /**
1147    * Get the value of the {@link #selectionForeground} property.
1148    *
1149    * @return The current value of the property
1150    */
1151   public Color getSelectionForeground()
1152   {
1153     return selectionForeground;
1154   }
1155
1156   /**
1157    * Get the value of the {@link #showHorizontalLines} property.
1158    *
1159    * @return The current value of the property
1160    */
1161   public boolean getShowHorizontalLines()
1162   {
1163     return showHorizontalLines;
1164   }
1165
1166   /**
1167    * Get the value of the {@link #showVerticalLines} property.
1168    *
1169    * @return The current value of the property
1170    */
1171   public boolean getShowVerticalLines()
1172   {
1173     return showVerticalLines;
1174   }
1175
1176   /**
1177    * Get the value of the {@link #tableHeader} property.
1178    *
1179    * @return The current value of the property
1180    */
1181   public JTableHeader getTableHeader()
1182   {
1183     return tableHeader;
1184   }
1185
1186   /**
1187    * Removes specified column from displayable columns of this table.
1188    *
1189    * @param column column to removed
1190    */
1191   public void removeColumn(TableColumn column)
1192   {    
1193     columnModel.removeColumn(column);
1194   }
1195
1196   /**
1197    * Moves column at the specified index to new given location.
1198    *
1199    * @param column index of the column to move
1200    * @param targetColumn index specifying new location of the column
1201    */ 
1202   public void moveColumn(int column,int targetColumn) 
1203   {
1204     columnModel.moveColumn(column, targetColumn);
1205   }
1206
1207   /**
1208    * Set the value of the {@link #autoCreateColumnsFromModel} property.
1209    *
1210    * @param a The new value of the autoCreateColumnsFromModel property
1211    */ 
1212   public void setAutoCreateColumnsFromModel(boolean a)
1213   {
1214     autoCreateColumnsFromModel = a;
1215   }
1216
1217   /**
1218    * Set the value of the {@link #autoResizeMode} property.
1219    *
1220    * @param a The new value of the autoResizeMode property
1221    */ 
1222   public void setAutoResizeMode(int a)
1223   {
1224     autoResizeMode = a;
1225     revalidate();
1226     repaint();
1227   }
1228
1229   /**
1230    * Set the value of the {@link #rowHeight} property.
1231    *
1232    * @param r The new value of the rowHeight property
1233    */ 
1234   public void setRowHeight(int r)
1235   {
1236     if (rowHeight < 1)
1237       throw new IllegalArgumentException();
1238     
1239     rowHeight = r;
1240     revalidate();
1241     repaint();
1242   }
1243
1244   /**
1245    * Set the value of the {@link #rowMargin} property.
1246    *
1247    * @param r The new value of the rowMargin property
1248    */ 
1249   public void setRowMargin(int r)
1250   {
1251     rowMargin = r;
1252     revalidate();
1253     repaint();
1254   }
1255
1256   /**
1257    * Set the value of the {@link #rowSelectionAllowed} property.
1258    *
1259    * @param r The new value of the rowSelectionAllowed property
1260    */ 
1261   public void setRowSelectionAllowed(boolean r)
1262   {
1263     rowSelectionAllowed = r;
1264     repaint();
1265   }
1266
1267   /**
1268    * Set the value of the {@link #cellSelectionEnabled} property.
1269    *
1270    * @param c The new value of the cellSelectionEnabled property
1271    */ 
1272   public void setCellSelectionEnabled(boolean c)
1273   {
1274     setColumnSelectionAllowed(c);
1275     setRowSelectionAllowed(c);
1276     // for backward-compatibility sake:
1277     cellSelectionEnabled = true;
1278   }
1279
1280   /**
1281    * <p>Set the value of the {@link #dataModel} property.</p>
1282    *
1283    * <p>Unregister <code>this</code> as a {@link TableModelListener} from
1284    * previous {@link #dataModel} and register it with new parameter
1285    * <code>m</code>.</p>
1286    *
1287    * @param m The new value of the model property
1288    */ 
1289   public void setModel(TableModel m)
1290   {
1291     // Throw exception is m is null.
1292     if (m == null)
1293       throw new IllegalArgumentException();
1294    
1295     // Don't do anything if setting the current model again.
1296     if (dataModel == m)
1297       return;
1298     
1299     // Remove table as TableModelListener from old model.
1300     if (dataModel != null)
1301       dataModel.removeTableModelListener(this);
1302     
1303     if (m != null)
1304       {
1305         // Set property.
1306         dataModel = m;
1307
1308         // Add table as TableModelListener to new model.
1309         dataModel.addTableModelListener(this);
1310
1311         // Automatically create columns.
1312         if (autoCreateColumnsFromModel)
1313           createColumnsFromModel();
1314       }
1315     
1316     // Repaint table.
1317     revalidate();
1318     repaint();
1319   }
1320
1321   /**
1322    * <p>Set the value of the {@link #columnModel} property.</p>
1323    *
1324    * <p>Unregister <code>this</code> as a {@link TableColumnModelListener}
1325    * from previous {@link #columnModel} and register it with new parameter
1326    * <code>c</code>.</p>
1327    *
1328    * @param c The new value of the columnModel property
1329    */ 
1330   public void setColumnModel(TableColumnModel c)
1331   {
1332     if (c == null)
1333       throw new IllegalArgumentException();
1334     TableColumnModel tmp = columnModel;
1335     if (tmp != null)
1336       tmp.removeColumnModelListener(this);
1337     if (c != null)
1338       c.addColumnModelListener(this);
1339     columnModel = c;
1340     if (dataModel != null && columnModel != null)
1341       {
1342         int ncols = getColumnCount();
1343         for (int i = 0; i < ncols; ++i)
1344           columnModel.getColumn(i).setHeaderValue(dataModel.getColumnName(i));
1345       }
1346     revalidate();
1347     repaint();
1348   }
1349
1350   /**
1351    * Set the value of the {@link #columnSelectionAllowed} property.
1352    *
1353    * @param c The new value of the property
1354    */ 
1355   public void setColumnSelectionAllowed(boolean c)
1356   {
1357     getColumnModel().setColumnSelectionAllowed(c);
1358     repaint();
1359   }
1360
1361   /**
1362    * <p>Set the value of the {@link #selectionModel} property.</p>
1363    *
1364    * <p>Unregister <code>this</code> as a {@link ListSelectionListener}
1365    * from previous {@link #selectionModel} and register it with new
1366    * parameter <code>s</code>.</p>
1367    *
1368    * @param s The new value of the selectionModel property
1369    */ 
1370   public void setSelectionModel(ListSelectionModel s)
1371   {
1372     if (s == null)
1373       throw new IllegalArgumentException();
1374     ListSelectionModel tmp = selectionModel;
1375     if (tmp != null)
1376       tmp.removeListSelectionListener(this);
1377     if (s != null)
1378       s.addListSelectionListener(this);
1379     selectionModel = s;
1380   }
1381
1382   /**
1383    * Set the value of the {@link #selectionMode} property by
1384    * delegation to the {@link #selectionModel} field. The same selection
1385    * mode is set for row and column selection models.
1386    *
1387    * @param s The new value of the property
1388    */ 
1389   public void setSelectionMode(int s)
1390   { 
1391     selectionModel.setSelectionMode(s);    
1392     columnModel.getSelectionModel().setSelectionMode(s);
1393     
1394     repaint();
1395   }
1396
1397   /**
1398    * <p>Set the value of the {@link #cellEditor} property.</p>
1399    *
1400    * <p>Unregister <code>this</code> as a {@link CellEditorListener} from
1401    * previous {@link #cellEditor} and register it with new parameter
1402    * <code>c</code>.</p>
1403    *
1404    * @param c The new value of the cellEditor property
1405    */ 
1406   public void setCellEditor(TableCellEditor c)
1407   {
1408     TableCellEditor tmp = cellEditor;
1409     if (tmp != null)
1410       tmp.removeCellEditorListener(this);
1411     if (c != null)
1412       c.addCellEditorListener(this);
1413     cellEditor = c;
1414   }
1415
1416   /**
1417    * Set the value of the {@link #dragEnabled} property.
1418    *
1419    * @param d The new value of the dragEnabled property
1420    */ 
1421   public void setDragEnabled(boolean d)
1422   {
1423     dragEnabled = d;
1424   }
1425
1426   /**
1427    * Set the value of the {@link #gridColor} property.
1428    *
1429    * @param g The new value of the gridColor property
1430    */ 
1431   public void setGridColor(Color g)
1432   {
1433     gridColor = g;
1434     repaint();
1435   }
1436
1437   /**
1438    * Set the value of the {@link #intercellSpacing} property.
1439    *
1440    * @param i The new value of the intercellSpacing property
1441    */ 
1442   public void setIntercellSpacing(Dimension i)
1443   {
1444     rowMargin = i.height;
1445     columnModel.setColumnMargin(i.width);
1446     repaint();
1447   }
1448
1449   /**
1450    * Set the value of the {@link #preferredViewportSize} property.
1451    *
1452    * @param p The new value of the preferredViewportSize property
1453    */ 
1454   public void setPreferredScrollableViewportSize(Dimension p)
1455   {
1456     preferredViewportSize = p;
1457     revalidate();
1458     repaint();
1459   }
1460
1461   /**
1462    * <p>Set the value of the {@link #selectionBackground} property.</p>
1463    *
1464    * <p>Fire a PropertyChangeEvent with name {@link
1465    * #SELECTION_BACKGROUND_CHANGED_PROPERTY} to registered listeners, if
1466    * selectionBackground changed.</p>
1467    *
1468    * @param s The new value of the selectionBackground property
1469    */ 
1470   public void setSelectionBackground(Color s)
1471   {
1472     Color tmp = selectionBackground;
1473     selectionBackground = s;
1474     if (((tmp == null && s != null)
1475          || (s == null && tmp != null)
1476          || (tmp != null && s != null && !tmp.equals(s))))
1477       firePropertyChange(SELECTION_BACKGROUND_CHANGED_PROPERTY, tmp, s);
1478     repaint();
1479   }
1480
1481   /**
1482    * <p>Set the value of the {@link #selectionForeground} property.</p>
1483    *
1484    * <p>Fire a PropertyChangeEvent with name {@link
1485    * SELECTION_FOREGROUND_CHANGED_PROPERTY} to registered listeners, if
1486    * selectionForeground changed.</p>
1487    *
1488    * @param s The new value of the selectionForeground property
1489    */ 
1490   public void setSelectionForeground(Color s)
1491   {
1492     Color tmp = selectionForeground;
1493     selectionForeground = s;
1494     if (((tmp == null && s != null)
1495          || (s == null && tmp != null)
1496          || (tmp != null && s != null && !tmp.equals(s))))
1497       firePropertyChange(SELECTION_FOREGROUND_CHANGED_PROPERTY, tmp, s);
1498     repaint();
1499   }
1500
1501   /**
1502    * Set the value of the {@link #showGrid} property.
1503    *
1504    * @param s The new value of the showGrid property
1505    */ 
1506   public void setShowGrid(boolean s)
1507   {
1508     setShowVerticalLines(s);
1509     setShowHorizontalLines(s);
1510   }
1511
1512   /**
1513    * Set the value of the {@link #showHorizontalLines} property.
1514    *
1515    * @param s The new value of the showHorizontalLines property
1516    */ 
1517   public void setShowHorizontalLines(boolean s)
1518   {
1519     showHorizontalLines = s;
1520     repaint();
1521   }
1522
1523   /**
1524    * Set the value of the {@link #showVerticalLines} property.
1525    *
1526    * @param s The new value of the showVerticalLines property
1527    */ 
1528   public void setShowVerticalLines(boolean s)
1529   {
1530     showVerticalLines = s;
1531     repaint();
1532   }
1533
1534   /**
1535    * Set the value of the {@link #tableHeader} property.
1536    *
1537    * @param t The new value of the tableHeader property
1538    */ 
1539   public void setTableHeader(JTableHeader t)
1540   {
1541     if (tableHeader != null)
1542       tableHeader.setTable(null);
1543     tableHeader = t;
1544     if (tableHeader != null)
1545       tableHeader.setTable(this);
1546     revalidate();
1547     repaint();
1548   }
1549
1550   protected void configureEnclosingScrollPane()
1551   {
1552     JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
1553     if (jsp != null && tableHeader != null)
1554       {
1555         jsp.setColumnHeaderView(tableHeader);
1556       }
1557   }
1558
1559   protected void unconfigureEnclosingScrollPane()
1560   {
1561     JScrollPane jsp = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
1562     if (jsp != null)
1563       {
1564         jsp.setColumnHeaderView(null);
1565       }    
1566   }
1567
1568
1569   public void addNotify()
1570   {
1571     super.addNotify();
1572     configureEnclosingScrollPane();
1573   }
1574
1575   public void removeNotify()
1576   {
1577     super.addNotify();
1578     unconfigureEnclosingScrollPane();
1579   }
1580
1581
1582   /**
1583    * Sun javadocs describe an unusual implementation of
1584    * <code>doLayout</code> which involves some private interfaces. We try
1585    * to implement the same algorithm as is documented, but using the
1586    * columnModel directly. We still use a private helper method, but it has
1587    * a simpler signature.
1588    */
1589
1590   private void distributeSpill(TableColumn[] cols, int spill)
1591   {
1592     int MIN = 0;
1593     int MAX = 0;
1594     int PREF = 0;
1595
1596     int[] min = new int[cols.length];
1597     int[] max = new int[cols.length];
1598     int[] pref = new int[cols.length];
1599
1600     for (int i = 0; i < cols.length; ++i)
1601       {
1602         pref[i] = cols[i].getPreferredWidth();
1603         min[i] = cols[i].getMinWidth();
1604         max[i] = cols[i].getMaxWidth();
1605         PREF += pref[i];
1606         MIN += min[i];
1607         MAX += max[i];
1608       }
1609
1610     for (int i = 0; i < cols.length; ++i)
1611       {
1612         int adj = 0;
1613         if (spill > 0)          
1614           adj = (spill * (pref[i] - min[i])) / (PREF - MIN);
1615         else
1616           adj = (spill * (max[i] - pref[i])) / (MAX - PREF);
1617         cols[i].setWidth(pref[i] + adj);        
1618       }    
1619   }
1620   
1621   public void doLayout()
1622   {
1623     TableColumn resizingColumn = null;
1624
1625     int ncols = getColumnCount();
1626     if (ncols < 1)
1627       return;
1628
1629     int[] pref = new int[ncols];
1630     int prefSum = 0;
1631     int rCol = -1;
1632
1633     if (tableHeader != null)
1634       resizingColumn = tableHeader.getResizingColumn();
1635
1636     for (int i = 0; i < ncols; ++i)
1637       {
1638         TableColumn col = columnModel.getColumn(i);
1639         int p = col.getWidth();
1640         pref[i] = p;
1641         prefSum += p;
1642         if (resizingColumn == col)
1643           rCol = i;
1644       }
1645
1646     int spill = prefSum - getWidth();
1647
1648     if (resizingColumn != null)
1649       {
1650         TableColumn col;
1651         TableColumn [] cols;
1652
1653         switch (getAutoResizeMode())
1654           {
1655           case AUTO_RESIZE_LAST_COLUMN:
1656             col = columnModel.getColumn(ncols-1);
1657             col.setWidth(col.getPreferredWidth() + spill);
1658             break;
1659             
1660           case AUTO_RESIZE_NEXT_COLUMN:
1661             col = columnModel.getColumn(ncols-1);
1662             col.setWidth(col.getPreferredWidth() + spill);
1663             break;
1664
1665           case AUTO_RESIZE_ALL_COLUMNS:
1666             cols = new TableColumn[ncols];
1667             for (int i = 0; i < ncols; ++i)
1668               cols[i] = columnModel.getColumn(i);
1669             distributeSpill(cols, spill);
1670             break;
1671
1672           case AUTO_RESIZE_SUBSEQUENT_COLUMNS:
1673             cols = new TableColumn[ncols];
1674             for (int i = rCol; i < ncols; ++i)
1675               cols[i] = columnModel.getColumn(i);
1676             distributeSpill(cols, spill);
1677             break;
1678
1679           case AUTO_RESIZE_OFF:
1680           default:
1681           }
1682       }
1683     else
1684       {
1685         TableColumn [] cols = new TableColumn[ncols];
1686         for (int i = 0; i < ncols; ++i)
1687           cols[i] = columnModel.getColumn(i);
1688         distributeSpill(cols, spill);        
1689       }
1690   }
1691   
1692   /**
1693    * @deprecated Replaced by <code>doLayout()</code>
1694    */
1695   public void sizeColumnsToFit(boolean lastColumnOnly)
1696   {
1697     doLayout();
1698   }
1699
1700   /**
1701    * Obsolete since JDK 1.4. Please use <code>doLayout()</code>.
1702    */
1703   public void sizeColumnsToFit(int resizingColumn)
1704   {
1705     doLayout();
1706   }
1707
1708   public String getUIClassID()
1709   {
1710     return "TableUI";
1711   }
1712
1713   /**
1714    * This method returns the table's UI delegate.
1715    *
1716    * @return The table's UI delegate.
1717    */
1718   public TableUI getUI()
1719   {
1720     return (TableUI) ui;
1721   }
1722
1723   /**
1724    * This method sets the table's UI delegate.
1725    *
1726    * @param ui The table's UI delegate.
1727    */
1728   public void setUI(TableUI ui)
1729   {
1730     super.setUI(ui);
1731   }
1732
1733   public void updateUI()
1734   {
1735     setUI((TableUI) UIManager.getUI(this));
1736     revalidate();
1737     repaint();
1738   }
1739
1740   public Class getColumnClass(int column)
1741   {
1742     return dataModel.getColumnClass(column);
1743   }
1744   
1745   public String getColumnName(int column)
1746   {
1747     return dataModel.getColumnName(column);
1748   }
1749
1750   public int getEditingColumn()
1751   {
1752     return editingColumn;
1753   }
1754
1755   public void setEditingColumn(int column)
1756   {
1757     editingColumn = column;
1758   }
1759   
1760   public int getEditingRow()
1761   {
1762     return editingRow;
1763   }
1764
1765   public void setEditingRow(int column)
1766   {
1767     editingRow = column;
1768   }
1769   
1770   public Component getEditorComponent()
1771   {
1772     return editorComp;
1773   }
1774   
1775   public boolean isEditing()
1776   {
1777     return editorComp != null;
1778   }
1779
1780   public void setDefaultEditor(Class columnClass, TableCellEditor editor)
1781   {
1782     if (editor != null)
1783       defaultEditorsByColumnClass.put(columnClass, editor);
1784     else
1785       defaultEditorsByColumnClass.remove(columnClass);
1786   }
1787
1788   public void addColumnSelectionInterval(int index0, int index1)
1789   {
1790     if ((index0 < 0 || index0 > (getColumnCount()-1)
1791          || index1 < 0 || index1 > (getColumnCount()-1)))
1792       throw new IllegalArgumentException("Column index out of range.");
1793     
1794     getColumnModel().getSelectionModel().addSelectionInterval(index0, index1);
1795   }
1796   
1797   public void addRowSelectionInterval(int index0, int index1)
1798   {            
1799     if ((index0 < 0 || index0 > (getRowCount()-1)
1800          || index1 < 0 || index1 > (getRowCount()-1)))
1801       throw new IllegalArgumentException("Row index out of range.");
1802         
1803     getSelectionModel().addSelectionInterval(index0, index1);
1804   }
1805   
1806   public void setColumnSelectionInterval(int index0, int index1)
1807   {
1808     if ((index0 < 0 || index0 > (getColumnCount()-1)
1809          || index1 < 0 || index1 > (getColumnCount()-1)))
1810       throw new IllegalArgumentException("Column index out of range.");
1811
1812     getColumnModel().getSelectionModel().setSelectionInterval(index0, index1);
1813   }
1814   
1815   public void setRowSelectionInterval(int index0, int index1)
1816   {    
1817     if ((index0 < 0 || index0 > (getRowCount()-1)
1818          || index1 < 0 || index1 > (getRowCount()-1)))
1819       throw new IllegalArgumentException("Row index out of range.");
1820
1821     getSelectionModel().setSelectionInterval(index0, index1);
1822   }
1823   
1824   public void removeColumnSelectionInterval(int index0, int index1)  
1825   {
1826     if ((index0 < 0 || index0 > (getColumnCount()-1)
1827          || index1 < 0 || index1 > (getColumnCount()-1)))
1828       throw new IllegalArgumentException("Column index out of range.");
1829
1830     getColumnModel().getSelectionModel().removeSelectionInterval(index0, index1);
1831   }
1832   
1833   public void removeRowSelectionInterval(int index0, int index1)
1834   {
1835     if ((index0 < 0 || index0 > (getRowCount()-1)
1836          || index1 < 0 || index1 > (getRowCount()-1)))
1837       throw new IllegalArgumentException("Row index out of range.");
1838
1839     getSelectionModel().removeSelectionInterval(index0, index1);
1840   }
1841   
1842   public boolean isColumnSelected(int column)
1843   {
1844     return getColumnModel().getSelectionModel().isSelectedIndex(column);
1845   }
1846
1847   public boolean isRowSelected(int row)
1848   {
1849     return getSelectionModel().isSelectedIndex(row);
1850   }
1851
1852   public boolean isCellSelected(int row, int column)
1853   {
1854     return isRowSelected(row) && isColumnSelected(column);
1855   }
1856   
1857   public void selectAll()
1858   {
1859     setColumnSelectionInterval(0, getColumnCount() - 1);
1860     setRowSelectionInterval(0, getRowCount() - 1);
1861   }
1862
1863   public Object getValueAt(int row, int column)
1864   {
1865     return dataModel.getValueAt(row, convertColumnIndexToModel(column));
1866   }
1867
1868   public void setValueAt(Object value, int row, int column)
1869   {
1870     dataModel.setValueAt(value, row, convertColumnIndexToModel(column));
1871   }
1872
1873   public TableColumn getColumn(Object identifier)
1874   {
1875     return columnModel.getColumn(columnModel.getColumnIndex(identifier));
1876   }
1877 }