KickJava   Java API By Example, From Geeks To Geeks.

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


1 /* $Id: SSTableKeyAdapter.java,v 1.6 2005/02/09 21:22:35 yoda2 Exp $
2  *
3  * Tab Spacing = 4
4  *
5  * Copyright (c) 2004-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.Toolkit JavaDoc;
36 import java.awt.event.KeyAdapter JavaDoc;
37 import java.awt.event.KeyEvent JavaDoc;
38 import java.awt.datatransfer.Clipboard JavaDoc;
39 import java.awt.datatransfer.StringSelection JavaDoc;
40 import java.awt.datatransfer.DataFlavor JavaDoc;
41 import java.awt.datatransfer.Transferable JavaDoc;
42 import java.awt.datatransfer.UnsupportedFlavorException JavaDoc;
43 import java.util.StringTokenizer JavaDoc;
44 import javax.swing.JTable JavaDoc;
45 import javax.swing.JOptionPane JavaDoc;
46 import java.lang.reflect.Constructor JavaDoc;
47 import java.io.IOException JavaDoc;
48 import java.io.Serializable JavaDoc;
49
50 /**
51  * SSTableKeyAdapter.java
52  *<p>
53  * SwingSet - Open Toolkit For Making Swing Controls Database-Aware
54  *<p><pre>
55  * Key adapter for JTable & SSDataGrid that manages cut & paste functionality
56  * between a table and either another table or a spreadsheet.
57  *</pre><p>
58  * @author $Author: yoda2 $
59  * @version $Revision: 1.6 $
60  */

61 public class SSTableKeyAdapter extends KeyAdapter JavaDoc implements Serializable JavaDoc {
62
63     /**
64      * On state for copying or pasting.
65      */

66     protected int onMask = KeyEvent.CTRL_DOWN_MASK;
67
68     /**
69      * Off state for copying or pasting.
70      */

71     protected int offMask = KeyEvent.ALT_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK;
72
73     /**
74      * Indicates whether or not row insertions are allowed via cut/copy & paste.
75      */

76     protected boolean allowInsertion = false;
77
78     /**
79      * Indicates row used for insertion in SSDataGrid.
80      */

81     protected boolean forSSDataGrid = false;
82
83     /**
84      * Constructs a KeyAdapter for the JTable.
85      *
86      * @param _jTable JTable for which copy and paste support should be added.
87      */

88     public SSTableKeyAdapter(JTable JavaDoc _jTable) {
89         init(_jTable);
90     }
91
92     /**
93      * Sets allowInsertion indicator. Set true if new rows can be added to
94      * JTable via cut/copy & paste - otherwise false. False by default.
95      *
96      * @param _allowInsertion true if new rows can be added when pasting data
97      * from clipboard, else false.
98      */

99     public void setAllowInsertion(boolean _allowInsertion) {
100         allowInsertion = _allowInsertion;
101     }
102
103     /**
104      * Sets forSSDataGrid indicator. True if the key adapter is
105      * used for SSDataGrid -- otherwise false. False by default.
106      *
107      * @param _forSSDataGrid - true if this key adapter is used for SSDataGrid,
108      * else false.
109      */

110     public void setForSSDataGrid(boolean _forSSDataGrid) {
111         forSSDataGrid = _forSSDataGrid;
112     }
113
114     /**
115      * Adds the key listener for the specified JTable.
116      */

117     protected void init(JTable JavaDoc _jTable) {
118         _jTable.addKeyListener(this);
119     }
120
121     /**
122      * Invoked when a key is released.
123      */

124     public void keyReleased(KeyEvent JavaDoc ke) {
125         StringBuffer JavaDoc strBuf = new StringBuffer JavaDoc();
126
127         JTable JavaDoc jTable = (JTable JavaDoc)ke.getSource();
128 // System.out.println("Key Released on GRID");
129
// System.out.println("Key Released: " + ke.getKeyCode() + " " + ((ke.getModifiersEx() & (onMask | offMask)) == onMask));
130

131         if (((ke.getModifiersEx() & (onMask | offMask)) == onMask) && ke.getKeyCode() == KeyEvent.VK_C) {
132         // CHECK IF CONTROL-C IS PRESSED
133
// SHIFT OR ALT SHOULD NOT BE DOWN
134

135             // ALERT USER
136
// System.out.println("Going to handle copy");
137

138             // GET COLUMNS INVOLVED
139
int numRows = jTable.getSelectedRowCount();
140                 int numColumns = 0;
141                 if (jTable instanceof SSDataGrid) {
142                     numColumns = ((SSDataGrid)jTable).getSelectedColumnCount();
143                 } else {
144                     numColumns = jTable.getSelectedColumnCount();
145                 }
146
147             // CHECK IF THERE IS ATLEAST ONE SELECTED CELL.
148
// IF NOT NOTHING TO COPY JUST RETURN.
149
if (numRows < 1 || numColumns < 1) {
150                     return;
151                 }
152
153             // GET THE ROWS AND COLUMNS SELECTED.
154
int[] selectedRows = jTable.getSelectedRows();
155                 int[] selectedColumns = null;
156                 if (jTable instanceof SSDataGrid) {
157                     selectedColumns = ((SSDataGrid)jTable).getSelectedColumns();
158                 } else {
159                     selectedColumns = jTable.getSelectedColumns();
160                 }
161
162             // COPY THE DATA IN THE SELECTED ROWS AND COLUMNS
163
// APPEND A TAB AFTER EACH CELL AND A NEW LINE CHAR AT END OF EACH ROW.
164
for (int i=0; i<selectedRows.length; i++) {
165                     for (int j=0; j<selectedColumns.length; j++) {
166                         strBuf.append(jTable.getValueAt(selectedRows[i], selectedColumns[j]));
167                         if (j < (numColumns -1)) {
168                             strBuf.append("\t");
169                         }
170                     }
171                     strBuf.append("\n");
172                 }
173
174             // GET THE SYSTEM CLIPBOARD
175
Clipboard JavaDoc clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
176
177             // CREATE A TRANSFERABLE OBJECT
178
StringSelection JavaDoc stringSelection = new StringSelection JavaDoc(strBuf.toString());
179
180             // COPY THE DATA TO CLIP BOARD
181
clipboard.setContents(stringSelection,stringSelection);
182
183         } else if (((ke.getModifiersEx() & (onMask | offMask)) == onMask) && ke.getKeyCode() == KeyEvent.VK_V) {
184         // CHECK IF CONTROL-V IS PRESSED
185
// SHIFT OR ALT SHOULD NOT BE DOWN
186

187             // GET CLIPBOARD
188
Clipboard JavaDoc clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
189
190             // GET THE CONTENTS OF THE CLIPBOARD
191
Transferable JavaDoc transferable = clipboard.getContents(this);
192
193             // IF THE CONTENT TYPE SUPPORTS STRING TYPE GET THE DATA.
194
if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
195                 // GET DATA FROM CLIPBOARD
196
String JavaDoc strData = "";
197                     try {
198                         strData = (String JavaDoc)transferable.getTransferData(DataFlavor.stringFlavor);
199                         System.out.println(strData);
200                     } catch(UnsupportedFlavorException JavaDoc ufe) {
201                         ufe.printStackTrace();
202                         return;
203                     } catch(IOException JavaDoc ioe) {
204                         ioe.printStackTrace();
205                         return;
206                     }
207
208                 // IF USER HAS NOT SELECTED ANY CELL THEN DO NOT COPY.
209
if (jTable.getSelectedRowCount() < 1 || jTable.getSelectedColumnCount() < 1) {
210                         return;
211                     }
212
213                 // GET THE SELECTED ROWS AND COLUMNS
214
int[] selectedRows = jTable.getSelectedRows();
215                     int[] selectedColumns = jTable.getSelectedColumns();
216
217                 // CREATE A STRING TOKENIZER TO BREAK THE DATA INTO ROWS.
218
StringTokenizer JavaDoc rowTokens = new StringTokenizer JavaDoc(strData, "\n", false);
219
220                 // INITIALIZE THE NUMBER OF ROWS AND COLUMNS
221
int numRows = 0;
222                     int numColumns = 0;
223
224                     StringTokenizer JavaDoc columnTokens;
225
226                 // SEE IF THE DATA HAS ATLEAST ONE ROW
227
// IF IT DOES GET THE NUMBER OF COLUMNS PRESENT.
228
if (rowTokens.hasMoreTokens()) {
229                         numRows++;
230                         columnTokens = new StringTokenizer JavaDoc(rowTokens.nextToken(), "\t", false);
231                         // WHILE THERE ARE TOKENS INCREMENT THE COLUMN COUNT
232
for (; columnTokens.hasMoreTokens(); numColumns++) {
233                                 columnTokens.nextToken();
234                             }
235                     }
236
237                 // GET THE NUMBER OF ROWS PRESENT
238
for(; rowTokens.hasMoreTokens(); numRows++){
239                         rowTokens.nextToken();
240                     }
241
242                 // GET THE NUMBER OF COLUMNS AND ROWS IN THE JTABLE.
243
int rowCount = jTable.getRowCount();
244                     int columnCount = jTable.getColumnCount();
245
246                     if (forSSDataGrid || jTable instanceof SSDataGrid) {
247                         rowCount--;
248                     }
249
250                 // IF THE NUMBER OF COLUMNS NEEDED TO COPY FROM CLIPBOARD
251
// IS MORE THAN THAT IN JTABLE CANCEL COPY
252
// YOU HAVE TO CHECK THIS FROM THE STARTING SELECTED CELL
253
// NO NEED TO ADD ONE FOR SELECTEDCOLUMNS[0] AS THE PASTING STARTS FROM THAT ITSELF
254
if (columnCount < (numColumns + selectedColumns[0])) {
255                         JOptionPane.showMessageDialog(jTable, "There are not enough columns in the table to copy into.\n");
256                         return;
257                     }
258
259                     int numRowsToCopy = numRows;
260
261                 // SEE IF SUFFICENT ROWS ARE PRESENT.
262
if (rowCount < (numRows + selectedRows[0])) {
263                         JOptionPane.showMessageDialog(jTable, "There are not enough rows in the table to copy into.\n");
264                         if (allowInsertion) {
265                             int option = JOptionPane.showConfirmDialog(jTable, "Do you want to insert new rows?", "Add Rows", JOptionPane.YES_NO_OPTION);
266                             if (option == JOptionPane.YES_OPTION) {
267                             // SET THE NUMBER OF ROWS TO COPY EQUAL TO
268
// NUMBER OF ROWS IN DATA.
269
numRowsToCopy = numRows;
270                             } else if (JOptionPane.showConfirmDialog(jTable, "Do you want to copy data into just the rows present?", "Limited Copy", JOptionPane.YES_NO_OPTION)
271                                 == JOptionPane.YES_OPTION) {
272                             // GET THE NUMBER OF ROWS FROM SELECTED ROW TO LAST ROW
273
// NO NEED TO ADD A ONE
274
numRowsToCopy = rowCount - selectedRows[0];
275                             }
276                         } else if (JOptionPane.showConfirmDialog(jTable, "Do you want to copy data into just the rows present?", "Limited Copy", JOptionPane.YES_NO_OPTION)
277                             == JOptionPane.YES_OPTION) {
278                         // GET THE NUMBER OF ROWS FROM SELECTED ROW TO LAST ROW
279
// NO NEED TO ADD A ONE
280
numRowsToCopy = rowCount - selectedRows[0];
281                         }
282
283                     }
284
285                 // COPY THE DATA FROM CLIP BOARD TO JTABLE
286
try {
287                     // TOKENIZE DATA IN TO ROWS
288
rowTokens = new StringTokenizer JavaDoc(strData, "\n", false);
289
290                     // WHILE THERE ARE ROWS IN THE CLIP BOARD DATA AND NUMBER OF ROWS
291
// COPIED IS LESS THEN WE SHOULD COPY DATA TO JTABLE.
292
for (int i=0;rowTokens.hasMoreTokens() && i<numRowsToCopy; i++) {
293                         // TOKENIZE THE ROW INFORMATION IN TO COLUMNS
294
columnTokens = new StringTokenizer JavaDoc(rowTokens.nextToken(), "\t", false);
295                         // PASTE THE DATA IN TO JTABLE ROW.
296
for (int j=0; columnTokens.hasMoreTokens(); j++) {
297                             // GET THE VALUE FOR THIS CELL IN THE FORM OF THIS COLUMN CLASS OBJECT
298
Object JavaDoc newValue = getObjectToSet(jTable, selectedColumns[0]+j, columnTokens.nextToken());
299                             // SET THE VALUE FOR THE COLUMN
300
jTable.setValueAt(newValue, selectedRows[0]+i, selectedColumns[0]+j);
301                             }
302                         }
303
304                     // UPDATE THE UI AS WE HAVE UPDATED UNDERLIYING DATA
305
// THIS HAS TO PROPOGATE TO THE SCREEN.
306
jTable.updateUI();
307
308                     } catch(NoSuchMethodException JavaDoc nsme) {
309                         nsme.printStackTrace();
310                         JOptionPane.showMessageDialog(jTable, "One of the column class does not provide a constructor"
311                             + "that takes a single String Argument");
312                     } catch(SecurityException JavaDoc se) {
313                         se.printStackTrace();
314                         JOptionPane.showMessageDialog(jTable, "One of the column class does not provide a constructor"
315                             + "that takes a single String Argument");
316                     } catch(InstantiationException JavaDoc ie) {
317                         ie.printStackTrace();
318                         JOptionPane.showMessageDialog(jTable, "Failed to copy data. Error occured while instantiating"
319                             +"a single String argument constructor for a column ");
320                     } catch(Exception JavaDoc e) {
321                         e.printStackTrace();
322                         JOptionPane.showMessageDialog(jTable, "Failed to copy data.");
323                     }
324
325                 } // end if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
326

327         } // end if (((ke.getModifiersEx() & (onMask | offMask)) == onMask) && ke.getKeyCode() == KeyEvent.VK_C) {
328

329     } // end public void keyReleased(KeyEvent ke) {
330

331     /**
332      * Takes the column number and string value to be set for that column and
333      * converts the string in to appropriate class.
334      * The class is found by calling the getColumnClass() method of the JTable.
335      *
336      * @param _jTable JTable containing target object
337      * @param _column the column number for which new value has to be set.
338      * @param _value string representation of the new value.
339      *
340      * @return returns the value as a column class object.
341      */

342     protected Object JavaDoc getObjectToSet(JTable JavaDoc _jTable, int _column, String JavaDoc _value) throws Exception JavaDoc {
343     // GET THE COLUMN CLASS
344
Class JavaDoc objectClass = _jTable.getColumnClass(_column);
345         Object JavaDoc newValue = null;
346         try {
347         // GET THE CONSTRUCTOR FOR THE CLASS WHICH TAKES A STRING
348
Constructor JavaDoc constructor = objectClass.getConstructor(new Class JavaDoc[]{String JavaDoc.class});
349
350         // CREATE AN INSTANCE OF THE OBJECT
351
newValue = constructor.newInstance(new Object JavaDoc[]{_value});
352
353         } catch(NoSuchMethodException JavaDoc nsme) {
354             newValue = _value;
355         }
356
357     // RETURN THE NEWLY CREATED OBJECT.
358
return newValue;
359
360     }
361
362  } // end public class SSTableKeyAdapter extends KeyAdapter implements Serializable {
363

364 /*
365  * $Log: SSTableKeyAdapter.java,v $
366  * Revision 1.6 2005/02/09 21:22:35 yoda2
367  * JavaDoc cleanup.
368  *
369  * Revision 1.5 2005/02/04 22:48:54 yoda2
370  * API cleanup & updated Copyright info.
371  *
372  * Revision 1.4 2004/11/11 14:45:48 yoda2
373  * Using TextPad, converted all tabs to "soft" tabs comprised of four actual spaces.
374  *
375  * Revision 1.3 2004/08/11 14:44:31 prasanth
376  * Added java doc.
377  *
378  * Revision 1.2 2004/08/10 22:06:59 yoda2
379  * Added/edited JavaDoc, made code layout more uniform across classes, made various small coding improvements suggested by PMD.
380  *
381  * Revision 1.1 2004/07/30 22:38:54 prasanth
382  * Table listener for copy and paste support.
383  *
384  */
Popular Tags