KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > nqadmin > swingSet > SSDataGrid


1 /* $Id: SSDataGrid.java,v 1.33 2005/03/09 21:59:41 prasanth Exp $
2  *
3  * Tab Spacing = 4
4  *
5  * Copyright (c) 2003-2005, The Pangburn Company and Prasanth R. Pasala
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer. Redistributions in binary
13  * form must reproduce the above copyright notice, this list of conditions and
14  * the following disclaimer in the documentation and/or other materials
15  * provided with the distribution. The names of its contributors may not be
16  * used to endorse or promote products derived from this software without
17  * specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */

32
33 package com.nqadmin.swingSet;
34
35 import java.awt.*;
36 import java.awt.event.*;
37 import javax.swing.*;
38 import javax.swing.event.*;
39 import javax.swing.table.*;
40 import javax.swing.border.LineBorder JavaDoc;
41 import java.sql.SQLException JavaDoc;
42 import java.sql.Date JavaDoc;
43 import java.util.GregorianCalendar JavaDoc;
44 import java.util.Calendar JavaDoc;
45 import java.util.StringTokenizer JavaDoc;
46 import java.util.EventObject JavaDoc;
47 import java.util.Vector JavaDoc;
48 import com.nqadmin.swingSet.datasources.SSRowSet;
49
50 /**
51  * SSDataGrid.java
52  *<p>
53  * SwingSet - Open Toolkit For Making Swing Controls Database-Aware
54  *<p><pre>
55  * SSDataGrid provides a way to display information from a database in a table
56  * format (aka "spreadsheet" or "datasheet" view). The SSDataGrid takes a SSRowSet
57  * as a source of data. It also provides different cell renderers including a
58  * comboboxes renderer and a date renderer.
59  *
60  * SSDataGrid internally uses the SSTableModel to display the information in a
61  * table format. SSDataGrid also provides an easy means for displaying headers.
62  * Columns can be hidden or made uneditable. In addition, it provides much finer
63  * control over which cells can be edited and which cells can't be edited. It
64  * uses the SSCellEditing interface for achieving this. The implementation of
65  * this interface also provides a way to specify what kind of information is valid
66  * for each cell.
67  *
68  * SSDataGrid uses the isCellEditable() method in SSCellEditing to determine if a
69  * cell is editable or not. The cellUpdateRequested() method of SSCellEditing is
70  * used to notify a user program when an update is requested. While doing so it
71  * provides the present value in the cell and also the new value. Based on this
72  * information the new value can be rejected or accepted by the program.
73  *
74  * SSDataGrid also provides an "extra" row to facilitate the addition of rows to
75  * the table. Default values for various columns can be set programmatically. A
76  * programmer can also specify which column is the primary key column for the
77  * underlying SSRowSet and supply a primary key for that column when a new row is
78  * being added.
79  *
80  * While using the headers always set them before you set the SSRowSet.
81  * Otherwise the headers will not appear.
82  *
83  * Also if you are using column names rather than column numbers for different function
84  * you have to call them only after setting the SSRowSet. Because SSDataGrid uses the
85  * SSRowSet to convert the column names to column numbers. If you specify the column
86  * numbers you can do before or after setting the SSRowSet, it does not matter.
87  *
88  * You can simply remember this order
89  * 1.Set the headers
90  * 2.Set the SSRowSet
91  * 3.Any other function calls.
92  *
93  * Simple Example:
94  *
95  * // SET THE HEADER BEFORE SETTING THE SSROWSET
96  * dataGrid.setHeaders(new String[]{"Part Name", "Color Code", " Weight", "City"});
97  * dataGrid.setSSRowSet(ssRowSet);
98  * // HIDE THE PART ID COLUMN
99  * // THIS SETS THE WIDTH OF THE COLUMN TO 0
100  * //dataGrid.setHiddenColumns(new String[]{"part_id"});
101  * dataGrid.setHiddenColumns(new String[]{"part_id"});
102  *
103  * dataGrid.setMessageWindow(this);
104  * dataGrid.setUneditableColumns(new String[]{"part_id"});
105  *
106  * dataGrid.setComboRenderer("color_code",new String[]{"Red","Green","Blue"},
107  * new Integer[]{new Integer(0),new Integer(1),new Integer(2)});
108  * dataGrid.setDefaultValues(new int[]{1,2,3},new Object[]{new Integer(0),
109  * new Integer(20),new String("New Orleans")});
110  *
111  * dataGrid.setPrimaryColumn("part_id");
112  * dataGrid.setSSDataValue(new SSDataValue(){
113  * public Object getPrimaryColumnValue(){
114  * // YOUR PRIMARY KEY VALUE GENERATION GOES HERE
115  * // IF ITS SOME THING USER ENTERS THEN NO PROBLEM
116  * // IF ITS AN AUTO INCREMENT FIELD THEN IT DEPENDS ON
117  * // THE DATABASE DRIVER YOU ARE USING.
118  * // IF THE UPDATEROW CAN RETRIEVE THE VALUES FOR THE ROW
119  * // WITH OUT KNOWING THE PRIMARY KEY VALUE ITS FINE
120  * // BUT POSTGRES CAN'T UPDATE ROW WITH OUT THE PRIMARY
121  * // COLUMN.
122  *
123  * // YOUR PRIMARY KEY VALUE GENERATION GOES HERE.
124  * ........
125  * ........
126  * ........
127  * }
128  * });
129  *
130  * Also See Examples 5, 6, 7 in the samples.
131  *</pre><p>
132  * @author $Author: prasanth $
133  * @version $Revision: 1.33 $
134  */

135
136 public class SSDataGrid extends JTable {
137
138     /**
139      * Component where messages should be popped up.
140      */

141     protected Component messageWindow = null;
142
143     /**
144      * SSRowSet from which component will get/set values.
145      */

146     protected SSRowSet sSRowSet = null;
147
148     /**
149      * Number of columns in the SSRowSet.
150      */

151     protected int columnCount = -1;
152
153     /**
154      * Number of records retrieved from the SSRowSet.
155      */

156     protected int rowCount = -1;
157
158     /**
159      * Minimum width of the columns in the data grid.
160      */

161     protected int columnWidth = 100;
162
163     /**
164      * Table model to construct the JTable
165      */

166     protected SSTableModel tableModel = new SSTableModel();
167
168     /**
169      * Scrollpane used to scroll datagrid.
170      */

171     protected JScrollPane scrollPane = null; //new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
172

173     /**
174      * Array used to store the column numbers that have to be hidden.
175      */

176     protected int[] hiddenColumns = null;
177
178     /**
179      * Array used to store the column names that have to hidden.
180      */

181     protected String JavaDoc[] hiddenColumnNames = null;
182
183     /**
184      * Variable to indicate if execute() should be called on the SSRowSet.
185      */

186     protected boolean callExecute = true;
187
188     /**
189      * Variable to indicate if the data grid will display an additional row for
190      * inserting new rows.
191      */

192     protected boolean insertion = true;
193
194     /**
195      * Constructs a data grid with the data source set to the given SSRowSet.
196      *
197      * @param _sSRowSet SSRowSet from which values have to be retrieved.
198      */

199     public SSDataGrid(SSRowSet _sSRowSet) {
200         sSRowSet = _sSRowSet;
201         init();
202         bind();
203     }
204
205     /**
206      * Constructs an empty data grid.
207      */

208     public SSDataGrid() {
209         init();
210     }
211
212     /**
213      * Sets the minimum column width for the data grid.
214      *
215      * @param _columnWidth minimum column width of the each column
216      */

217     public void setColumnWidth(int _columnWidth) {
218         int oldValue = columnWidth;
219         columnWidth = _columnWidth;
220         firePropertyChange("columnWidth", oldValue, columnWidth);
221     }
222
223     /**
224      * Returns the minimum column width for the data grid.
225      *
226      * @return minimum column width of the each column
227      */

228     public int getColumnWidth() {
229         return columnWidth;
230     }
231
232     /**
233      * Sets the component on which error messages will be popped up.
234      * The error dialog will use this component as its parent component.
235      *
236      * @param _messageWindow the component that should be used when displaying error messages
237      */

238     public void setMessageWindow(Component _messageWindow) {
239         Component oldValue = messageWindow;
240         messageWindow = _messageWindow;
241         firePropertyChange("messageWindow", oldValue, messageWindow);
242         tableModel.setMessageWindow(messageWindow);
243     }
244
245     /**
246      * Returns the component on which error messages will be popped up.
247      * The error dialog will use this component as its parent component.
248      *
249      * @return the component that should be used when displaying error messages
250      */

251     public Component getMessageWindow() {
252         return messageWindow;
253     }
254
255     /**
256      * Sets the callExecute property.
257      * If set to true causes the navigator to skip the execute function call on the specified SSRowSet.
258      * (See FAQ for further details)
259      *
260      * @param _callExecute true if execute function call has to be skipped else false
261      */

262     public void setCallExecute(boolean _callExecute) {
263         boolean oldValue = callExecute;
264         callExecute = _callExecute;
265         firePropertyChange("callExecute", oldValue, callExecute);
266     }
267
268     /**
269      * Returns the callExecute property.
270      * If set to true causes the navigator to skip the execute function call on the specified SSRowSet.
271      * (See FAQ for further details).
272      *
273      * @return true if execute function call has to be skipped else false
274      */

275     public boolean getCallExecute() {
276         return callExecute;
277     }
278
279     /**
280      * Sets the allowInsertion property of the table.
281      * If set to true an additional row for inserting new rows will be displayed
282      *
283      * @param _insertion true if new rows can be added else false.
284      */

285     public void setInsertion(boolean _insertion) {
286         boolean oldValue = insertion;
287         insertion = _insertion;
288         firePropertyChange("insertion", oldValue, insertion);
289         tableModel.setInsertion(_insertion);
290         updateUI();
291     }
292
293     /**
294      * Returns the allowInsertion property of the table.
295      * If set to true an additional row for inserting new rows will be displayed
296      *
297      * @return true if new rows can be added else false.
298      */

299     public boolean getInsertion() {
300         return insertion;
301     }
302
303     /**
304      * Returns the list of selected columns.
305      * This function gets the list of selected columns from parent class
306      * and removes any columns which are present in hidden columns.
307      *
308      * Currently not a bean property since there is no associated variable
309      *
310      * @return array of selected columns
311      */

312     // THIS IS A STRANGE BEHAVIOUR. FOR SOME REASON SOMETIMES THE
313
// LIST OF SELECTED COLUMNS INCLUDED HIDDEN COLUMNS THIS CAUSES
314
// A PROBLEM WITH COPY AND PASTE OPERATIONS. SO MAKE SURE THAT THIS
315
// LIST DOES NOT CONTAIN HIDDEN COLUMNS
316
public int[] getSelectedColumns() {
317         // IF THERE ARE NO HIDDEN COLUMNS THEN RETURN THE SAME LIST
318
if (hiddenColumns == null) {
319                 return super.getSelectedColumns();
320             }
321
322         // GET THE LIST OF SELECTED COLUMNS FROM SUPER CLASS.
323
int[] selectedColumns = super.getSelectedColumns();
324             Vector JavaDoc filteredColumns = new Vector JavaDoc();
325
326         // FILTER OUT THE HIDDEN COLUMNS FROM THIS LIST.
327
for (int i=0; i<selectedColumns.length; i++) {
328                 boolean found = false;
329                 // CHECK THIS COLUMN NUMBER WITH HIDDEN COLUMNS
330
for (int j=0; j<hiddenColumns.length; j++) {
331                     // IF ITS THERES INDICATE THE SAME AND BREAK OUT.
332
if (selectedColumns[i] == hiddenColumns[j]) {
333                             found = true;
334                             break;
335                         }
336                     }
337                 // IF THIS COLUMN IS NOT IN HIDDEN COLUMNS ADD IT TO FILTERED LIST
338
if (!found) {
339                         filteredColumns.add(new Integer JavaDoc(selectedColumns[i]));
340                     }
341             }
342
343         // CREATE AN INT ARRAY CONTAINING THE FILETED LIST OF COLUMNS
344
int[] result = new int[filteredColumns.size()];
345             for (int i=0; i<filteredColumns.size(); i++) {
346                 result[i] = ((Integer JavaDoc)filteredColumns.elementAt(i)).intValue();
347             }
348
349             return result;
350     }
351
352     /**
353      * Returns number of selected columns.
354      *
355      * Currently not a bean property since there is no associated variable.
356      *
357      * @return number of selected columns
358      */

359     public int getSelectedColumnCount() {
360         int[] selectedColumns = this.getSelectedColumns();
361         if (selectedColumns == null) {
362             return 0;
363         }
364
365         return selectedColumns.length;
366     }
367
368     /**
369      * Binds the SSRowSet to the grid.
370      * Data is taken from the new SSRowSet.
371      *
372      * @param _sSRowSet the SSRowSet which acts as the data source.
373      */

374      public void setSSRowSet(SSRowSet _sSRowSet) {
375         SSRowSet oldValue = sSRowSet;
376         sSRowSet = _sSRowSet;
377         firePropertyChange("sSRowSet", oldValue, sSRowSet);
378         bind();
379      } // end public void setSSRowSet(SSRowSet _sSRowSet) {
380

381     /**
382      * Returns the SSRowSet being used to get the values.
383      *
384      * @return returns the SSRowSet being used.
385      */

386     public SSRowSet getSSRowSet() {
387         return sSRowSet;
388     }
389
390     /**
391      * Returns scroll pane with the JTable embedded in it.
392      *
393      * Currently not a bean property since there is no associated variable.
394      *
395      * @return scroll pane with embedded JTable
396      */

397      public Component getComponent(){
398         return scrollPane;
399      }
400
401     /**
402      * Sets the default values for different columns.
403      * When a new row is added these default values will be added to the columns.
404      * Please make sure that the object specified for each column is of the same type
405      * as that of the column in the database.
406      * Use the getColumnClass function in JTable to determine the exact data type.
407      *
408      * Currently not a bean property since there is no associated variable.
409      *
410      * @param _columnNumbers array containing the column numbers for which the
411      * defaults apply.
412      * @param _values the values for the column numbers specified in _columnNumbers.
413      */

414      public void setDefaultValues(int[] _columnNumbers, Object JavaDoc[] _values) {
415          //if (tableModel == null) {
416
// tableModel = new SSTableModel();
417
//}
418
tableModel.setDefaultValues(_columnNumbers,_values);
419      }
420
421     /**
422      * Sets the default values for different columns.
423      * When a new row is added these default values will be added to the columns.
424      * Please make sure that the object specified for each column is of the same type
425      * as that of the column in the database.
426      * Use the getColumnClass function in JTable to determine the exact data type.
427      *
428      * Currently not a bean property since there is no associated variable.
429      *
430      * @param _columnNames array containing the column names for which the
431      * defaults apply.
432      * @param _values the values for the column names specified in _columnNames.
433      *
434      * @throws SQLException is the specified column name is not present in the SSRowSet
435      */

436      public void setDefaultValues(String JavaDoc[] _columnNames, Object JavaDoc[] _values) throws SQLException JavaDoc {
437
438         int[] columnNumbers = null;
439
440         //if (tableModel == null) {
441
// tableModel = new SSTableModel();
442
//}
443

444         if ( _columnNames != null) {
445             columnNumbers = new int[_columnNames.length];
446
447             for (int i=0; i< _columnNames.length;i++) {
448                 columnNumbers[i] = sSRowSet.getColumnIndex(_columnNames[i]) -1 ;
449             }
450         }
451
452         tableModel.setDefaultValues(columnNumbers, _values);
453      }
454
455     /**
456      * Returns the default value being used for the specified column.
457      * Returns null if a default is not in use.
458      *
459      * Currently not a bean property since there is no associated variable.
460      *
461      * @param _columnNumber the column number for which default value is to be returned.
462      *
463      * @return returns an object containing the default value for the requested column.
464      */

465      public Object JavaDoc getDefaultValue(int _columnNumber) {
466         return tableModel.getDefaultValue(_columnNumber);
467      }
468
469     /**
470      * Returns the default value being used for the specified column.
471      * Returns null if a default is not in use.
472      *
473      * Currently not a bean property since there is no associated variable.
474      *
475      * @param _columnName the column name for which default value is to be returned.
476      *
477      * @return returns an object containing the default value for the requested column.
478      *
479      * @throws SQLException is the specified column name is not present in the SSRowSet
480      */

481      public Object JavaDoc getDefaultValue(String JavaDoc _columnName) throws SQLException JavaDoc {
482         int columnNumber = sSRowSet.getColumnIndex(_columnName);
483         return tableModel.getDefaultValue(columnNumber -1);
484      }
485
486     /**
487      * Sets the column number which is the primary column for the table.
488      * This is required if new rows have to be added to the JTable.
489      * For this to properly work the SSDataValue object should also be provided
490      * SSDataValue is used to get the value for the primary column.
491      *
492      * Currently not a bean property since there is no associated variable.
493      *
494      * @param _columnNumber the column which is the primary column.
495      */

496     public void setPrimaryColumn(int _columnNumber) {
497         tableModel.setPrimaryColumn(_columnNumber);
498     }
499
500     /**
501      * Sets the column number which is the primary column for the table.
502      * This is required if new rows have to be added to the JTable.
503      * For this to properly work the SSDataValue object should also be provided
504      * SSDataValue is used to get the value for the primary column.
505      *
506      * Currently not a bean property since there is no associated variable.
507      *
508      * @param _columnName the column which is the primary column.
509      */

510     public void setPrimaryColumn(String JavaDoc _columnName) throws SQLException JavaDoc {
511         int columnNumber = sSRowSet.getColumnIndex(_columnName) -1;
512         tableModel.setPrimaryColumn(columnNumber);
513     }
514
515     /**
516      * Sets the SSDataValue interface implemention. This interface specifies
517      * function to retrieve primary column values for a new row to be added.
518      *
519      * Currently not a bean property since there is no associated variable.
520      *
521      * @param _dataValue implementation of SSDataValue
522      */

523     public void setSSDataValue(SSDataValue _dataValue) {
524         tableModel.setSSDataValue(_dataValue);
525     }
526
527     /**
528      * Sets a date renderer for the specified column.
529      * The date will be displayed in mm/dd/yyyy format. If a date renderer
530      * is not requested then the date will be displayed in a standard format(yyyy-mm-dd).
531      *
532      * Currently not a bean property since there is no associated variable.
533      *
534      * @param _column column number for which a date renderer is needed.
535      */

536     public void setDateRenderer(int _column) {
537         TableColumnModel columnModel = getColumnModel();
538         TableColumn tableColumn = columnModel.getColumn(_column);
539         tableColumn.setCellRenderer(new DateRenderer());
540         tableColumn.setCellEditor(new DateEditor());
541     }
542
543     /**
544      * Sets a date renderer for the specified column.
545      * The date will be displayed in mm/dd/yyyy format. If a date renderer
546      * is not requested then the date will be displayed in a standard format(yyyy-mm-dd).
547      *
548      * Currently not a bean property since there is no associated variable.
549      *
550      * @param _column column name for which a date renderer is needed.
551      */

552     public void setDateRenderer(String JavaDoc _column) throws SQLException JavaDoc {
553         int column = sSRowSet.getColumnIndex(_column) -1;
554         TableColumnModel columnModel = getColumnModel();
555         TableColumn tableColumn = columnModel.getColumn(column);
556         tableColumn.setCellRenderer(new DateRenderer());
557         tableColumn.setCellEditor(new DateEditor());
558     }
559
560     /**
561      * Sets a combo box renderer for the specified column.
562      * This is use full to limit the values that go with a column or if an underlying code
563      * is do be displayed in a more meaningfull manner.
564      *
565      * Currently not a bean property since there is no associated variable.
566      *
567      * @param _column column number for which combo renderer is to be provided.
568      * @param _displayItems the actual Objects to be displayed in the combo box.
569      * @param _underlyingValues the values that have to be written to the database when an
570      * item in the combo box is selected.
571      */

572     public void setComboRenderer(int _column, Object JavaDoc[] _displayItems, Object JavaDoc[] _underlyingValues) {
573         setComboRenderer(_column, _displayItems, _underlyingValues, 250);
574     }
575
576     /**
577      * Sets a combo box renderer for the specified column.
578      * This is use full to limit the values that go with a column or if an underlying code
579      * is do be displayed in a more meaningfull manner.
580      *
581      * Currently not a bean property since there is no associated variable.
582      *
583      * @param _column column number for which combo renderer is to be provided.
584      * @param _displayItems the actual Objects to be displayed in the combo box.
585      * @param _underlyingValues the values that have to be written to the database when an
586      * item in the combo box is selected.
587      */

588     public void setComboRenderer(int _column, Object JavaDoc[] _displayItems, Object JavaDoc[] _underlyingValues, int _columnWidth) {
589         setRowHeight(20);
590         TableColumnModel columnModel = getColumnModel();
591         TableColumn tableColumn = columnModel.getColumn(_column);
592         tableColumn.setCellRenderer(new ComboRenderer(_displayItems, _underlyingValues));
593         tableColumn.setCellEditor(new ComboEditor(_displayItems, _underlyingValues));
594         tableColumn.setMinWidth(_columnWidth);
595     }
596
597     /**
598      * Sets a combo box renderer for the specified column.
599      * This is use full to limit the values that go with a column or if an underlying code
600      * is do be displayed in a more meaningfull manner.
601      *
602      * Currently not a bean property since there is no associated variable.
603      *
604      * @param _column column name for which combo renderer is to be provided.
605      * @param _displayItems the actual Objects to be displayed in the combo box.
606      * @param _underlyingValues the values that have to be written to the database when an
607      * item in the combo box is selected.
608      */

609     public void setComboRenderer(String JavaDoc _column, Object JavaDoc[] _displayItems, Object JavaDoc[] _underlyingValues) throws SQLException JavaDoc {
610         setComboRenderer(_column, _displayItems, _underlyingValues, 250);
611     }
612
613     /**
614      * Sets a combo box renderer for the specified column.
615      * This is use full to limit the values that go with a column or if an underlying code
616      * is do be displayed in a more meaningfull manner.
617      *
618      * Currently not a bean property since there is no associated variable.
619      *
620      * @param _column column name for which combo renderer is to be provided.
621      * @param _displayItems the actual Objects to be displayed in the combo box.
622      * @param _underlyingValues the values that have to be written to the database when an
623      * item in the combo box is selected.
624      * @param _columnWidth required minimum width for this column
625      */

626     public void setComboRenderer(String JavaDoc _column, Object JavaDoc[] _displayItems, Object JavaDoc[] _underlyingValues, int _columnWidth) throws SQLException JavaDoc {
627         int column = sSRowSet.getColumnIndex(_column)-1;
628         setComboRenderer(column, _displayItems, _underlyingValues, _columnWidth);
629     }
630
631     /**
632      * Sets a check box renderer for the specified column.
633      *
634      * Currently not a bean property since there is no associated variable.
635      *
636      * @param _column - name ofthe column for which check box rendering is needed.
637      */

638     public void setCheckBoxRenderer(String JavaDoc _column) throws SQLException JavaDoc{
639         int column = sSRowSet.getColumnIndex(_column) - 1;
640         setCheckBoxRenderer(column);
641     }
642
643     /**
644      * Sets a check box renderer for the specified column.
645      *
646      * Currently not a bean property since there is no associated variable.
647      *
648      * @param _column - column number for which check box rendering is needed.
649      */

650     public void setCheckBoxRenderer(int _column) throws SQLException JavaDoc{
651         TableColumnModel columnModel = getColumnModel();
652         TableColumn tableColumn = columnModel.getColumn(_column);
653         tableColumn.setCellRenderer(new CheckBoxRenderer());
654         tableColumn.setCellEditor(new CheckBoxEditor());
655     }
656
657     /**
658      * Sets the header for the JTable.
659      * This function has to be called before setting the SSRowSet for SSDataGrid.
660      *
661      * Currently not a bean property since there is no associated variable.
662      *
663      * @param _headers array of string objects representing the header of each column.
664      */

665     public void setHeaders(String JavaDoc[] _headers) {
666         tableModel.setHeaders(_headers);
667     }
668
669     /**
670      * Sets the uneditable columns.
671      * The columns specified as uneditable will not be available for user to edit.
672      * This overrides the isCellEditable function in SSCellEditing.
673      *
674      * Currently not a bean property since there is no associated variable.
675      *
676      * @param _columnNumbers array specifying the column numbers which should be
677      * uneditable.
678      */

679     public void setUneditableColumns(int[] _columnNumbers) {
680         tableModel.setUneditableColumns(_columnNumbers);
681     }
682
683     /**
684      * Sets the uneditable columns.
685      * The columns specified as uneditable will not be available for user to edit.
686      * This overrides the isCellEditable function in SSCellEditing.
687      *
688      * Currently not a bean property since there is no associated variable.
689      *
690      * @param _columnNames array specifying the column names which should be
691      * uneditable.
692      */

693     public void setUneditableColumns(String JavaDoc[] _columnNames) throws SQLException JavaDoc {
694         int[] columnNumbers = null;
695         if (_columnNames != null) {
696             columnNumbers = new int[_columnNames.length];
697
698             for (int i=0;i<_columnNames.length;i++) {
699                 columnNumbers[i] = sSRowSet.getColumnIndex(_columnNames[i]) -1;
700             }
701         }
702
703         tableModel.setUneditableColumns(columnNumbers);
704     }
705
706     /**
707      * Sets the column numbers that should be hidden.
708      * The SSDataGrid sets the column width of these columns to 0.
709      * The columns are set to zero width rather than removing the column from the table.
710      * Thus preserving the column numbering.If a column is removed then the column numbers
711      * for columns after the removed column will change.
712      * Even if the column is specified as hidden user will be seeing a tiny strip.
713      * Make sure that you specify the hidden column numbers in the uneditable column
714      * list.
715      *
716      * Currently not a bean property since there is no associated variable.
717      *
718      * @param _columnNumbers array specifying the column numbers which should be
719      * hidden
720      */

721     public void setHiddenColumns(int[] _columnNumbers) {
722         hiddenColumns = _columnNumbers;
723         tableModel.setHiddenColumns(_columnNumbers);
724         hideColumns();
725     }
726
727     /**
728      * Sets the column numbers that should be hidden.
729      * The SSDataGrid sets the column width of these columns to 0.
730      * The columns are set to zero width rather than removing the column from the table.
731      * Thus preserving the column numbering.If a column is removed then the column numbers
732      * for columns after the removed column will change.
733      * Even if the column is specified as hidden user will be seeing a tiny strip.
734      * Make sure that you specify the hidden column numbers in the uneditable column
735      * list.
736      *
737      * Currently not a bean property since there is no associated variable.
738      *
739      * @param _columnNames array specifying the column names which should be
740      * hidden
741      */

742     public void setHiddenColumns(String JavaDoc[] _columnNames) throws SQLException JavaDoc {
743         hiddenColumns = null;
744         tableModel.setHiddenColumns(hiddenColumns);
745         if (_columnNames != null) {
746             hiddenColumns = new int[_columnNames.length];
747             for(int i=0; i<_columnNames.length; i++) {
748                 hiddenColumns[i] = sSRowSet.getColumnIndex(_columnNames[i]) -1;
749             }
750         }
751         hideColumns();
752     }
753
754     /**
755      * If the user has to decide on which cell has to be editable and which is not
756      * then SSCellEditable interface has to be implemented and set it for the SSTableModel.
757      *
758      * Currently not a bean property since there is no associated variable.
759      *
760      * @param _cellEditing implementation of SSCellEditable interface.
761      */

762     public void setSSCellEditing(SSCellEditing _cellEditing) {
763         tableModel.setSSCellEditing( _cellEditing );
764     }
765     
766     /**
767      * This is the default editor for Numeric, String & Object column types.
768      */

769     class DefaultEditor extends DefaultCellEditor{
770         /**
771          * Value of the editor.
772          */

773         Object JavaDoc value;
774         
775         /**
776          * Constructor to instanciate an object of column type from a string.
777          */

778         java.lang.reflect.Constructor JavaDoc constructor;
779         
780               
781         /**
782          * Constructs Default Editor.
783          */

784         public DefaultEditor() {
785             super(new SSTextField());
786             MyListener listener = new MyListener();
787             getComponent().addFocusListener(listener);
788             getComponent().addKeyListener(listener);
789         }
790         
791         /**
792          * Implementation of KeyListener & FocusListener for the editor component.
793          */

794         private class MyListener implements KeyListener, FocusListener{
795             
796             int keyPressed = 0;
797             boolean hasFocus = false;
798             
799         // ASSUMPTION HERE IS THAT THE EDITOR WILL NOT GET THE KEY PRESSED EVENT
800
// FOR THE FIRST KEY (WHICH TRIGGERS THE EDITOR, EVENT IS CONSUMED BY JTABLE)
801
/**
802              * Increment the key pressed variable when ever there is a key pressed event.
803              *only exception is tab key.
804              */

805             public void keyPressed(KeyEvent ke){
806                 if(ke.getKeyCode() != KeyEvent.VK_TAB)
807                     keyPressed++;
808             }
809             
810             /**
811              * Based on if this is first key release event the contents will be cleared
812              */

813             public void keyReleased(KeyEvent ke){
814                 JComponent editor = (JComponent)DefaultEditor.this.getComponent();
815                 if(editor instanceof JTextField){
816                     if(keyPressed == 0 && Character.isLetterOrDigit(ke.getKeyChar())){
817                         ((JTextField)editor).setText(String.valueOf(ke.getKeyChar()));
818                     }
819                 }
820                 keyPressed--;
821                 if(keyPressed < 0)
822                     keyPressed = 0;
823                 
824             }
825             
826             public void keyTyped(KeyEvent ke){
827             }
828             
829             /**
830              *
831              */

832             public void focusGained(FocusEvent fe){
833                 ((SSTextField)getComponent()).selectAll();
834                 hasFocus = true;
835             }
836             
837             /**
838              * sets the keyPressed variable to zero.
839              */

840             public void focusLost(FocusEvent fe){
841             // SET THE KEYPRESSED TO ZERO AS THE EDITOR HAS LOST THE FOCUS.
842
hasFocus = false;
843                 keyPressed = 0;
844             }
845         }
846
847         public boolean stopCellEditing() {
848             String JavaDoc s = (String JavaDoc)super.getCellEditorValue();
849             
850             if (s.trim().equals("")){
851                 if (constructor.getDeclaringClass() == String JavaDoc.class) {
852                     value = s;
853                 }
854                 super.stopCellEditing();
855             }
856     
857             try {
858                 value = constructor.newInstance(new Object JavaDoc[]{s});
859             }catch (Exception JavaDoc e) {
860             // DRAW A RED BORDER IF THE VALUE OBJECT CAN'T BE CREATED.
861
// PROBABLY THE DATA ENTERED IS NOT RIGHT (STRING IN NUMBER FIELD OR VICE-VERSA)
862
((JComponent)getComponent()).setBorder(new LineBorder JavaDoc(Color.red));
863                 return false;
864             }
865             
866             return super.stopCellEditing();
867         }
868     
869         public Component getTableCellEditorComponent(JTable table, Object JavaDoc value,
870                              boolean isSelected, int row, int column) {
871         // SET INITIAL VALUE TO NULL.
872
this.value = null;
873             
874             ((JComponent)getComponent()).setBorder(new LineBorder JavaDoc(Color.black));
875             
876         // GET A CONSTRUCTOR FOR AN OBJECT OF THE CURRENT COLUMN TYPE.
877
// THIS IS NEEDED FOR RETURNING THE VALUE IN COLUMN CLASS OBJECT
878
try {
879                 Class JavaDoc type = table.getColumnClass(column);
880                 if (type == Object JavaDoc.class) {
881                     type = String JavaDoc.class;
882                 }
883                 constructor = type.getConstructor(new Class JavaDoc[]{String JavaDoc.class});
884             }catch (Exception JavaDoc e) {
885                 return null;
886             }
887             
888             return super.getTableCellEditorComponent(table, value, isSelected, row, column);
889         }
890     
891         /**
892          * Returns the cell value.
893          */

894         public Object JavaDoc getCellEditorValue() {
895             return value;
896         }
897     
898     }
899
900     
901     /**
902      * Initialization code.
903      */

904     protected void init() {
905         
906         // FORCE JTABLE TO SURRENDER TO THE EDITOR WHEN KEYSTROKES CAUSE THE EDITOR TO BE ACTIVATED
907
setSurrendersFocusOnKeystroke(true);
908             setDefaultEditor(Number JavaDoc.class, new DefaultEditor());
909             setDefaultEditor(String JavaDoc.class, new DefaultEditor());
910             setDefaultEditor(Object JavaDoc.class, new DefaultEditor());
911             
912         // ADD KEY LISTENER TO JTABLE.
913
// THIS IS USED FOR DELETING THE ROWS
914
// ALLOWS MULTIPLE ROW DELETION.
915
// KEY SEQUENCE FOR DELETING ROWS IS CTRL-X.
916
this.addKeyListener(new KeyAdapter() {
917                 private boolean controlPressed = false;
918
919             // IF THE KEY PRESSED IS CONTROL STORE THAT INFO.
920
public void keyPressed(KeyEvent ke) {
921                     if (ke.getKeyCode() == KeyEvent.VK_CONTROL) {
922                         controlPressed = true;
923                     }
924                 }
925
926             // HANDLE KEY RELEASES
927
public void keyReleased(KeyEvent ke) {
928                 // IF CONTROL KEY IS RELEASED SET THAT CONTROL IS NOT PRESSED.
929
if (ke.getKeyCode() == KeyEvent.VK_CONTROL) {
930                         controlPressed = false;
931                     }
932                 // IF X IS PRESSED WHILE THE CONTROL KEY IS STILL PRESSED
933
// DELETE THE SELECTED ROWS.
934
if (ke.getKeyCode() == KeyEvent.VK_X) {
935                         if (! controlPressed) {
936