14.4 Dropping Multiple Datatypes

A limitation of the Swing data transfer mechanism is that, by default, it supports only a single type of data. It is useful, sometimes, to allow a component to accept pastes and drops of more than one type, handling each type in a different way. A JEditorPane component might handle dropped text in one way, handle dropped colors another way (by changing the foreground color of the selected text, for example), and handle dropped files yet another way (for example, by inserting the contents of the file). In the previous examples, we've created our own TransferHandler instances for simple data transfer customization. For more complex customizations, such as supporting multiple drop types, we need to subclass TransferHandler.

Example 14-3 lists the FileTransferHandler class. It is a TransferHandler subclass that wraps and delegates to some other specified TransferHandler, adding the ability to accept pastes and drops of files using the predefined DataFlavor.javaFileListFlavor flavor. The example includes an inner class named Test that demonstrates its use with a JTextArea and a JFileChooser. Depending on how well integrated your Java implementation is with your operating system's desktop, you may also be able to drag files from your desktop into the JTextArea.

Example 14-3. FileTransferHandler.java
package je3.datatransfer; import javax.swing.*; import java.awt.datatransfer.*; import java.io.*; import java.awt.event.InputEvent; import java.util.List; /**  * This TransferHandler subclass wraps another TransferHandler and delegates  * most of its operations to the wrapped handler.  It adds the ability to  * to drop or paste files using the predefined DataFlavor.javaFileListFlavor.  * When a file list is pasted or dropped, it assumes the files are text, reads  * them in order, concatenates their contents, and then passes the resulting  * string to the wrapped handler for insertion.  */ public class FileTransferHandler extends TransferHandler {     TransferHandler wrappedHandler;    // The handler that we wrap     // We use this array to test the wrapped handler     static DataFlavor[  ] stringFlavorArray =         new DataFlavor[  ] { DataFlavor.stringFlavor };          /** Pass an existing TransferHandler to this constructor */     public FileTransferHandler(TransferHandler wrappedHandler) {         if (wrappedHandler == null)           // Fail immediately on null             throw new NullPointerException( );         this.wrappedHandler = wrappedHandler; // Remember wrapped handler     }          /**      * This method returns true if the TransferHandler knows how to work      * with one of the specified flavors.  This implementation first checks      * the superclass, then checks for fileListFlavor support      */     public boolean canImport(JComponent c, DataFlavor[  ] flavors) {         // If the wrapped handler can import it, we're done         if (wrappedHandler.canImport(c, flavors)) return true;                  // Otherwise, if the wrapped handler can handle string imports, then          // see if we are being offered a list of files that we can convert         // to a string.         if (wrappedHandler.canImport(c, stringFlavorArray)) {             for(int i = 0; i < flavors.length; i++)                  if (flavors[i].equals(DataFlavor.javaFileListFlavor))                     return true;         }                  // Otherwise, we can't import any of the flavors.         return false;     }          /**      * If the wrapped handler can import strings and the specified Transferable      * can provide its data as a List of File objects, then we read the      * files, and pass their contents as a string to the wrapped handler.      * Otherwise, we offer the Transferable to the wrapped handler to handle      * on its own.      */     public boolean importData(JComponent c, Transferable t) {         // See if we're offered a java.util.List of java.io.File objects.         // We handle this case first because the Transferable is likely to         // also offer the filenames as strings, and we want to import the         // file contents, not their names!         if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor) &&             wrappedHandler.canImport(c, stringFlavorArray)) {             try {                 List filelist =                     (List)t.getTransferData(DataFlavor.javaFileListFlavor);                                  // Loop through the files to determine total size                 int numfiles = filelist.size( );                 int numbytes = 0;                 for(int i = 0; i < numfiles; i++) {                     File f = (File)filelist.get(i);                     numbytes += (int)f.length( );                 }                                  // There will never be more characters than bytes in the files                 char[  ] text = new char[numbytes]; // to hold file contents                 int p = 0;         // current position in the text[  ] array                                  // Loop through the files again, reading their content as text                 for(int i = 0; i < numfiles; i++) {                     File f = (File)filelist.get(i);                     Reader r = new BufferedReader(new FileReader(f));                     p += r.read(text, p, (int)f.length( ));                 }                                  // Convert the character array to a string and wrap it                 // in a pre-defined Transferable class for transferring strings                 StringSelection selection =                     new StringSelection(new String(text, 0, p));                 // Ask the wrapped handler to import the string                 return wrappedHandler.importData(c, selection);             }             // If anything goes wrong, just beep to tell the user             catch(UnsupportedFlavorException e) {                 c.getToolkit( ).beep( ); // audible error                 return false;          // return failure code             }             catch(IOException e) {                 c.getToolkit( ).beep( ); // audible error                 return false;          // return failure code             }         }                      // Otherwise let the wrapped class handle this Transferable itself         return wrappedHandler.importData(c, t);     }              /*      * The following methods just delegate to the wrapped TransferHandler      */     public void exportAsDrag(JComponent c, InputEvent e, int action) {         wrappedHandler.exportAsDrag(c, e, action);     }     public void exportToClipboard(JComponent c, Clipboard clip, int action) {         wrappedHandler.exportToClipboard(c, clip, action);     }     public int getSourceActions(JComponent c) {         return wrappedHandler.getSourceActions(c);     }     public Icon getVisualRepresentation(Transferable t) {         // This method is not currently (Java 1.4) used by Swing         return wrappedHandler.getVisualRepresentation(t);     }     /**       * This class demonstrates the FileTransferHandler by installing it on a      * JTextArea component and providing a JFileChooser to drag and cut files.      */     public static class Test {         public static void main(String[  ] args) {             // Here's the text area.  Note how we wrap our TransferHandler             // around the default handler returned by getTransferHandler( )             JTextArea textarea = new JTextArea( );             TransferHandler defaultHandler = textarea.getTransferHandler( );             textarea.setTransferHandler(new FileTransferHandler(defaultHandler));             // Here's a JFileChooser, with dragging explicitly enabled.             JFileChooser filechooser = new JFileChooser( );             filechooser.setDragEnabled(true);             // Display them both in a window             JFrame f = new JFrame("File Transfer Handler Test");             f.getContentPane( ).add(new JScrollPane(textarea), "Center");             f.getContentPane( ).add(filechooser, "South");             f.setSize(400, 600);             f.setVisible(true);         }     } }


Java Examples in a Nutshell
Java Examples in a Nutshell, 3rd Edition
ISBN: 0596006209
EAN: 2147483647
Year: 2003
Pages: 285

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net