Swing JFC Java

/*
 * Copyright (c) 2004 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 3nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose,
 * including teaching and use in open-source projects.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book, 
 * please visit http://www.davidflanagan.com/javaexamples3.
 */
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.InputEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.TransferHandler;
/**
 * 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 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);
  }
}