Java/Swing JFC/Drag Drop

Материал из Java эксперт
Перейти к: навигация, поиск

Содержание

Adding Image-Dragging Behavior

 
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Image;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.TransferHandler;
public class DragImage {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Clip Image");
    Container contentPane = frame.getContentPane();
    final Clipboard clipboard = frame.getToolkit().getSystemClipboard();
    Icon icon = new ImageIcon("jaeger.jpg");
    final JLabel label = new JLabel(icon);
    label.setTransferHandler(new ImageSelection());
    MouseListener mouseListener = new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        JComponent comp = (JComponent) e.getSource();
        TransferHandler handler = comp.getTransferHandler();
        handler.exportAsDrag(comp, e, TransferHandler.COPY);
      }
    };
    label.addMouseListener(mouseListener);
    JScrollPane pane = new JScrollPane(label);
    contentPane.add(pane, BorderLayout.CENTER);
    JButton copy = new JButton("Copy");
    copy.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        TransferHandler handler = label.getTransferHandler();
        handler.exportToClipboard(label, clipboard,
            TransferHandler.COPY);
      }
    });
    JButton clear = new JButton("Clear");
    clear.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent actionEvent) {
        label.setIcon(null);
      }
    });
    clear.setTransferHandler(new TransferHandler("text"));
    mouseListener = new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        JComponent comp = (JComponent) e.getSource();
        TransferHandler handler = comp.getTransferHandler();
        handler.exportAsDrag(comp, e, TransferHandler.COPY);
      }
    };
    clear.addMouseListener(mouseListener);
    JButton paste = new JButton("Paste");
    paste.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent actionEvent) {
        Transferable clipData = clipboard.getContents(clipboard);
        if (clipData != null) {
          if (clipData.isDataFlavorSupported(DataFlavor.imageFlavor)) {
            TransferHandler handler = label.getTransferHandler();
            handler.importData(label, clipData);
          }
        }
      }
    });
    JPanel p = new JPanel();
    p.add(copy);
    p.add(clear);
    p.add(paste);
    contentPane.add(p, BorderLayout.SOUTH);
    JTextField tf = new JTextField();
    tf.setDragEnabled(true);
    contentPane.add(tf, BorderLayout.NORTH);
    frame.setSize(300, 300);
    frame.show();
  }
}
class ImageSelection extends TransferHandler implements Transferable {
  private static final DataFlavor flavors[] = { DataFlavor.imageFlavor };
  private JLabel source;
  private Image image;
  public int getSourceActions(JComponent c) {
    return TransferHandler.COPY;
  }
  public boolean canImport(JComponent comp, DataFlavor flavor[]) {
    if (!(comp instanceof JLabel)) {
      return false;
    }
    for (int i = 0, n = flavor.length; i < n; i++) {
      for (int j = 0, m = flavors.length; j < m; j++) {
        if (flavor[i].equals(flavors[j])) {
          return true;
        }
      }
    }
    return false;
  }
  public Transferable createTransferable(JComponent comp) {
    // Clear
    source = null;
    image = null;
    if (comp instanceof JLabel) {
      JLabel label = (JLabel) comp;
      Icon icon = label.getIcon();
      if (icon instanceof ImageIcon) {
        image = ((ImageIcon) icon).getImage();
        source = label;
        return this;
      }
    }
    return null;
  }
  public boolean importData(JComponent comp, Transferable t) {
    if (comp instanceof JLabel) {
      JLabel label = (JLabel) comp;
      if (t.isDataFlavorSupported(flavors[0])) {
        try {
          image = (Image) t.getTransferData(flavors[0]);
          ImageIcon icon = new ImageIcon(image);
          label.setIcon(icon);
          return true;
        } catch (UnsupportedFlavorException ignored) {
        } catch (IOException ignored) {
        }
      }
    }
    return false;
  }
  // Transferable
  public Object getTransferData(DataFlavor flavor) {
    if (isDataFlavorSupported(flavor)) {
      return image;
    }
    return null;
  }
  public DataFlavor[] getTransferDataFlavors() {
    return flavors;
  }
  public boolean isDataFlavorSupported(DataFlavor flavor) {
    return flavor.equals(DataFlavor.imageFlavor);
  }
}





A simple drop tester application for JDK 1.4 Swing components

 
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
public class DropTest14 extends JFrame {
  JTextArea ta;
  public DropTest14() {
    super("Drop Test 1.4");
    setSize(300, 300);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    getContentPane().add(
        new JLabel("Drop the choice from your JList here:"),
        BorderLayout.NORTH);
    ta = new JTextArea();
    ta.setBackground(Color.white);
    getContentPane().add(ta, BorderLayout.CENTER);
    setVisible(true);
  }
  public static void main(String args[]) {
    new DropTest14();
  }
}





BasicDnD (Drag and Drop)

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * BasicDnD.java is a 1.4 example that requires no other files.
 */
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;
public class BasicDnD extends JPanel implements ActionListener {
  static JFrame frame;
  JTextArea textArea;
  JTextField textField;
  JList list;
  JTable table;
  JTree tree;
  JColorChooser colorChooser;
  JCheckBox toggleDnD;
  public BasicDnD() {
    super(new BorderLayout());
    JPanel leftPanel = createVerticalBoxPanel();
    JPanel rightPanel = createVerticalBoxPanel();
    //Create a table model.
    DefaultTableModel tm = new DefaultTableModel();
    tm.addColumn("Column 0");
    tm.addColumn("Column 1");
    tm.addColumn("Column 2");
    tm.addColumn("Column 3");
    tm
        .addRow(new String[] { "Table 00", "Table 01", "Table 02",
            "Table 03" });
    tm
        .addRow(new String[] { "Table 10", "Table 11", "Table 12",
            "Table 13" });
    tm
        .addRow(new String[] { "Table 20", "Table 21", "Table 22",
            "Table 23" });
    tm
        .addRow(new String[] { "Table 30", "Table 31", "Table 32",
            "Table 33" });
    //LEFT COLUMN
    //Use the table model to create a table.
    table = new JTable(tm);
    leftPanel.add(createPanelForComponent(table, "JTable"));
    //Create a color chooser.
    colorChooser = new JColorChooser();
    leftPanel.add(createPanelForComponent(colorChooser, "JColorChooser"));
    //RIGHT COLUMN
    //Create a textfield.
    textField = new JTextField(30);
    textField.setText("Favorite foods:\nPizza, Moussaka, Pot roast");
    rightPanel.add(createPanelForComponent(textField, "JTextField"));
    //Create a scrolled text area.
    textArea = new JTextArea(5, 30);
    textArea.setText("Favorite shows:\nBuffy, Alias, Angel");
    JScrollPane scrollPane = new JScrollPane(textArea);
    rightPanel.add(createPanelForComponent(scrollPane, "JTextArea"));
    //Create a list model and a list.
    DefaultListModel listModel = new DefaultListModel();
    listModel.addElement("Martha Washington");
    listModel.addElement("Abigail Adams");
    listModel.addElement("Martha Randolph");
    listModel.addElement("Dolley Madison");
    listModel.addElement("Elizabeth Monroe");
    listModel.addElement("Louisa Adams");
    listModel.addElement("Emily Donelson");
    list = new JList(listModel);
    list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    JScrollPane listView = new JScrollPane(list);
    listView.setPreferredSize(new Dimension(300, 100));
    rightPanel.add(createPanelForComponent(listView, "JList"));
    //Create a tree.
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(
        "Mia Familia");
    DefaultMutableTreeNode sharon = new DefaultMutableTreeNode("Sharon");
    rootNode.add(sharon);
    DefaultMutableTreeNode maya = new DefaultMutableTreeNode("Maya");
    sharon.add(maya);
    DefaultMutableTreeNode anya = new DefaultMutableTreeNode("Anya");
    sharon.add(anya);
    sharon.add(new DefaultMutableTreeNode("Bongo"));
    maya.add(new DefaultMutableTreeNode("Muffin"));
    anya.add(new DefaultMutableTreeNode("Winky"));
    DefaultTreeModel model = new DefaultTreeModel(rootNode);
    tree = new JTree(model);
    tree.getSelectionModel().setSelectionMode(
        TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
    JScrollPane treeView = new JScrollPane(tree);
    treeView.setPreferredSize(new Dimension(300, 100));
    rightPanel.add(createPanelForComponent(treeView, "JTree"));
    //Create the toggle button.
    toggleDnD = new JCheckBox("Turn on Drag and Drop");
    toggleDnD.setActionCommand("toggleDnD");
    toggleDnD.addActionListener(this);
    JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
        leftPanel, rightPanel);
    splitPane.setOneTouchExpandable(true);
    add(splitPane, BorderLayout.CENTER);
    add(toggleDnD, BorderLayout.PAGE_END);
    setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  }
  protected JPanel createVerticalBoxPanel() {
    JPanel p = new JPanel();
    p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
    p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    return p;
  }
  public JPanel createPanelForComponent(JComponent comp, String title) {
    JPanel panel = new JPanel(new BorderLayout());
    panel.add(comp, BorderLayout.CENTER);
    if (title != null) {
      panel.setBorder(BorderFactory.createTitledBorder(title));
    }
    return panel;
  }
  public void actionPerformed(ActionEvent e) {
    if ("toggleDnD".equals(e.getActionCommand())) {
      boolean toggle = toggleDnD.isSelected();
      textArea.setDragEnabled(toggle);
      textField.setDragEnabled(toggle);
      list.setDragEnabled(toggle);
      table.setDragEnabled(toggle);
      tree.setDragEnabled(toggle);
      colorChooser.setDragEnabled(toggle);
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    frame = new JFrame("BasicDnD");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    JComponent newContentPane = new BasicDnD();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}





Built-in drag and drop support: utilize a TransferHandler class

  
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.TransferHandler;
public class SimpleDnD {
  public static void main(String[] args) {
    JTextField field = new JTextField(10);
    JButton button = new JButton("Button");
    JFrame f = new JFrame();
    f.setTitle("Simple Drag & Drop");
    f.setLayout(new FlowLayout());
    f.add(button);
    f.add(field);
    field.setDragEnabled(true);
    button.setTransferHandler(new TransferHandler("text"));
    f.setSize(330, 150);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}





Color Drag Source

 
/*
 * This example is from the book "Java Foundation Classes in a Nutshell".
 * Written by David Flanagan. Copyright (c) 1999 by O"Reilly & Associates.  
 * You may distribute this source code for non-commercial purposes only.
 * You may study, modify, and use this example for any purpose, as long as
 * this notice is retained.  Note that this example is provided "as is",
 * WITHOUT WARRANTY of any kind either expressed or implied.
 */
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.*;
/**
 * This simple component displays a solid color, and allows that color
 * to be dragged. Also, it copies the color to the clipboard when the 
 * user clicks on it.
 */
public class ColorSource extends JComponent
       implements ClipboardOwner, DragGestureListener, DragSourceListener
{
  Color color;                // The color to display
  TransferableColor tcolor;   // The color, encapsulated for data transfer
  DragSource dragSource;      // We need this object for drag-and-drop
  /** A ColorSource normally displays itself with this border */
  protected static Border defaultBorder = new BevelBorder(BevelBorder.LOWERED);
  /** When we are the clipboard owner, uses this border */
  protected static Border highlightBorder = 
    new CompoundBorder(defaultBorder, new LineBorder(Color.black, 2));
  /** Create a new ColorSource object that displays the speciifed color */
  public ColorSource(Color color) {
    // Save the color.  Encapsulate it in a Transferable object so that
    // it can be used with cut-and-paste and drag-and-drop
    this.color = color;
    this.tcolor = new TransferableColor(color);
    // Set our default border
    this.setBorder(defaultBorder);
    // Listen for mouse clicks, and copy the color to the clipboard.
    this.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) { copy(); }
    });
    // Set up a DragGestureRecognizer that will detect when the user 
    // begins a drag.  When it detects one, it will notify us by calling
    // the dragGestureRecognized() method of the DragGestureListener
    // interface we implement below
    this.dragSource = DragSource.getDefaultDragSource();
    dragSource.createDefaultDragGestureRecognizer(this, // Look for drags on us
                  DnDConstants.ACTION_COPY_OR_MOVE,  // Recognize these types
                  this);                             // Tell us when recognized
  }
  // These are component methods that make this class work as a component.
  // They specify how big the component is, and what it it looks like.
  protected static Dimension mysize = new Dimension(25, 25);
  public Dimension getMinimumSize() { return mysize; }
  public Dimension getPreferredSize() { return mysize; }
  public void paintComponent(Graphics g) {
    g.setColor(color);
    Dimension s = this.getSize();
    Insets i = this.getInsets();
    g.fillRect(i.left, i.top, 
               s.width-i.left-i.right, s.height-i.top-i.bottom);
  }
  // The methods below support cut-and-paste
  /** This method copies the color to the clipboard. */
  public void copy() {
    // Get system clipboard
    Clipboard c = this.getToolkit().getSystemClipboard();
    // Put our TransferableColor object on the clipboard.
    // Also, we"ll get notification when we no longer own the clipboard
    c.setContents(tcolor, this);
    // Set a special border on ourselves that indicates that we"re the
    // current color available for pasting.
    this.setBorder(highlightBorder);
  }
  // This ClipboardOwner method is called when something else is
  // placed on the clipboard.  It means that our color is no longer
  // available for pasting, and we should not display the highlight border
  public void lostOwnership(Clipboard clipboard, Transferable contents) {
    this.setBorder(defaultBorder);
  }
  // The methods below support drag-and-drop
  // This DragGestureListener method is called when the DragGestureRecognizer
  // detects that the user has dragged the mouse.  It is responsible
  // for beginning the drag-and-drop process.
  public void dragGestureRecognized(DragGestureEvent e) {
    // Create an image we can drag along with us.
    // Not all systems support this, but it doesn"t hurt to try.
    Image colorblock = this.createImage(25,25);
    Graphics g = colorblock.getGraphics();
    g.setColor(color);
    g.fillRect(0,0,25,25);
    // Start dragging our transferable color object.
    e.startDrag(DragSource.DefaultMoveDrop,    // The initial drag cursor
                colorblock, new Point(0,0),    // The image to drag
                tcolor,                        // The data being dragged
                this);                         // Who to notify during drag
  }
  // These methods implement DragSourceListener.
  // Since we passed this object to startDrag, these methods will be
  // called at interesting points during the drag.  We could use them,
  // for example to implement custom cursors or other "drag over" effects
  public void dragEnter(DragSourceDragEvent e) {}
  public void dragExit(DragSourceEvent e) {}
  public void dragDropEnd(DragSourceDropEvent e) {}
  public void dragOver(DragSourceDragEvent e) {}
  public void dropActionChanged(DragSourceDragEvent e) {}
}





Comma separated text will be inserted into two or more rows.

 
import java.awt.FlowLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
public class ListDrop {
  class ListHandler extends TransferHandler {
    public boolean canImport(TransferSupport support) {
      if (!support.isDrop()) {
        return false;
      }
      return support.isDataFlavorSupported(DataFlavor.stringFlavor);
    }
    public boolean importData(TransferSupport support) {
      if (!canImport(support)) {
        return false;
      }
      Transferable transferable = support.getTransferable();
      String line;
      try {
        line = (String) transferable.getTransferData(DataFlavor.stringFlavor);
      } catch (Exception e) {
        return false;
      }
      JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
      int index = dl.getIndex();
      model.add(index++, line);
      return true;
    }
  }
  JTextField field = new JTextField(20);
  DefaultListModel model = new DefaultListModel();
  public ListDrop() {
    JFrame f = new JFrame();
    JList list = new JList(model);
    list.setDropMode(DropMode.INSERT);
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    list.setTransferHandler(new ListHandler());
    field.setDragEnabled(true);
    f.setLayout(new FlowLayout());
    f.add(new JScrollPane(list));
    f.add(field);
    f.pack();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
  public static void main(String[] args) {
    new ListDrop();
  }
}





Create a drag source a drop target and a transferable object.

 
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ComplexExample extends JFrame implements DragGestureListener {
  public ComplexExample() {
    JPanel left = new JPanel();
    left.setBackground(Color.red);
    JPanel right = new JPanel();
    right.setBackground(Color.white);
    new MyDropTargetListener(right);
    DragSource ds = new DragSource();
    ds.createDefaultDragGestureRecognizer(left, DnDConstants.ACTION_COPY, this);
    setLayout(new FlowLayout());
    add(left);
    add(right);
    setSize(40,50);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setVisible(true);
  }
  public void dragGestureRecognized(DragGestureEvent event) {
    Cursor cursor = null;
    JPanel panel = (JPanel) event.getComponent();
    Color color = panel.getBackground();
    if (event.getDragAction() == DnDConstants.ACTION_COPY) {
      cursor = DragSource.DefaultCopyDrop;
    }
    event.startDrag(cursor, new TransferableColor(color));
  }
  class MyDropTargetListener extends DropTargetAdapter {
    private DropTarget dropTarget;
    private JPanel panel;
    public MyDropTargetListener(JPanel panel) {
      this.panel = panel;
      dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY, this, true, null);
    }
    public void drop(DropTargetDropEvent event) {
      try {
        Transferable tr = event.getTransferable();
        Color color = (Color) tr.getTransferData(TransferableColor.colorFlavor);
        if (event.isDataFlavorSupported(TransferableColor.colorFlavor)) {
          event.acceptDrop(DnDConstants.ACTION_COPY);
          this.panel.setBackground(color);
          event.dropComplete(true);
          return;
        }
        event.rejectDrop();
      } catch (Exception e) {
        e.printStackTrace();
        event.rejectDrop();
      }
    }
  }
  public static void main(String[] args) {
    new ComplexExample();
  }
}
class TransferableColor implements Transferable {
  protected static DataFlavor colorFlavor = new DataFlavor(Color.class, "A Color Object");
  protected static DataFlavor[] supportedFlavors = { colorFlavor };
  Color color;
  public TransferableColor(Color color) {
    this.color = color;
  }
  public DataFlavor[] getTransferDataFlavors() {
    return supportedFlavors;
  }
  public boolean isDataFlavorSupported(DataFlavor flavor) {
    if (flavor.equals(colorFlavor) || flavor.equals(DataFlavor.stringFlavor))
      return true;
    return false;
  }
  public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
    if (flavor.equals(colorFlavor))
      return color;
    else if (flavor.equals(DataFlavor.stringFlavor))
      return color.toString();
    else
      throw new UnsupportedFlavorException(flavor);
  }
}





Demonstrate various aspects of Swing data transfer

 
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.TransferHandler;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
 * Demonstrate various aspects of Swing "data transfer".
 * 
 * @author Ian Darwin, http://www.darwinsys.ru
 * @author Jonathan Fuerth, http://www.SQLPower.ca
 */
public class Transfer extends JFrame {
  public static void main(String[] args) {
    new Transfer().setVisible(true);
  }
  private JTextField tf;
  private JLabel l;
  private JComboBox propertyComboBox;
  public Transfer() {
    // Establish the GUI
    Container cp = new Box(BoxLayout.X_AXIS);
    setContentPane(cp);
    JPanel firstPanel = new JPanel();
    propertyComboBox = new JComboBox();
    propertyComboBox.addItem("text");
    propertyComboBox.addItem("font");
    propertyComboBox.addItem("background");
    propertyComboBox.addItem("foreground");
    firstPanel.add(propertyComboBox);
    cp.add(firstPanel);
    cp.add(Box.createGlue());
    tf = new JTextField("Hello");
    tf.setForeground(Color.RED);
    tf.setDragEnabled(true);
    cp.add(tf);
    cp.add(Box.createGlue());
    l = new JLabel("Hello");
    l.setBackground(Color.YELLOW);
    cp.add(l);
    cp.add(Box.createGlue());
    JSlider stryder = new JSlider(SwingConstants.VERTICAL);
    stryder.setMinimum(10);
    stryder.setValue(14);
    stryder.setMaximum(72);
    stryder.setMajorTickSpacing(10);
    stryder.setPaintTicks(true);
    cp.add(stryder);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(500, 300);
    // Add Listeners and Converters
    setMyTransferHandlers((String) propertyComboBox.getSelectedItem());
    // Mousing in the Label starts a Drag.
    MouseListener myDragListener = new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        JComponent c = (JComponent) e.getSource();
        TransferHandler handler = c.getTransferHandler();
        handler.exportAsDrag(c, e, TransferHandler.COPY);
      }
    };
    l.addMouseListener(myDragListener);
    // Selecting in the ComboBox makes that the property that is xfered.
    propertyComboBox.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ce) {
        JComboBox bx = (JComboBox) ce.getSource();
        String prop = (String) bx.getSelectedItem();
        setMyTransferHandlers(prop);
      }
    });
    // Typing a word and pressing enter in the TextField tries
    // to set that as the font name.
    tf.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        JTextField jtf = (JTextField) evt.getSource();
        String fontName = jtf.getText();
        Font font = new Font(fontName, Font.BOLD, 18);
        tf.setFont(font);
      }
    });
    // Setting the Slider sets that font into the textfield.
    stryder.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent evt) {
        JSlider sl = (JSlider) evt.getSource();
        Font oldf = tf.getFont();
        Font newf = oldf.deriveFont((float) sl.getValue());
        tf.setFont(newf);
      }
    });
  }
  private void setMyTransferHandlers(String s) {
    TransferHandler th = new TransferHandler(s);
    tf.setTransferHandler(th);
    l.setTransferHandler(th);
  }
}





Detect a drag initiating gesture in your application

 
import java.awt.BorderLayout;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
public class Main extends JFrame implements DragGestureListener {
  String[] items = { "Java", "C", "C++", "Lisp", "Perl", "Python" };
  DragSource ds = new DragSource();
  JList jl = new JList(items);
  public Main() {
    setSize(200, 150);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    getContentPane().add(new JScrollPane(jl), BorderLayout.CENTER);
    
    DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(jl, DnDConstants.ACTION_COPY,
        this);
    setVisible(true);
  }
  public void dragGestureRecognized(DragGestureEvent dge) {
    System.out.println("Drag Gesture Recognized!");
  }
  public static void main(String args[]) {
    new Main();
  }
}





Drag and drop

 
/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd 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.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.ru/javaexamples2.
 */
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.StringTokenizer;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
/**
 * This component can operate in two modes. In "draw mode", it allows the user
 * to scribble with the mouse. In "drag mode", it allows the user to drag
 * scribbles with the mouse. Regardless of the mode, it always allows scribbles
 * to be dropped on it from other applications.
 */
public class ScribbleDragAndDrop extends JComponent implements
    DragGestureListener, // For recognizing the start of drags
    DragSourceListener, // For processing drag source events
    DropTargetListener, // For processing drop target events
    MouseListener, // For processing mouse clicks
    MouseMotionListener // For processing mouse drags
{
  ArrayList scribbles = new ArrayList(); // A list of Scribbles to draw
  Scribble currentScribble; // The scribble in progress
  Scribble beingDragged; // The scribble being dragged
  DragSource dragSource; // A central DnD object
  boolean dragMode; // Are we dragging or scribbling?
  // These are some constants we use
  static final int LINEWIDTH = 3;
  static final BasicStroke linestyle = new BasicStroke(LINEWIDTH);
  static final Border normalBorder = new BevelBorder(BevelBorder.LOWERED);
  static final Border dropBorder = new BevelBorder(BevelBorder.RAISED);
  /** The constructor: set up drag-and-drop stuff */
  public ScribbleDragAndDrop() {
    // Give ourselves a nice default border.
    // We"ll change this border during drag-and-drop.
    setBorder(normalBorder);
    // Register listeners to handle drawing
    addMouseListener(this);
    addMouseMotionListener(this);
    // Create a DragSource and DragGestureRecognizer to listen for drags
    // The DragGestureRecognizer will notify the DragGestureListener
    // when the user tries to drag an object
    dragSource = DragSource.getDefaultDragSource();
    dragSource.createDefaultDragGestureRecognizer(this, // What component
        DnDConstants.ACTION_COPY_OR_MOVE, // What drag types?
        this);// the listener
    // Create and set up a DropTarget that will listen for drags and
    // drops over this component, and will notify the DropTargetListener
    DropTarget dropTarget = new DropTarget(this, // component to monitor
        this); // listener to notify
    this.setDropTarget(dropTarget); // Tell the component about it.
  }
  /**
   * The component draws itself by drawing each of the Scribble objects.
   */
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.setStroke(linestyle); // Specify wide lines
    int numScribbles = scribbles.size();
    for (int i = 0; i < numScribbles; i++) {
      Scribble s = (Scribble) scribbles.get(i);
      g2.draw(s); // Draw the scribble
    }
  }
  public void setDragMode(boolean dragMode) {
    this.dragMode = dragMode;
  }
  public boolean getDragMode() {
    return dragMode;
  }
  /**
   * This method, and the following four methods are from the MouseListener
   * interface. If we"re in drawing mode, this method handles mouse down
   * events and starts a new scribble.
   */
  public void mousePressed(MouseEvent e) {
    if (dragMode)
      return;
    currentScribble = new Scribble();
    scribbles.add(currentScribble);
    currentScribble.moveto(e.getX(), e.getY());
  }
  public void mouseReleased(MouseEvent e) {
  }
  public void mouseClicked(MouseEvent e) {
  }
  public void mouseEntered(MouseEvent e) {
  }
  public void mouseExited(MouseEvent e) {
  }
  /**
   * This method and mouseMoved() below are from the MouseMotionListener
   * interface. If we"re in drawing mode, this method adds a new point to the
   * current scribble and requests a redraw
   */
  public void mouseDragged(MouseEvent e) {
    if (dragMode)
      return;
    currentScribble.lineto(e.getX(), e.getY());
    repaint();
  }
  public void mouseMoved(MouseEvent e) {
  }
  /**
   * This method implements the DragGestureListener interface. It will be
   * invoked when the DragGestureRecognizer thinks that the user has initiated
   * a drag. If we"re not in drawing mode, then this method will try to figure
   * out which Scribble object is being dragged, and will initiate a drag on
   * that object.
   */
  public void dragGestureRecognized(DragGestureEvent e) {
    // Don"t drag if we"re not in drag mode
    if (!dragMode)
      return;
    // Figure out where the drag started
    MouseEvent inputEvent = (MouseEvent) e.getTriggerEvent();
    int x = inputEvent.getX();
    int y = inputEvent.getY();
    // Figure out which scribble was clicked on, if any by creating a
    // small rectangle around the point and testing for intersection.
    Rectangle r = new Rectangle(x - LINEWIDTH, y - LINEWIDTH,
        LINEWIDTH * 2, LINEWIDTH * 2);
    int numScribbles = scribbles.size();
    for (int i = 0; i < numScribbles; i++) { // Loop through the scribbles
      Scribble s = (Scribble) scribbles.get(i);
      if (s.intersects(r)) {
        // The user started the drag on top of this scribble, so
        // start to drag it.
        // First, remember which scribble is being dragged, so we can
        // delete it later (if this is a move rather than a copy)
        beingDragged = s;
        // Next, create a copy that will be the one dragged
        Scribble dragScribble = (Scribble) s.clone();
        // Adjust the origin to the point the user clicked on.
        dragScribble.translate(-x, -y);
        // Choose a cursor based on the type of drag the user initiated
        Cursor cursor;
        switch (e.getDragAction()) {
        case DnDConstants.ACTION_COPY:
          cursor = DragSource.DefaultCopyDrop;
          break;
        case DnDConstants.ACTION_MOVE:
          cursor = DragSource.DefaultMoveDrop;
          break;
        default:
          return; // We only support move and copys
        }
        // Some systems allow us to drag an image along with the
        // cursor. If so, create an image of the scribble to drag
        if (dragSource.isDragImageSupported()) {
          Rectangle scribbleBox = dragScribble.getBounds();
          Image dragImage = this.createImage(scribbleBox.width,
              scribbleBox.height);
          Graphics2D g = (Graphics2D) dragImage.getGraphics();
          g.setColor(new Color(0, 0, 0, 0)); // transparent background
          g.fillRect(0, 0, scribbleBox.width, scribbleBox.height);
          g.setColor(Color.black);
          g.setStroke(linestyle);
          g.translate(-scribbleBox.x, -scribbleBox.y);
          g.draw(dragScribble);
          Point hotspot = new Point(-scribbleBox.x, -scribbleBox.y);
          // Now start dragging, using the image.
          e.startDrag(cursor, dragImage, hotspot, dragScribble, this);
        } else {
          // Or start the drag without an image
          e.startDrag(cursor, dragScribble, this);
        }
        // After we"ve started dragging one scribble, stop looking
        return;
      }
    }
  }
  /**
   * This method, and the four unused methods that follow it implement the
   * DragSourceListener interface. dragDropEnd() is invoked when the user
   * drops the scribble she was dragging. If the drop was successful, and if
   * the user did a "move" rather than a "copy", then we delete the dragged
   * scribble from the list of scribbles to draw.
   */
  public void dragDropEnd(DragSourceDropEvent e) {
    if (!e.getDropSuccess())
      return;
    int action = e.getDropAction();
    if (action == DnDConstants.ACTION_MOVE) {
      scribbles.remove(beingDragged);
      beingDragged = null;
      repaint();
    }
  }
  // These methods are also part of DragSourceListener.
  // They are invoked at interesting points during the drag, and can be
  // used to perform "drag over" effects, such as changing the drag cursor
  // or drag image.
  public void dragEnter(DragSourceDragEvent e) {
  }
  public void dragExit(DragSourceEvent e) {
  }
  public void dropActionChanged(DragSourceDragEvent e) {
  }
  public void dragOver(DragSourceDragEvent e) {
  }
  // The next five methods implement DropTargetListener
  /**
   * This method is invoked when the user first drags something over us. If we
   * understand the data type being dragged, then call acceptDrag() to tell
   * the system that we"re receptive. Also, we change our border as a "drag
   * under" effect to signal that we can accept the drop.
   */
  public void dragEnter(DropTargetDragEvent e) {
    if (e.isDataFlavorSupported(Scribble.scribbleDataFlavor)
        || e.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      e.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
      this.setBorder(dropBorder);
    }
  }
  /** The user is no longer dragging over us, so restore the border */
  public void dragExit(DropTargetEvent e) {
    this.setBorder(normalBorder);
  }
  /**
   * This is the key method of DropTargetListener. It is invoked when the user
   * drops something on us.
   */
  public void drop(DropTargetDropEvent e) {
    this.setBorder(normalBorder); // Restore the default border
    // First, check whether we understand the data that was dropped.
    // If we supports our data flavors, accept the drop, otherwise reject.
    if (e.isDataFlavorSupported(Scribble.scribbleDataFlavor)
        || e.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
    } else {
      e.rejectDrop();
      return;
    }
    // We"ve accepted the drop, so now we attempt to get the dropped data
    // from the Transferable object.
    Transferable t = e.getTransferable(); // Holds the dropped data
    Scribble droppedScribble; // This will hold the Scribble object
    // First, try to get the data directly as a scribble object
    try {
      droppedScribble = (Scribble) t
          .getTransferData(Scribble.scribbleDataFlavor);
    } catch (Exception ex) { // unsupported flavor, IO exception, etc.
      // If that doesn"t work, try to get it as a String and parse it
      try {
        String s = (String) t.getTransferData(DataFlavor.stringFlavor);
        droppedScribble = Scribble.parse(s);
      } catch (Exception ex2) {
        // If we still couldn"t get the data, tell the system we failed
        e.dropComplete(false);
        return;
      }
    }
    // If we get here, we"ve got the Scribble object
    Point p = e.getLocation(); // Where did the drop happen?
    droppedScribble.translate(p.getX(), p.getY()); // Move it there
    scribbles.add(droppedScribble); // add to display list
    repaint(); // ask for redraw
    e.dropComplete(true); // signal success!
  }
  // These are unused DropTargetListener methods
  public void dragOver(DropTargetDragEvent e) {
  }
  public void dropActionChanged(DropTargetDragEvent e) {
  }
  /**
   * The main method. Creates a simple application using this class. Note the
   * buttons for switching between draw mode and drag mode.
   */
  public static void main(String[] args) {
    // Create a frame and put a scribble pane in it
    JFrame frame = new JFrame("ScribbleDragAndDrop");
    final ScribbleDragAndDrop scribblePane = new ScribbleDragAndDrop();
    frame.getContentPane().add(scribblePane, BorderLayout.CENTER);
    // Create two buttons for switching modes
    JToolBar toolbar = new JToolBar();
    ButtonGroup group = new ButtonGroup();
    JToggleButton draw = new JToggleButton("Draw");
    JToggleButton drag = new JToggleButton("Drag");
    draw.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        scribblePane.setDragMode(false);
      }
    });
    drag.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        scribblePane.setDragMode(true);
      }
    });
    group.add(draw);
    group.add(drag);
    toolbar.add(draw);
    toolbar.add(drag);
    frame.getContentPane().add(toolbar, BorderLayout.NORTH);
    // Start off in drawing mode
    draw.setSelected(true);
    scribblePane.setDragMode(false);
    // Pop up the window
    frame.setSize(400, 400);
    frame.setVisible(true);
  }
}
class Scribble implements Shape, Transferable, Serializable, Cloneable {
  protected double[] points = new double[64]; // The scribble data
  protected int numPoints = 0; // The current number of points
  double maxX = Double.NEGATIVE_INFINITY; // The bounding box
  double maxY = Double.NEGATIVE_INFINITY;
  double minX = Double.POSITIVE_INFINITY;
  double minY = Double.POSITIVE_INFINITY;
  /**
   * Begin a new polyline at (x,y). Note the use of Double.NaN in the points
   * array to mark the beginning of a new polyline
   */
  public void moveto(double x, double y) {
    if (numPoints + 3 > points.length)
      reallocate();
    // Mark this as the beginning of a new line
    points[numPoints++] = Double.NaN;
    // The rest of this method is just like lineto();
    lineto(x, y);
  }
  /**
   * Add the point (x,y) to the end of the current polyline
   */
  public void lineto(double x, double y) {
    if (numPoints + 2 > points.length)
      reallocate();
    points[numPoints++] = x;
    points[numPoints++] = y;
    // See if the point enlarges our bounding box
    if (x > maxX)
      maxX = x;
    if (x < minX)
      minX = x;
    if (y > maxY)
      maxY = y;
    if (y < minY)
      minY = y;
  }
  /**
   * Append the Scribble s to this Scribble
   */
  public void append(Scribble s) {
    int n = numPoints + s.numPoints;
    double[] newpoints = new double[n];
    System.arraycopy(points, 0, newpoints, 0, numPoints);
    System.arraycopy(s.points, 0, newpoints, numPoints, s.numPoints);
    points = newpoints;
    numPoints = n;
    minX = Math.min(minX, s.minX);
    maxX = Math.max(maxX, s.maxX);
    minY = Math.min(minY, s.minY);
    maxY = Math.max(maxY, s.maxY);
  }
  /**
   * Translate the coordinates of all points in the Scribble by x,y
   */
  public void translate(double x, double y) {
    for (int i = 0; i < numPoints; i++) {
      if (Double.isNaN(points[i]))
        continue;
      points[i++] += x;
      points[i] += y;
    }
    minX += x;
    maxX += x;
    minY += y;
    maxY += y;
  }
  /** An internal method to make more room in the data array */
  protected void reallocate() {
    double[] newpoints = new double[points.length * 2];
    System.arraycopy(points, 0, newpoints, 0, numPoints);
    points = newpoints;
  }
  /** Clone a Scribble object and its internal array of data */
  public Object clone() {
    try {
      Scribble s = (Scribble) super.clone(); // make a copy of all fields
      s.points = (double[]) points.clone(); // copy the entire array
      return s;
    } catch (CloneNotSupportedException e) { // This should never happen
      return this;
    }
  }
  /** Convert the scribble data to a textual format */
  public String toString() {
    StringBuffer b = new StringBuffer();
    for (int i = 0; i < numPoints; i++) {
      if (Double.isNaN(points[i])) {
        b.append("m ");
      } else {
        b.append(points[i]);
        b.append(" ");
      }
    }
    return b.toString();
  }
  /**
   * Create a new Scribble object and initialize it by parsing a string of
   * coordinate data in the format produced by toString()
   */
  public static Scribble parse(String s) throws NumberFormatException {
    StringTokenizer st = new StringTokenizer(s);
    Scribble scribble = new Scribble();
    while (st.hasMoreTokens()) {
      String t = st.nextToken();
      if (t.charAt(0) == "m") {
        scribble.moveto(Double.parseDouble(st.nextToken()), Double
            .parseDouble(st.nextToken()));
      } else {
        scribble.lineto(Double.parseDouble(t), Double.parseDouble(st
            .nextToken()));
      }
    }
    return scribble;
  }
  // ========= The following methods implement the Shape interface ========
  /** Return the bounding box of the Shape */
  public Rectangle getBounds() {
    return new Rectangle((int) (minX - 0.5f), (int) (minY - 0.5f),
        (int) (maxX - minX + 0.5f), (int) (maxY - minY + 0.5f));
  }
  /** Return the bounding box of the Shape */
  public Rectangle2D getBounds2D() {
    return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
  }
  /** Our shape is an open curve, so it never contains anything */
  public boolean contains(Point2D p) {
    return false;
  }
  public boolean contains(Rectangle2D r) {
    return false;
  }
  public boolean contains(double x, double y) {
    return false;
  }
  public boolean contains(double x, double y, double w, double h) {
    return false;
  }
  /**
   * Determine if the scribble intersects the specified rectangle by testing
   * each line segment individually
   */
  public boolean intersects(Rectangle2D r) {
    if (numPoints < 4)
      return false;
    int i = 0;
    double x1, y1, x2 = 0.0, y2 = 0.0;
    while (i < numPoints) {
      if (Double.isNaN(points[i])) { // If we"re beginning a new line
        i++; // Skip the NaN
        x2 = points[i++];
        y2 = points[i++];
      } else {
        x1 = x2;
        y1 = y2;
        x2 = points[i++];
        y2 = points[i++];
        if (r.intersectsLine(x1, y1, x2, y2))
          return true;
      }
    }
    return false;
  }
  /** Test for intersection by invoking the method above */
  public boolean intersects(double x, double y, double w, double h) {
    return intersects(new Rectangle2D.Double(x, y, w, h));
  }
  /**
   * Return a PathIterator object that tells Java2D how to draw this scribble
   */
  public PathIterator getPathIterator(AffineTransform at) {
    return new ScribbleIterator(at);
  }
  /**
   * Return a PathIterator that doesn"t include curves. Ours never does.
   */
  public PathIterator getPathIterator(AffineTransform at, double flatness) {
    return getPathIterator(at);
  }
  /**
   * This inner class implements the PathIterator interface to describe the
   * shape of a scribble. Since a Scribble is composed of arbitrary movetos
   * and linetos, we simply return their coordinates
   */
  public class ScribbleIterator implements PathIterator {
    protected int i = 0; // Position in array
    protected AffineTransform transform;
    public ScribbleIterator(AffineTransform transform) {
      this.transform = transform;
    }
    /** How to determine insideness and outsideness for this shape */
    public int getWindingRule() {
      return PathIterator.WIND_NON_ZERO;
    }
    /** Have we reached the end of the scribble path yet? */
    public boolean isDone() {
      return i >= numPoints;
    }
    /** Move on to the next segment of the path */
    public void next() {
      if (Double.isNaN(points[i]))
        i += 3;
      else
        i += 2;
    }
    /**
     * Get the coordinates of the current moveto or lineto as floats
     */
    public int currentSegment(float[] coords) {
      int retval;
      if (Double.isNaN(points[i])) { // If its a moveto
        coords[0] = (float) points[i + 1];
        coords[1] = (float) points[i + 2];
        retval = SEG_MOVETO;
      } else {
        coords[0] = (float) points[i];
        coords[1] = (float) points[i + 1];
        retval = SEG_LINETO;
      }
      // If a transform was specified, use it on the coordinates
      if (transform != null)
        transform.transform(coords, 0, coords, 0, 1);
      return retval;
    }
    /**
     * Get the coordinates of the current moveto or lineto as doubles
     */
    public int currentSegment(double[] coords) {
      int retval;
      if (Double.isNaN(points[i])) {
        coords[0] = points[i + 1];
        coords[1] = points[i + 2];
        retval = SEG_MOVETO;
      } else {
        coords[0] = points[i];
        coords[1] = points[i + 1];
        retval = SEG_LINETO;
      }
      if (transform != null)
        transform.transform(coords, 0, coords, 0, 1);
      return retval;
    }
  }
  //====== The following methods implement the Transferable interface =====
  // This is the custom DataFlavor for Scribble objects
  public static DataFlavor scribbleDataFlavor = new DataFlavor(
      Scribble.class, "Scribble");
  // This is a list of the flavors we know how to work with
  public static DataFlavor[] supportedFlavors = { scribbleDataFlavor,
      DataFlavor.stringFlavor };
  /** Return the data formats or "flavors" we know how to transfer */
  public DataFlavor[] getTransferDataFlavors() {
    return (DataFlavor[]) supportedFlavors.clone();
  }
  /** Check whether we support a given flavor */
  public boolean isDataFlavorSupported(DataFlavor flavor) {
    return (flavor.equals(scribbleDataFlavor) || flavor
        .equals(DataFlavor.stringFlavor));
  }
  /**
   * Return the scribble data in the requested format, or throw an exception
   * if we don"t support the requested format
   */
  public Object getTransferData(DataFlavor flavor)
      throws UnsupportedFlavorException {
    if (flavor.equals(scribbleDataFlavor)) {
      return this;
    } else if (flavor.equals(DataFlavor.stringFlavor)) {
      return toString();
    } else
      throw new UnsupportedFlavorException(flavor);
  }
}





Drag and drop icons: use an icon property.

 
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.TransferHandler;
class DragMouseAdapter extends MouseAdapter {
  public void mousePressed(MouseEvent e) {
    JComponent c = (JComponent) e.getSource();
    TransferHandler handler = c.getTransferHandler();
    handler.exportAsDrag(c, e, TransferHandler.COPY);
  }
}
public class IconDnD {
  public static void main(String[] args) {
    JFrame f = new JFrame("Icon Drag & Drop");
    ImageIcon icon1 = new ImageIcon("a.png");
    ImageIcon icon2 = new ImageIcon("b.png");
    ImageIcon icon3 = new ImageIcon("c.png");
    JButton button = new JButton(icon2);
    JLabel label1 = new JLabel(icon1, JLabel.CENTER);
    JLabel label2 = new JLabel(icon3, JLabel.CENTER);
    MouseListener listener = new DragMouseAdapter();
    label1.addMouseListener(listener);
    label2.addMouseListener(listener);
    label1.setTransferHandler(new TransferHandler("icon"));
    button.setTransferHandler(new TransferHandler("icon"));
    label2.setTransferHandler(new TransferHandler("icon"));
    f.setLayout(new FlowLayout());
    f.add(label1);
    f.add(button);
    f.add(label2);
    f.pack();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
}





Drag and drop: TextArea

 
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// DropTest2.java
//Another simple drag & drop tester application.
//
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
public class DropTest2 extends JFrame implements DropTargetListener {
  DropTarget dt;
  JTextArea ta;
  public DropTest2() {
    super("Drop Test");
    setSize(300, 300);

    getContentPane().add(
        new JLabel("Drop a list from your file chooser here:"),
        BorderLayout.NORTH);
    ta = new JTextArea();
    ta.setBackground(Color.white);
    getContentPane().add(ta, BorderLayout.CENTER);
    // Set up our text area to recieve drops...
    // This class will handle drop events
    dt = new DropTarget(ta, this);
    setVisible(true);
  }
  public void dragEnter(DropTargetDragEvent dtde) {
    System.out.println("Drag Enter");
  }
  public void dragExit(DropTargetEvent dte) {
    System.out.println("Drag Exit");
  }
  public void dragOver(DropTargetDragEvent dtde) {
    System.out.println("Drag Over");
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    System.out.println("Drop Action Changed");
  }
  public void drop(DropTargetDropEvent dtde) {
    try {
      // Ok, get the dropped object and try to figure out what it is
      Transferable tr = dtde.getTransferable();
      DataFlavor[] flavors = tr.getTransferDataFlavors();
      for (int i = 0; i < flavors.length; i++) {
        System.out.println("Possible flavor: "
            + flavors[i].getMimeType());
        // Check for file lists specifically
        if (flavors[i].isFlavorJavaFileListType()) {
          // Great! Accept copy drops...
          dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
          ta.setText("Successful file list drop.\n\n");
          // And add the list of file names to our text area
          java.util.List list = (java.util.List) tr
              .getTransferData(flavors[i]);
          for (int j = 0; j < list.size(); j++) {
            ta.append(list.get(j) + "\n");
          }
          // If we made it this far, everything worked.
          dtde.dropComplete(true);
          return;
        }
        // Ok, is it another Java object?
        else if (flavors[i].isFlavorSerializedObjectType()) {
          dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
          ta.setText("Successful text drop.\n\n");
          Object o = tr.getTransferData(flavors[i]);
          ta.append("Object: " + o);
          dtde.dropComplete(true);
          return;
        }
        // How about an input stream?
        else if (flavors[i].isRepresentationClassInputStream()) {
          dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
          ta.setText("Successful text drop.\n\n");
          ta.read(new InputStreamReader((InputStream) tr
              .getTransferData(flavors[i])),
              "from system clipboard");
          dtde.dropComplete(true);
          return;
        }
      }
      // Hmm, the user must not have dropped a file list
      System.out.println("Drop failed: " + dtde);
      dtde.rejectDrop();
    } catch (Exception e) {
      e.printStackTrace();
      dtde.rejectDrop();
    }
  }
  public static void main(String args[]) {
    new DropTest2();
  }
}





Drag capabilities: JList

 
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
public class DragTest14 extends JFrame {
  JList jl;
  String[] items = { "Java", "C", "C++", "Lisp", "Perl", "Python" };
  public DragTest14() {
    super("Drag Test 1.4");
    setSize(200, 150);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    jl = new JList(items);
    jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    jl.setDragEnabled(true);
    getContentPane().add(new JScrollPane(jl), BorderLayout.CENTER);
    setVisible(true);
  }
  public static void main(String args[]) {
    new DragTest14();
  }
}





Drag Color Demo

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * DragColorDemo.java is a 1.4 example that requires 
 * the following file:
 *    ColorTransferHandler.java
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.TransferHandler;
/**
 * Example code that shows any JComponent can be customized to allow dropping of
 * a color.
 */
public class DragColorDemo extends JPanel implements ActionListener {
  JCheckBox toggleForeground;
  ColorTransferHandler colorHandler;
  public DragColorDemo() {
    super(new BorderLayout());
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
    JColorChooser chooser = new JColorChooser();
    chooser.setDragEnabled(true);
    add(chooser, BorderLayout.PAGE_START);
    //Create the color transfer handler.
    colorHandler = new ColorTransferHandler();
    //Create a matrix of 9 buttons.
    JPanel buttonPanel = new JPanel(new GridLayout(3, 3));
    for (int i = 0; i < 9; i++) {
      JButton tmp = new JButton("Button " + i);
      tmp.setTransferHandler(colorHandler);
      buttonPanel.add(tmp);
    }
    add(buttonPanel, BorderLayout.CENTER);
    //Create a check box.
    toggleForeground = new JCheckBox("Change the foreground color.");
    toggleForeground.setSelected(true);
    toggleForeground.addActionListener(this);
    JPanel textPanel = new JPanel(new BorderLayout());
    textPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    textPanel.add(toggleForeground, BorderLayout.PAGE_START);
    //Create a label.
    JLabel label = new JLabel(
        "Change the color of any button or this label by dropping a color.");
    label.setTransferHandler(colorHandler);
    label.setOpaque(true); //So the background color can be changed.
    textPanel.add(label, BorderLayout.PAGE_END);
    add(textPanel, BorderLayout.PAGE_END);
  }
  public void actionPerformed(ActionEvent e) {
    colorHandler.setChangesForegroundColor(toggleForeground.isSelected());
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("DragColorDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and setup the content pane.
    JComponent newContentPane = new DragColorDemo();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
/*
 * ColorTransferHandler.java is used by the 1.4 DragColorDemo.java and
 * DragColorTextFieldDemo examples.
 */
/**
 * An implementation of TransferHandler that adds support for dropping colors.
 * Dropping a color on a component having this TransferHandler changes the
 * foreground or the background of the component to the dropped color, according
 * to the value of the changesForegroundColor property.
 */
class ColorTransferHandler extends TransferHandler {
  //The data type exported from JColorChooser.
  String mimeType = DataFlavor.javaJVMLocalObjectMimeType
      + ";class=java.awt.Color";
  DataFlavor colorFlavor;
  private boolean changesForegroundColor = true;
  ColorTransferHandler() {
    //Try to create a DataFlavor for color.
    try {
      colorFlavor = new DataFlavor(mimeType);
    } catch (ClassNotFoundException e) {
    }
  }
  /**
   * Overridden to import a Color if it is available.
   * getChangesForegroundColor is used to determine whether the foreground or
   * the background color is changed.
   */
  public boolean importData(JComponent c, Transferable t) {
    if (hasColorFlavor(t.getTransferDataFlavors())) {
      try {
        Color col = (Color) t.getTransferData(colorFlavor);
        if (getChangesForegroundColor()) {
          c.setForeground(col);
        } else {
          c.setBackground(col);
        }
        return true;
      } catch (UnsupportedFlavorException ufe) {
        System.out.println("importData: unsupported data flavor");
      } catch (IOException ioe) {
        System.out.println("importData: I/O exception");
      }
    }
    return false;
  }
  /**
   * Does the flavor list have a Color flavor?
   */
  protected boolean hasColorFlavor(DataFlavor[] flavors) {
    if (colorFlavor == null) {
      return false;
    }
    for (int i = 0; i < flavors.length; i++) {
      if (colorFlavor.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
  /**
   * Overridden to include a check for a color flavor.
   */
  public boolean canImport(JComponent c, DataFlavor[] flavors) {
    return hasColorFlavor(flavors);
  }
  protected void setChangesForegroundColor(boolean flag) {
    changesForegroundColor = flag;
  }
  protected boolean getChangesForegroundColor() {
    return changesForegroundColor;
  }
}





Drag Color TextField Demo

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * DragColorTextFieldDemo.java is a 1.4 example that requires
 * the following files:
 *     ColorTransferHandler.java
 *     ColorAndTextTransferHandler.java
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.KeyEvent;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.TransferHandler;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.Position;
/**
 * Example code that shows a text component that both accepts color (by changing
 * its foreground) and also exports simple text.
 */
public class DragColorTextFieldDemo extends JPanel {
  JCheckBox toggleForeground;
  ColorAndTextTransferHandler colorHandler;
  public DragColorTextFieldDemo() {
    super(new BorderLayout());
    JTextField textField;
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
    JColorChooser chooser = new JColorChooser();
    chooser.setDragEnabled(true);
    add(chooser, BorderLayout.PAGE_START);
    //Create the color transfer handler.
    colorHandler = new ColorAndTextTransferHandler();
    //Create some text fields.
    JPanel buttonPanel = new JPanel(new GridLayout(3, 1));
    textField = new JTextField("I can accept color/text and drag text.");
    textField.setTransferHandler(colorHandler);
    textField.setDragEnabled(true);
    buttonPanel.add(textField);
    textField = new JTextField("Me too!");
    textField.setTransferHandler(colorHandler);
    textField.setDragEnabled(true);
    buttonPanel.add(textField);
    textField = new JTextField("Me three!");
    textField.setTransferHandler(colorHandler);
    textField.setDragEnabled(true);
    buttonPanel.add(textField);
    add(buttonPanel, BorderLayout.CENTER);
  }
  //Create an Edit menu to support cut/copy/paste.
  public JMenuBar createMenuBar() {
    JMenuItem menuItem = null;
    JMenuBar menuBar = new JMenuBar();
    JMenu mainMenu = new JMenu("Edit");
    mainMenu.setMnemonic(KeyEvent.VK_E);
    menuItem = new JMenuItem(new DefaultEditorKit.CutAction());
    menuItem.setText("Cut");
    menuItem.setMnemonic(KeyEvent.VK_T);
    mainMenu.add(menuItem);
    menuItem = new JMenuItem(new DefaultEditorKit.CopyAction());
    menuItem.setText("Copy");
    menuItem.setMnemonic(KeyEvent.VK_C);
    mainMenu.add(menuItem);
    menuItem = new JMenuItem(new DefaultEditorKit.PasteAction());
    menuItem.setText("Paste");
    menuItem.setMnemonic(KeyEvent.VK_P);
    mainMenu.add(menuItem);
    menuBar.add(mainMenu);
    return menuBar;
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("DragColorTextFieldDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the menu bar and content pane.
    DragColorTextFieldDemo demo = new DragColorTextFieldDemo();
    frame.setJMenuBar(demo.createMenuBar());
    demo.setOpaque(true); //content panes must be opaque
    frame.setContentPane(demo);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
/*
 * ColorAndTextTransferHandler.java is used by the 1.4 DragColorDemo.java
 * example.
 */
/**
 * An implementation of TransferHandler that adds support for the import of
 * color and the import and export of text. Dropping a color on a component
 * having this TransferHandler changes the foreground of the component to the
 * imported color.
 */
class ColorAndTextTransferHandler extends ColorTransferHandler {
  private DataFlavor stringFlavor = DataFlavor.stringFlavor;
  private JTextComponent source;
  private boolean shouldRemove;
  //Start and end position in the source text.
  //We need this information when performing a MOVE
  //in order to remove the dragged text from the source.
  Position p0 = null, p1 = null;
  //Get the flavors from the Transferable.
  //Is there a color flavor? If so, set the foreground color.
  //Is there a string flavor? If so, set the text property.
  public boolean importData(JComponent c, Transferable t) {
    JTextComponent tc = (JTextComponent) c;
    if (!canImport(c, t.getTransferDataFlavors())) {
      return false;
    }
    if (tc.equals(source) && (tc.getCaretPosition() >= p0.getOffset())
        && (tc.getCaretPosition() <= p1.getOffset())) {
      shouldRemove = false;
      return true;
    }
    if (hasStringFlavor(t.getTransferDataFlavors())) {
      try {
        String str = (String) t.getTransferData(stringFlavor);
        tc.replaceSelection(str);
        return true;
      } catch (UnsupportedFlavorException ufe) {
        System.out.println("importData: unsupported data flavor");
      } catch (IOException ioe) {
        System.out.println("importData: I/O exception");
      }
    }
    //The ColorTransferHandler superclass handles color.
    return super.importData(c, t);
  }
  //Create a Transferable implementation that contains the
  //selected text.
  protected Transferable createTransferable(JComponent c) {
    source = (JTextComponent) c;
    int start = source.getSelectionStart();
    int end = source.getSelectionEnd();
    Document doc = source.getDocument();
    if (start == end) {
      return null;
    }
    try {
      p0 = doc.createPosition(start);
      p1 = doc.createPosition(end);
    } catch (BadLocationException e) {
      System.out
          .println("Can"t create position - unable to remove text from source.");
    }
    shouldRemove = true;
    String data = source.getSelectedText();
    return new StringSelection(data);
  }
  public int getSourceActions(JComponent c) {
    return COPY_OR_MOVE;
  }
  //Remove the old text if the action is a MOVE.
  //However, we do not allow dropping on top of the selected text,
  //so in that case do nothing.
  protected void exportDone(JComponent c, Transferable data, int action) {
    if (shouldRemove && (action == MOVE)) {
      if ((p0 != null) && (p1 != null)
          && (p0.getOffset() != p1.getOffset())) {
        try {
          JTextComponent tc = (JTextComponent) c;
          tc.getDocument().remove(p0.getOffset(),
              p1.getOffset() - p0.getOffset());
        } catch (BadLocationException e) {
          System.out.println("Can"t remove text from source.");
        }
      }
    }
    source = null;
  }
  /**
   * Does flavors contain a color or string Transferable?
   */
  public boolean canImport(JComponent c, DataFlavor[] flavors) {
    if (hasStringFlavor(flavors)) {
      return true;
    }
    return super.canImport(c, flavors);
  }
  /**
   * Does the flavor list have a string flavor?
   */
  protected boolean hasStringFlavor(DataFlavor[] flavors) {
    for (int i = 0; i < flavors.length; i++) {
      if (stringFlavor.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
}
/*
 * ColorTransferHandler.java is used by the 1.4 DragColorDemo.java and
 * DragColorTextFieldDemo examples.
 */
/**
 * An implementation of TransferHandler that adds support for dropping colors.
 * Dropping a color on a component having this TransferHandler changes the
 * foreground or the background of the component to the dropped color, according
 * to the value of the changesForegroundColor property.
 */
class ColorTransferHandler extends TransferHandler {
  //The data type exported from JColorChooser.
  String mimeType = DataFlavor.javaJVMLocalObjectMimeType
      + ";class=java.awt.Color";
  DataFlavor colorFlavor;
  private boolean changesForegroundColor = true;
  ColorTransferHandler() {
    //Try to create a DataFlavor for color.
    try {
      colorFlavor = new DataFlavor(mimeType);
    } catch (ClassNotFoundException e) {
    }
  }
  /**
   * Overridden to import a Color if it is available.
   * getChangesForegroundColor is used to determine whether the foreground or
   * the background color is changed.
   */
  public boolean importData(JComponent c, Transferable t) {
    if (hasColorFlavor(t.getTransferDataFlavors())) {
      try {
        Color col = (Color) t.getTransferData(colorFlavor);
        if (getChangesForegroundColor()) {
          c.setForeground(col);
        } else {
          c.setBackground(col);
        }
        return true;
      } catch (UnsupportedFlavorException ufe) {
        System.out.println("importData: unsupported data flavor");
      } catch (IOException ioe) {
        System.out.println("importData: I/O exception");
      }
    }
    return false;
  }
  /**
   * Does the flavor list have a Color flavor?
   */
  protected boolean hasColorFlavor(DataFlavor[] flavors) {
    if (colorFlavor == null) {
      return false;
    }
    for (int i = 0; i < flavors.length; i++) {
      if (colorFlavor.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
  /**
   * Overridden to include a check for a color flavor.
   */
  public boolean canImport(JComponent c, DataFlavor[] flavors) {
    return hasColorFlavor(flavors);
  }
  protected void setChangesForegroundColor(boolean flag) {
    changesForegroundColor = flag;
  }
  protected boolean getChangesForegroundColor() {
    return changesForegroundColor;
  }
}





Drag Drop Tree Example

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ruparator;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.plaf.basic.BasicTreeUI.TreeExpansionHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
public class DragDropTreeExample {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    final JFrame f = new JFrame("FileTree Drop and Drop Example");
    try {
      final FileTree tree = new FileTree("D:\\");
      // Add a drop target to the FileTree
      FileTreeDropTarget target = new FileTreeDropTarget(tree);
      // Add a drag source to the FileTree
      FileTreeDragSource source = new FileTreeDragSource(tree);
      tree.setEditable(true);
      f.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent evt) {
          System.exit(0);
        }
      });
      JPanel panel = new JPanel();
      final JCheckBox editable = new JCheckBox("Editable");
      editable.setSelected(true);
      panel.add(editable);
      editable.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          tree.setEditable(editable.isSelected());
        }
      });
      final JCheckBox enabled = new JCheckBox("Enabled");
      enabled.setSelected(true);
      panel.add(enabled);
      enabled.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          tree.setEnabled(enabled.isSelected());
        }
      });
      f.getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
      f.getContentPane().add(panel, BorderLayout.SOUTH);
      f.setSize(500, 400);
      f.setVisible(true);
    } catch (Exception e) {
      System.out.println("Failed to build GUI: " + e);
    }
  }
}
class FileTree extends JTree implements Autoscroll {
  public static final Insets defaultScrollInsets = new Insets(8, 8, 8, 8);
  protected Insets scrollInsets = defaultScrollInsets;
  public FileTree(String path) throws FileNotFoundException,
      SecurityException {
    super((TreeModel) null); // Create the JTree itself
    // Use horizontal and vertical lines
    putClientProperty("JTree.lineStyle", "Angled");
    // Create the first node
    FileTreeNode rootNode = new FileTreeNode(null, path);
    // Populate the root node with its subdirectories
    boolean addedNodes = rootNode.populateDirectories(true);
    setModel(new DefaultTreeModel(rootNode));
    // Listen for Tree Selection Events
    addTreeExpansionListener(new TreeExpansionHandler());
  }
  // Returns the full pathname for a path, or null if not a known path
  public String getPathName(TreePath path) {
    Object o = path.getLastPathComponent();
    if (o instanceof FileTreeNode) {
      return ((FileTreeNode) o).fullName;
    }
    return null;
  }
  // Adds a new node to the tree after construction.
  // Returns the inserted node, or null if the parent
  // directory has not been expanded.
  public FileTreeNode addNode(FileTreeNode parent, String name) {
    int index = parent.addNode(name);
    if (index != -1) {
      ((DefaultTreeModel) getModel()).nodesWereInserted(parent,
          new int[] { index });
      return (FileTreeNode) parent.getChildAt(index);
    }
    // No node was created
    return null;
  }
  // Autoscrolling support
  public void setScrollInsets(Insets insets) {
    this.scrollInsets = insets;
  }
  public Insets getScrollInsets() {
    return scrollInsets;
  }
  // Implementation of Autoscroll interface
  public Insets getAutoscrollInsets() {
    Rectangle r = getVisibleRect();
    Dimension size = getSize();
    Insets i = new Insets(r.y + scrollInsets.top, r.x + scrollInsets.left,
        size.height - r.y - r.height + scrollInsets.bottom, size.width
            - r.x - r.width + scrollInsets.right);
    return i;
  }
  public void autoscroll(Point location) {
    JScrollPane scroller = (JScrollPane) SwingUtilities.getAncestorOfClass(
        JScrollPane.class, this);
    if (scroller != null) {
      JScrollBar hBar = scroller.getHorizontalScrollBar();
      JScrollBar vBar = scroller.getVerticalScrollBar();
      Rectangle r = getVisibleRect();
      if (location.x <= r.x + scrollInsets.left) {
        // Need to scroll left
        hBar.setValue(hBar.getValue() - hBar.getUnitIncrement(-1));
      }
      if (location.y <= r.y + scrollInsets.top) {
        // Need to scroll up
        vBar.setValue(vBar.getValue() - vBar.getUnitIncrement(-1));
      }
      if (location.x >= r.x + r.width - scrollInsets.right) {
        // Need to scroll right
        hBar.setValue(hBar.getValue() + hBar.getUnitIncrement(1));
      }
      if (location.y >= r.y + r.height - scrollInsets.bottom) {
        // Need to scroll down
        vBar.setValue(vBar.getValue() + vBar.getUnitIncrement(1));
      }
    }
  }
  // Inner class that represents a node in this file system tree
  public static class FileTreeNode extends DefaultMutableTreeNode {
    public FileTreeNode(String parent, String name)
        throws SecurityException, FileNotFoundException {
      this.name = name;
      // See if this node exists and whether it is a directory
      fullName = parent == null ? name : parent + File.separator + name;
      File f = new File(fullName);
      if (f.exists() == false) {
        throw new FileNotFoundException("File " + fullName
            + " does not exist");
      }
      isDir = f.isDirectory();
      // Hack for Windows which doesn"t consider a drive to be a
      // directory!
      if (isDir == false && f.isFile() == false) {
        isDir = true;
      }
    }
    // Override isLeaf to check whether this is a directory
    public boolean isLeaf() {
      return !isDir;
    }
    // Override getAllowsChildren to check whether this is a directory
    public boolean getAllowsChildren() {
      return isDir;
    }
    // Return whether this is a directory
    public boolean isDir() {
      return isDir;
    }
    // Get full path
    public String getFullName() {
      return fullName;
    }
    // For display purposes, we return our own name
    public String toString() {
      return name;
    }
    // If we are a directory, scan our contents and populate
    // with children. In addition, populate those children
    // if the "descend" flag is true. We only descend once,
    // to avoid recursing the whole subtree.
    // Returns true if some nodes were added
    boolean populateDirectories(boolean descend) {
      boolean addedNodes = false;
      // Do this only once
      if (populated == false) {
        File f;
        try {
          f = new File(fullName);
        } catch (SecurityException e) {
          populated = true;
          return false;
        }
        if (interim == true) {
          // We have had a quick look here before:
          // remove the dummy node that we added last time
          removeAllChildren();
          interim = false;
        }
        String[] names = f.list(); // Get list of contents
        // Process the contents
        ArrayList list = new ArrayList();
        for (int i = 0; i < names.length; i++) {
          String name = names[i];
          File d = new File(fullName, name);
          try {
            FileTreeNode node = new FileTreeNode(fullName, name);
            list.add(node);
            if (descend && d.isDirectory()) {
              node.populateDirectories(false);
            }
            addedNodes = true;
            if (descend == false) {
              // Only add one node if not descending
              break;
            }
          } catch (Throwable t) {
            // Ignore phantoms or access problems
          }
        }
        if (addedNodes == true) {
          // Now sort the list of contained files and directories
          Object[] nodes = list.toArray();
          Arrays.sort(nodes, new Comparator() {
            public boolean equals(Object o) {
              return false;
            }
            public int compare(Object o1, Object o2) {
              FileTreeNode node1 = (FileTreeNode) o1;
              FileTreeNode node2 = (FileTreeNode) o2;
              // Directories come first
              if (node1.isDir != node2.isDir) {
                return node1.isDir ? -1 : +1;
              }
              // Both directories or both files -
              // compare based on pathname
              return node1.fullName.rupareTo(node2.fullName);
            }
          });
          // Add sorted items as children of this node
          for (int j = 0; j < nodes.length; j++) {
            this.add((FileTreeNode) nodes[j]);
          }
        }
        // If we were scanning to get all subdirectories,
        // or if we found no content, there is no
        // reason to look at this directory again, so
        // set populated to true. Otherwise, we set interim
        // so that we look again in the future if we need to
        if (descend == true || addedNodes == false) {
          populated = true;
        } else {
          // Just set interim state
          interim = true;
        }
      }
      return addedNodes;
    }
    // Adding a new file or directory after
    // constructing the FileTree. Returns
    // the index of the inserted node.
    public int addNode(String name) {
      // If not populated yet, do nothing
      if (populated == true) {
        // Do not add a new node if
        // the required node is already there
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
          FileTreeNode node = (FileTreeNode) getChildAt(i);
          if (node.name.equals(name)) {
            // Already exists - ensure
            // we repopulate
            if (node.isDir()) {
              node.interim = true;
              node.populated = false;
            }
            return -1;
          }
        }
        // Add a new node
        try {
          FileTreeNode node = new FileTreeNode(fullName, name);
          add(node);
          return childCount;
        } catch (Exception e) {
        }
      }
      return -1;
    }
    protected String name; // Name of this component
    protected String fullName; // Full pathname
    protected boolean populated;// true if we have been populated
    protected boolean interim; // true if we are in interim state
    protected boolean isDir; // true if this is a directory
  }
  // Inner class that handles Tree Expansion Events
  protected class TreeExpansionHandler implements TreeExpansionListener {
    public void treeExpanded(TreeExpansionEvent evt) {
      TreePath path = evt.getPath(); // The expanded path
      JTree tree = (JTree) evt.getSource(); // The tree
      // Get the last component of the path and
      // arrange to have it fully populated.
      FileTreeNode node = (FileTreeNode) path.getLastPathComponent();
      if (node.populateDirectories(true)) {
        ((DefaultTreeModel) tree.getModel()).nodeStructureChanged(node);
      }
    }
    public void treeCollapsed(TreeExpansionEvent evt) {
      // Nothing to do
    }
  }
}
class FileTreeDropTarget implements DropTargetListener, PropertyChangeListener {
  public FileTreeDropTarget(FileTree tree) {
    this.tree = tree;
    // Listen for changes in the enabled property
    tree.addPropertyChangeListener(this);
    // Create the DropTarget and register
    // it with the FileTree.
    dropTarget = new DropTarget(tree, DnDConstants.ACTION_COPY_OR_MOVE,
        this, tree.isEnabled(), null);
  }
  // Implementation of the DropTargetListener interface
  public void dragEnter(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("dragEnter, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Save the list of selected items
    saveTreeSelection();
    // Get the type of object being transferred and determine
    // whether it is appropriate.
    checkTransferType(dtde);
    // Accept or reject the drag.
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void dragExit(DropTargetEvent dte) {
    DnDUtils.debugPrintln("DropTarget dragExit");
    // Do drag-under feedback
    dragUnderFeedback(null, false);
    // Restore the original selections
    restoreTreeSelection();
  }
  public void dragOver(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dragOver, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dropActionChanged, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void drop(DropTargetDropEvent dtde) {
    DnDUtils.debugPrintln("DropTarget drop, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Check the drop action
    if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
      // Accept the drop and get the transfer data
      dtde.acceptDrop(dtde.getDropAction());
      Transferable transferable = dtde.getTransferable();
      boolean dropSucceeded = false;
      try {
        tree.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        // Save the user"s selections
        saveTreeSelection();
        dropSucceeded = dropFile(dtde.getDropAction(), transferable,
            dtde.getLocation());
        DnDUtils.debugPrintln("Drop completed, success: "
            + dropSucceeded);
      } catch (Exception e) {
        DnDUtils.debugPrintln("Exception while handling drop " + e);
      } finally {
        tree.setCursor(Cursor.getDefaultCursor());
        // Restore the user"s selections
        restoreTreeSelection();
        dtde.dropComplete(dropSucceeded);
      }
    } else {
      DnDUtils.debugPrintln("Drop target rejected drop");
      dtde.dropComplete(false);
    }
  }
  // PropertyChangeListener interface
  public void propertyChange(PropertyChangeEvent evt) {
    String propertyName = evt.getPropertyName();
    if (propertyName.equals("enabled")) {
      // Enable the drop target if the FileTree is enabled
      // and vice versa.
      dropTarget.setActive(tree.isEnabled());
    }
  }
  // Internal methods start here
  protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
    int dropAction = dtde.getDropAction();
    int sourceActions = dtde.getSourceActions();
    boolean acceptedDrag = false;
    DnDUtils.debugPrintln("\tSource actions are "
        + DnDUtils.showActions(sourceActions) + ", drop action is "
        + DnDUtils.showActions(dropAction));
    Point location = dtde.getLocation();
    boolean acceptableDropLocation = isAcceptableDropLocation(location);
    // Reject if the object being transferred
    // or the operations available are not acceptable.
    if (!acceptableType
        || (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if (!tree.isEditable()) {
      // Can"t drag to a read-only FileTree
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if (!acceptableDropLocation) {
      // Can only drag to writable directory
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      // Not offering copy or move - suggest a copy
      DnDUtils.debugPrintln("Drop target offering COPY");
      dtde.acceptDrag(DnDConstants.ACTION_COPY);
      acceptedDrag = true;
    } else {
      // Offering an acceptable operation: accept
      DnDUtils.debugPrintln("Drop target accepting drag");
      dtde.acceptDrag(dropAction);
      acceptedDrag = true;
    }
    return acceptedDrag;
  }
  protected void dragUnderFeedback(DropTargetDragEvent dtde,
      boolean acceptedDrag) {
    if (dtde != null && acceptedDrag) {
      Point location = dtde.getLocation();
      if (isAcceptableDropLocation(location)) {
        tree.setSelectionRow(tree.getRowForLocation(location.x,
            location.y));
      } else {
        tree.clearSelection();
      }
    } else {
      tree.clearSelection();
    }
  }
  protected void checkTransferType(DropTargetDragEvent dtde) {
    // Accept a list of files
    acceptableType = false;
    if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      acceptableType = true;
    }
    DnDUtils.debugPrintln("Data type acceptable - " + acceptableType);
  }
  // This method handles a drop for a list of files
  protected boolean dropFile(int action, Transferable transferable,
      Point location) throws IOException, UnsupportedFlavorException,
      MalformedURLException {
    List files = (List) transferable
        .getTransferData(DataFlavor.javaFileListFlavor);
    TreePath treePath = tree.getPathForLocation(location.x, location.y);
    File targetDirectory = findTargetDirectory(location);
    if (treePath == null || targetDirectory == null) {
      return false;
    }
    FileTree.FileTreeNode node = (FileTree.FileTreeNode) treePath
        .getLastPathComponent();
    // Highlight the drop location while we perform the drop
    tree.setSelectionPath(treePath);
    // Get File objects for all files being
    // transferred, eliminating duplicates.
    File[] fileList = getFileList(files);
    // Don"t overwrite files by default
    copyOverExistingFiles = false;
    // Copy or move each source object to the target
    for (int i = 0; i < fileList.length; i++) {
      File f = fileList[i];
      if (f.isDirectory()) {
        transferDirectory(action, f, targetDirectory, node);
      } else {
        try {
          transferFile(action, fileList[i], targetDirectory, node);
        } catch (IllegalStateException e) {
          // Cancelled by user
          return false;
        }
      }
    }
    return true;
  }
  protected File findTargetDirectory(Point location) {
    TreePath treePath = tree.getPathForLocation(location.x, location.y);
    if (treePath != null) {
      FileTree.FileTreeNode node = (FileTree.FileTreeNode) treePath
          .getLastPathComponent();
      // Only allow a drop on a writable directory
      if (node.isDir()) {
        try {
          File f = new File(node.getFullName());
          if (f.canWrite()) {
            return f;
          }
        } catch (Exception e) {
        }
      }
    }
    return null;
  }
  protected boolean isAcceptableDropLocation(Point location) {
    return findTargetDirectory(location) != null;
  }
  protected void saveTreeSelection() {
    selections = tree.getSelectionPaths();
    leadSelection = tree.getLeadSelectionPath();
    tree.clearSelection();
  }
  protected void restoreTreeSelection() {
    tree.setSelectionPaths(selections);
    // Restore the lead selection
    if (leadSelection != null) {
      tree.removeSelectionPath(leadSelection);
      tree.addSelectionPath(leadSelection);
    }
  }
  // Get the list of files being transferred and
  // remove any duplicates. For example, if the
  // list contains /a/b/c and /a/b/c/d, the
  // second entry is removed.
  protected File[] getFileList(List files) {
    int size = files.size();
    // Get the files into an array for sorting
    File[] f = new File[size];
    Iterator iter = files.iterator();
    int count = 0;
    while (iter.hasNext()) {
      f[count++] = (File) iter.next();
    }
    // Sort the files into alphabetical order
    // based on pathnames.
    Arrays.sort(f, new Comparator() {
      public boolean equals(Object o1) {
        return false;
      }
      public int compare(Object o1, Object o2) {
        return ((File) o1).getAbsolutePath().rupareTo(
            ((File) o2).getAbsolutePath());
      }
    });
    // Remove duplicates, retaining the results in a Vector
    Vector v = new Vector();
    char separator = System.getProperty("file.separator").charAt(0);
    outer: for (int i = f.length - 1; i >= 0; i--) {
      String secondPath = f[i].getAbsolutePath();
      int secondLength = secondPath.length();
      for (int j = i - 1; j >= 0; j--) {
        String firstPath = f[j].getAbsolutePath();
        int firstLength = firstPath.length();
        if (secondPath.startsWith(firstPath)
            && firstLength != secondLength
            && secondPath.charAt(firstLength) == separator) {
          continue outer;
        }
      }
      v.add(f[i]);
    }
    // Copy the retained files into an array
    f = new File[v.size()];
    v.copyInto(f);
    return f;
  }
  // Copy or move a file
  protected void transferFile(int action, File srcFile, File targetDirectory,
      FileTree.FileTreeNode targetNode) {
    DnDUtils.debugPrintln((action == DnDConstants.ACTION_COPY ? "Copy"
        : "Move")
        + " file "
        + srcFile.getAbsolutePath()
        + " to "
        + targetDirectory.getAbsolutePath());
    // Create a File entry for the target
    String name = srcFile.getName();
    File newFile = new File(targetDirectory, name);
    if (newFile.exists()) {
      // Already exists - is it the same file?
      if (newFile.equals(srcFile)) {
        // Exactly the same file - ignore
        return;
      }
      // File of this name exists in this directory
      if (copyOverExistingFiles == false) {
        int res = JOptionPane.showOptionDialog(tree,
            "A file called\n   " + name
                + "\nalready exists in the directory\n   "
                + targetDirectory.getAbsolutePath()
                + "\nOverwrite it?", "File Exists",
            JOptionPane.DEFAULT_OPTION,
            JOptionPane.QUESTION_MESSAGE, null, new String[] {
                "Yes", "Yes to All", "No", "Cancel" }, "No");
        switch (res) {
        case 1: // Yes to all
          copyOverExistingFiles = true;
        case 0: // Yes
          break;
        case 2: // No
          return;
        default: // Cancel
          throw new IllegalStateException("Cancelled");
        }
      }
    } else {
      // New file - create it
      try {
        newFile.createNewFile();
      } catch (IOException e) {
        JOptionPane.showMessageDialog(tree,
            "Failed to create new file\n  "
                + newFile.getAbsolutePath(),
            "File Creation Failed", JOptionPane.ERROR_MESSAGE);
        return;
      }
    }
    // Copy the data and close file.
    BufferedInputStream is = null;
    BufferedOutputStream os = null;
    try {
      is = new BufferedInputStream(new FileInputStream(srcFile));
      os = new BufferedOutputStream(new FileOutputStream(newFile));
      int size = 4096;
      byte[] buffer = new byte[size];
      int len;
      while ((len = is.read(buffer, 0, size)) > 0) {
        os.write(buffer, 0, len);
      }
    } catch (IOException e) {
      JOptionPane.showMessageDialog(tree, "Failed to copy file\n  "
          + name + "\nto directory\n  "
          + targetDirectory.getAbsolutePath(), "File Copy Failed",
          JOptionPane.ERROR_MESSAGE);
      return;
    } finally {
      try {
        if (is != null) {
          is.close();
        }
        if (os != null) {
          os.close();
        }
      } catch (IOException e) {
      }
    }
    // Remove the source if this is a move operation.
    if (action == DnDConstants.ACTION_MOVE
        && System.getProperty("DnDExamples.allowRemove") != null) {
      srcFile.delete();
    }
    // Update the tree display
    if (targetNode != null) {
      tree.addNode(targetNode, name);
    }
  }
  protected void transferDirectory(int action, File srcDir,
      File targetDirectory, FileTree.FileTreeNode targetNode) {
    DnDUtils.debugPrintln((action == DnDConstants.ACTION_COPY ? "Copy"
        : "Move")
        + " directory "
        + srcDir.getAbsolutePath()
        + " to "
        + targetDirectory.getAbsolutePath());
    // Do not copy a directory into itself or
    // a subdirectory of itself.
    File parentDir = targetDirectory;
    while (parentDir != null) {
      if (parentDir.equals(srcDir)) {
        DnDUtils.debugPrintln("-- SUPPRESSED");
        return;
      }
      parentDir = parentDir.getParentFile();
    }
    // Copy the directory itself, then its contents
    // Create a File entry for the target
    String name = srcDir.getName();
    File newDir = new File(targetDirectory, name);
    if (newDir.exists()) {
      // Already exists - is it the same directory?
      if (newDir.equals(srcDir)) {
        // Exactly the same file - ignore
        return;
      }
    } else {
      // Directory does not exist - create it
      if (newDir.mkdir() == false) {
        // Failed to create - abandon this directory
        JOptionPane.showMessageDialog(tree,
            "Failed to create target directory\n  "
                + newDir.getAbsolutePath(),
            "Directory creation Failed", JOptionPane.ERROR_MESSAGE);
        return;
      }
    }
    // Add a node for the new directory
    if (targetNode != null) {
      targetNode = tree.addNode(targetNode, name);
    }
    // Now copy the directory content.
    File[] files = srcDir.listFiles();
    for (int i = 0; i < files.length; i++) {
      File f = files[i];
      if (f.isFile()) {
        transferFile(action, f, newDir, targetNode);
      } else if (f.isDirectory()) {
        transferDirectory(action, f, newDir, targetNode);
      }
    }
    // Remove the source directory after moving
    if (action == DnDConstants.ACTION_MOVE
        && System.getProperty("DnDExamples.allowRemove") != null) {
      srcDir.delete();
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    final JFrame f = new JFrame("FileTree Drop Target Example");
    try {
      final FileTree tree = new FileTree("D:\\");
      // Add a drop target to the FileTree
      FileTreeDropTarget target = new FileTreeDropTarget(tree);
      tree.setEditable(true);
      f.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent evt) {
          System.exit(0);
        }
      });
      JPanel panel = new JPanel();
      final JCheckBox editable = new JCheckBox("Editable");
      editable.setSelected(true);
      panel.add(editable);
      editable.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          tree.setEditable(editable.isSelected());
        }
      });
      final JCheckBox enabled = new JCheckBox("Enabled");
      enabled.setSelected(true);
      panel.add(enabled);
      enabled.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          tree.setEnabled(enabled.isSelected());
        }
      });
      f.getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
      f.getContentPane().add(panel, BorderLayout.SOUTH);
      f.setSize(500, 400);
      f.setVisible(true);
    } catch (Exception e) {
      System.out.println("Failed to build GUI: " + e);
    }
  }
  protected FileTree tree;
  protected DropTarget dropTarget;
  protected boolean acceptableType; // Indicates whether data is acceptable
  TreePath[] selections; // Initially selected rows
  TreePath leadSelection; // Initial lead selection
  boolean copyOverExistingFiles;
}

class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK | DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = (System
      .getProperty("DnDExamples.debug") != null);
}
class FileTreeDragSource implements DragGestureListener, DragSourceListener {
  public FileTreeDragSource(FileTree tree) {
    this.tree = tree;
    // Use the default DragSource
    DragSource dragSource = DragSource.getDefaultDragSource();
    // Create a DragGestureRecognizer and
    // register as the listener
    dragSource.createDefaultDragGestureRecognizer(tree,
        DnDConstants.ACTION_COPY_OR_MOVE, this);
  }
  // Implementation of DragGestureListener interface.
  public void dragGestureRecognized(DragGestureEvent dge) {
    // Get the mouse location and convert it to
    // a location within the tree.
    Point location = dge.getDragOrigin();
    TreePath dragPath = tree.getPathForLocation(location.x, location.y);
    if (dragPath != null && tree.isPathSelected(dragPath)) {
      // Get the list of selected files and create a Transferable
      // The list of files and the is saved for use when
      // the drop completes.
      paths = tree.getSelectionPaths();
      if (paths != null && paths.length > 0) {
        dragFiles = new File[paths.length];
        for (int i = 0; i < paths.length; i++) {
          String pathName = tree.getPathName(paths[i]);
          dragFiles[i] = new File(pathName);
        }
        Transferable transferable = new FileListTransferable(dragFiles);
        dge.startDrag(null, transferable, this);
      }
    }
  }
  // Implementation of DragSourceListener interface
  public void dragEnter(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dragEnter, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragOver(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dragOver, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragExit(DragSourceEvent dse) {
    DnDUtils.debugPrintln("Drag Source: dragExit");
  }
  public void dropActionChanged(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dropActionChanged, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragDropEnd(DragSourceDropEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: drop completed, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()) + ", success: "
        + dsde.getDropSuccess());
    // If the drop action was ACTION_MOVE,
    // the tree might need to be updated.
    if (dsde.getDropAction() == DnDConstants.ACTION_MOVE) {
      final File[] draggedFiles = dragFiles;
      final TreePath[] draggedPaths = paths;
      Timer tm = new Timer(200, new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          // Check whether each of the dragged files exists.
          // If it does not, we need to remove the node
          // that represents it from the tree.
          for (int i = 0; i < draggedFiles.length; i++) {
            if (draggedFiles[i].exists() == false) {
              // Remove this node
              DefaultMutableTreeNode node = (DefaultMutableTreeNode) draggedPaths[i]
                  .getLastPathComponent();
              ((DefaultTreeModel) tree.getModel())
                  .removeNodeFromParent(node);
            }
          }
        }
      });
      tm.setRepeats(false);
      tm.start();
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Draggable File Tree");
    try {
      FileTree tree = new FileTree("D:\\");
      f.getContentPane().add(new JScrollPane(tree));
      // Attach the drag source
      FileTreeDragSource dragSource = new FileTreeDragSource(tree);
    } catch (Exception e) {
    }
    f.pack();
    f.setVisible(true);
  }
  protected FileTree tree; // The associated tree
  protected File[] dragFiles; // Dragged files
  protected TreePath[] paths; // Dragged paths
}

class FileListTransferable implements Transferable {
  public FileListTransferable(File[] files) {
    fileList = new ArrayList();
    for (int i = 0; i < files.length; i++) {
      fileList.add(files[i]);
    }
  }
  // Implementation of the Transferable interface
  public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[] { DataFlavor.javaFileListFlavor };
  }
  public boolean isDataFlavorSupported(DataFlavor fl) {
    return fl.equals(DataFlavor.javaFileListFlavor);
  }
  public Object getTransferData(DataFlavor fl) {
    if (!isDataFlavorSupported(fl)) {
      return null;
    }
    return fileList;
  }
  List fileList; // The list of files
}





Drag File Demo

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * DragFileDemo.java is a 1.4 example that requires the following file:
 * FileAndTextTransferHandler.java TabbedPaneController.java
 */
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.TransferHandler;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.Position;
public class DragFileDemo extends JPanel implements ActionListener {
  JTextArea fileArea;
  JFileChooser fc;
  JButton clear;
  TabbedPaneController tpc;
  public DragFileDemo() {
    super(new BorderLayout());
    fc = new JFileChooser();
    ;
    fc.setMultiSelectionEnabled(true);
    fc.setDragEnabled(true);
    fc.setControlButtonsAreShown(false);
    JPanel fcPanel = new JPanel(new BorderLayout());
    fcPanel.add(fc, BorderLayout.CENTER);
    clear = new JButton("Clear All");
    clear.addActionListener(this);
    JPanel buttonPanel = new JPanel(new BorderLayout());
    buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    buttonPanel.add(clear, BorderLayout.LINE_END);
    JPanel upperPanel = new JPanel(new BorderLayout());
    upperPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    upperPanel.add(fcPanel, BorderLayout.CENTER);
    upperPanel.add(buttonPanel, BorderLayout.PAGE_END);
    //The TabbedPaneController manages the panel that
    //contains the tabbed pane. When there are no files
    //the panel contains a plain text area. Then, as
    //files are dropped onto the area, the tabbed panel
    //replaces the file area.
    JTabbedPane tabbedPane = new JTabbedPane();
    JPanel tabPanel = new JPanel(new BorderLayout());
    tabPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    tpc = new TabbedPaneController(tabbedPane, tabPanel);
    JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
        upperPanel, tabPanel);
    splitPane.setDividerLocation(400);
    splitPane.setPreferredSize(new Dimension(530, 650));
    add(splitPane, BorderLayout.CENTER);
  }
  public void setDefaultButton() {
    getRootPane().setDefaultButton(clear);
  }
  public void actionPerformed(ActionEvent e) {
    if (e.getSource() == clear) {
      tpc.clearAll();
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("DragFileDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the menu bar and content pane.
    DragFileDemo demo = new DragFileDemo();
    demo.setOpaque(true); //content panes must be opaque
    frame.setContentPane(demo);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
    demo.setDefaultButton();
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
/*
 * TabbedPaneController.java is used by the 1.4 DragFileDemo.java example.
 */
/*
 * Class that manages area where the contents of files are displayed. When no
 * files are present, there is a simple JTextArea instructing users to drop a
 * file. As soon as a file is dropped, a JTabbedPane is placed into the window
 * and each file is displayed under its own tab. When all the files are removed,
 * the JTabbedPane is removed from the window and the simple JTextArea is again
 * displayed.
 */
class TabbedPaneController {
  JPanel tabbedPanel = null;
  JTabbedPane tabbedPane;
  JPanel emptyFilePanel = null;
  JTextArea emptyFileArea = null;
  FileAndTextTransferHandler transferHandler;
  boolean noFiles = true;
  String fileSeparator;
  public TabbedPaneController(JTabbedPane tb, JPanel tp) {
    tabbedPane = tb;
    tabbedPanel = tp;
    transferHandler = new FileAndTextTransferHandler(this);
    fileSeparator = System.getProperty("file.separator");
    //The split method in the String class uses
    //regular expressions to define the text used for
    //the split. The forward slash "\" is a special
    //character and must be escaped. Some look and feels,
    //such as Microsoft Windows, use the forward slash to
    //delimit the path.
    if ("\\".equals(fileSeparator)) {
      fileSeparator = "\\\\";
    }
    init();
  }
  public JTextArea addTab(String filename) {
    if (noFiles) {
      tabbedPanel.remove(emptyFilePanel);
      tabbedPanel.add(tabbedPane, BorderLayout.CENTER);
      noFiles = false;
    }
    String[] str = filename.split(fileSeparator);
    return makeTextPanel(str[str.length - 1], filename);
  }
  //Remove all tabs and their components, then put the default
  //file area back.
  public void clearAll() {
    if (noFiles == false) {
      tabbedPane.removeAll();
      tabbedPanel.remove(tabbedPane);
    }
    init();
  }
  private void init() {
    String defaultText = "Select one or more files from the file chooser and drop here...";
    noFiles = true;
    if (emptyFilePanel == null) {
      emptyFileArea = new JTextArea(20, 15);
      emptyFileArea.setEditable(false);
      emptyFileArea.setDragEnabled(true);
      emptyFileArea.setTransferHandler(transferHandler);
      emptyFileArea.setMargin(new Insets(5, 5, 5, 5));
      JScrollPane fileScrollPane = new JScrollPane(emptyFileArea);
      emptyFilePanel = new JPanel(new BorderLayout(), false);
      emptyFilePanel.add(fileScrollPane, BorderLayout.CENTER);
    }
    tabbedPanel.add(emptyFilePanel, BorderLayout.CENTER);
    tabbedPanel.repaint();
    emptyFileArea.setText(defaultText);
  }
  protected JTextArea makeTextPanel(String name, String toolTip) {
    JTextArea fileArea = new JTextArea(20, 15);
    fileArea.setDragEnabled(true);
    fileArea.setTransferHandler(transferHandler);
    fileArea.setMargin(new Insets(5, 5, 5, 5));
    JScrollPane fileScrollPane = new JScrollPane(fileArea);
    tabbedPane.addTab(name, null, (Component) fileScrollPane, toolTip);
    tabbedPane.setSelectedComponent((Component) fileScrollPane);
    return fileArea;
  }
}
/*
 * FileAndTextTransferHandler.java is used by the 1.4 DragFileDemo.java example.
 */
class FileAndTextTransferHandler extends TransferHandler {
  private DataFlavor fileFlavor, stringFlavor;
  private TabbedPaneController tpc;
  private JTextArea source;
  private boolean shouldRemove;
  protected String newline = "\n";
  //Start and end position in the source text.
  //We need this information when performing a MOVE
  //in order to remove the dragged text from the source.
  Position p0 = null, p1 = null;
  FileAndTextTransferHandler(TabbedPaneController t) {
    tpc = t;
    fileFlavor = DataFlavor.javaFileListFlavor;
    stringFlavor = DataFlavor.stringFlavor;
  }
  public boolean importData(JComponent c, Transferable t) {
    JTextArea tc;
    if (!canImport(c, t.getTransferDataFlavors())) {
      return false;
    }
    //A real application would load the file in another
    //thread in order to not block the UI. This step
    //was omitted here to simplify the code.
    try {
      if (hasFileFlavor(t.getTransferDataFlavors())) {
        String str = null;
        java.util.List files = (java.util.List) t
            .getTransferData(fileFlavor);
        for (int i = 0; i < files.size(); i++) {
          File file = (File) files.get(i);
          //Tell the tabbedpane controller to add
          //a new tab with the name of this file
          //on the tab. The text area that will
          //display the contents of the file is returned.
          tc = tpc.addTab(file.toString());
          BufferedReader in = null;
          try {
            in = new BufferedReader(new FileReader(file));
            while ((str = in.readLine()) != null) {
              tc.append(str + newline);
            }
          } catch (IOException ioe) {
            System.out
                .println("importData: Unable to read from file "
                    + file.toString());
          } finally {
            if (in != null) {
              try {
                in.close();
              } catch (IOException ioe) {
                System.out
                    .println("importData: Unable to close file "
                        + file.toString());
              }
            }
          }
        }
        return true;
      } else if (hasStringFlavor(t.getTransferDataFlavors())) {
        tc = (JTextArea) c;
        if (tc.equals(source)
            && (tc.getCaretPosition() >= p0.getOffset())
            && (tc.getCaretPosition() <= p1.getOffset())) {
          shouldRemove = false;
          return true;
        }
        String str = (String) t.getTransferData(stringFlavor);
        tc.replaceSelection(str);
        return true;
      }
    } catch (UnsupportedFlavorException ufe) {
      System.out.println("importData: unsupported data flavor");
    } catch (IOException ieo) {
      System.out.println("importData: I/O exception");
    }
    return false;
  }
  protected Transferable createTransferable(JComponent c) {
    source = (JTextArea) c;
    int start = source.getSelectionStart();
    int end = source.getSelectionEnd();
    Document doc = source.getDocument();
    if (start == end) {
      return null;
    }
    try {
      p0 = doc.createPosition(start);
      p1 = doc.createPosition(end);
    } catch (BadLocationException e) {
      System.out
          .println("Can"t create position - unable to remove text from source.");
    }
    shouldRemove = true;
    String data = source.getSelectedText();
    return new StringSelection(data);
  }
  public int getSourceActions(JComponent c) {
    return COPY_OR_MOVE;
  }
  //Remove the old text if the action is a MOVE.
  //However, we do not allow dropping on top of the selected text,
  //so in that case do nothing.
  protected void exportDone(JComponent c, Transferable data, int action) {
    if (shouldRemove && (action == MOVE)) {
      if ((p0 != null) && (p1 != null)
          && (p0.getOffset() != p1.getOffset())) {
        try {
          JTextComponent tc = (JTextComponent) c;
          tc.getDocument().remove(p0.getOffset(),
              p1.getOffset() - p0.getOffset());
        } catch (BadLocationException e) {
          System.out.println("Can"t remove text from source.");
        }
      }
    }
    source = null;
  }
  public boolean canImport(JComponent c, DataFlavor[] flavors) {
    if (hasFileFlavor(flavors)) {
      return true;
    }
    if (hasStringFlavor(flavors)) {
      return true;
    }
    return false;
  }
  private boolean hasFileFlavor(DataFlavor[] flavors) {
    for (int i = 0; i < flavors.length; i++) {
      if (fileFlavor.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
  private boolean hasStringFlavor(DataFlavor[] flavors) {
    for (int i = 0; i < flavors.length; i++) {
      if (stringFlavor.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
}





Drag List Demo

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * DragListDemo.java is a 1.4 example that requires the following file:
 * ArrayListTransferHandler.java
 */
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
public class DragListDemo extends JPanel {
  ArrayListTransferHandler arrayListHandler;
  public DragListDemo() {
    arrayListHandler = new ArrayListTransferHandler();
    JList list1, list2;
    DefaultListModel list1Model = new DefaultListModel();
    list1Model.addElement("0 (list 1)");
    list1Model.addElement("1 (list 1)");
    list1Model.addElement("2 (list 1)");
    list1Model.addElement("3 (list 1)");
    list1Model.addElement("4 (list 1)");
    list1Model.addElement("5 (list 1)");
    list1Model.addElement("6 (list 1)");
    list1 = new JList(list1Model);
    list1.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    list1.setTransferHandler(arrayListHandler);
    list1.setDragEnabled(true);
    JScrollPane list1View = new JScrollPane(list1);
    list1View.setPreferredSize(new Dimension(200, 100));
    JPanel panel1 = new JPanel();
    panel1.setLayout(new BorderLayout());
    panel1.add(list1View, BorderLayout.CENTER);
    panel1.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    DefaultListModel list2Model = new DefaultListModel();
    list2Model.addElement("0 (list 2)");
    list2Model.addElement("1 (list 2)");
    list2Model.addElement("2 (list 2)");
    list2Model.addElement("3 (list 2)");
    list2Model.addElement("4 (list 2)");
    list2Model.addElement("5 (list 2)");
    list2Model.addElement("6 (list 2)");
    list2 = new JList(list2Model);
    list2.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    list2.setTransferHandler(arrayListHandler);
    list2.setDragEnabled(true);
    JScrollPane list2View = new JScrollPane(list2);
    list2View.setPreferredSize(new Dimension(200, 100));
    JPanel panel2 = new JPanel();
    panel2.setLayout(new BorderLayout());
    panel2.add(list2View, BorderLayout.CENTER);
    panel2.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    setLayout(new BorderLayout());
    add(panel1, BorderLayout.LINE_START);
    add(panel2, BorderLayout.LINE_END);
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("DragListDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    DragListDemo demo = new DragListDemo();
    frame.setContentPane(demo);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
/*
 * ArrayListTransferHandler.java is used by the 1.4 DragListDemo.java example.
 */
class ArrayListTransferHandler extends TransferHandler {
  DataFlavor localArrayListFlavor, serialArrayListFlavor;
  String localArrayListType = DataFlavor.javaJVMLocalObjectMimeType
      + ";class=java.util.ArrayList";
  JList source = null;
  int[] indices = null;
  int addIndex = -1; //Location where items were added
  int addCount = 0; //Number of items added
  public ArrayListTransferHandler() {
    try {
      localArrayListFlavor = new DataFlavor(localArrayListType);
    } catch (ClassNotFoundException e) {
      System.out
          .println("ArrayListTransferHandler: unable to create data flavor");
    }
    serialArrayListFlavor = new DataFlavor(ArrayList.class, "ArrayList");
  }
  public boolean importData(JComponent c, Transferable t) {
    JList target = null;
    ArrayList alist = null;
    if (!canImport(c, t.getTransferDataFlavors())) {
      return false;
    }
    try {
      target = (JList) c;
      if (hasLocalArrayListFlavor(t.getTransferDataFlavors())) {
        alist = (ArrayList) t.getTransferData(localArrayListFlavor);
      } else if (hasSerialArrayListFlavor(t.getTransferDataFlavors())) {
        alist = (ArrayList) t.getTransferData(serialArrayListFlavor);
      } else {
        return false;
      }
    } catch (UnsupportedFlavorException ufe) {
      System.out.println("importData: unsupported data flavor");
      return false;
    } catch (IOException ioe) {
      System.out.println("importData: I/O exception");
      return false;
    }
    //At this point we use the same code to retrieve the data
    //locally or serially.
    //We"ll drop at the current selected index.
    int index = target.getSelectedIndex();
    //Prevent the user from dropping data back on itself.
    //For example, if the user is moving items #4,#5,#6 and #7 and
    //attempts to insert the items after item #5, this would
    //be problematic when removing the original items.
    //This is interpreted as dropping the same data on itself
    //and has no effect.
    if (source.equals(target)) {
      if (indices != null && index >= indices[0] - 1
          && index <= indices[indices.length - 1]) {
        indices = null;
        return true;
      }
    }
    DefaultListModel listModel = (DefaultListModel) target.getModel();
    int max = listModel.getSize();
    if (index < 0) {
      index = max;
    } else {
      index++;
      if (index > max) {
        index = max;
      }
    }
    addIndex = index;
    addCount = alist.size();
    for (int i = 0; i < alist.size(); i++) {
      listModel.add(index++, alist.get(i));
    }
    return true;
  }
  protected void exportDone(JComponent c, Transferable data, int action) {
    if ((action == MOVE) && (indices != null)) {
      DefaultListModel model = (DefaultListModel) source.getModel();
      //If we are moving items around in the same list, we
      //need to adjust the indices accordingly since those
      //after the insertion point have moved.
      if (addCount > 0) {
        for (int i = 0; i < indices.length; i++) {
          if (indices[i] > addIndex) {
            indices[i] += addCount;
          }
        }
      }
      for (int i = indices.length - 1; i >= 0; i--)
        model.remove(indices[i]);
    }
    indices = null;
    addIndex = -1;
    addCount = 0;
  }
  private boolean hasLocalArrayListFlavor(DataFlavor[] flavors) {
    if (localArrayListFlavor == null) {
      return false;
    }
    for (int i = 0; i < flavors.length; i++) {
      if (flavors[i].equals(localArrayListFlavor)) {
        return true;
      }
    }
    return false;
  }
  private boolean hasSerialArrayListFlavor(DataFlavor[] flavors) {
    if (serialArrayListFlavor == null) {
      return false;
    }
    for (int i = 0; i < flavors.length; i++) {
      if (flavors[i].equals(serialArrayListFlavor)) {
        return true;
      }
    }
    return false;
  }
  public boolean canImport(JComponent c, DataFlavor[] flavors) {
    if (hasLocalArrayListFlavor(flavors)) {
      return true;
    }
    if (hasSerialArrayListFlavor(flavors)) {
      return true;
    }
    return false;
  }
  protected Transferable createTransferable(JComponent c) {
    if (c instanceof JList) {
      source = (JList) c;
      indices = source.getSelectedIndices();
      Object[] values = source.getSelectedValues();
      if (values == null || values.length == 0) {
        return null;
      }
      ArrayList alist = new ArrayList(values.length);
      for (int i = 0; i < values.length; i++) {
        Object o = values[i];
        String str = o.toString();
        if (str == null)
          str = "";
        alist.add(str);
      }
      return new ArrayListTransferable(alist);
    }
    return null;
  }
  public int getSourceActions(JComponent c) {
    return COPY_OR_MOVE;
  }
  public class ArrayListTransferable implements Transferable {
    ArrayList data;
    public ArrayListTransferable(ArrayList alist) {
      data = alist;
    }
    public Object getTransferData(DataFlavor flavor)
        throws UnsupportedFlavorException {
      if (!isDataFlavorSupported(flavor)) {
        throw new UnsupportedFlavorException(flavor);
      }
      return data;
    }
    public DataFlavor[] getTransferDataFlavors() {
      return new DataFlavor[] { localArrayListFlavor,
          serialArrayListFlavor };
    }
    public boolean isDataFlavorSupported(DataFlavor flavor) {
      if (localArrayListFlavor.equals(flavor)) {
        return true;
      }
      if (serialArrayListFlavor.equals(flavor)) {
        return true;
      }
      return false;
    }
  }
}





Drag Picture Demo

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * DragPictureDemo.java is a 1.4 example that requires the following files:
 * Picture.java DTPicture.java PictureTransferHandler.java images/Maya.jpg
 * images/Anya.jpg images/Laine.jpg images/Cosmo.jpg images/Adele.jpg
 * images/Alexi.jpg
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.IOException;
import javax.accessibility.Accessible;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.TransferHandler;
public class DragPictureDemo extends JPanel {
  DTPicture pic1, pic2, pic3, pic4, pic5, pic6, pic7, pic8, pic9, pic10,
      pic11, pic12;
  static String mayaString = "Maya";
  static String anyaString = "Anya";
  static String laineString = "Laine";
  static String cosmoString = "Cosmo";
  static String adeleString = "Adele";
  static String alexiString = "Alexi";
  PictureTransferHandler picHandler;
  public DragPictureDemo() {
    super(new BorderLayout());
    picHandler = new PictureTransferHandler();
    JPanel mugshots = new JPanel(new GridLayout(4, 3));
    pic1 = new DTPicture(createImageIcon("images/" + mayaString + ".jpg",
        mayaString).getImage());
    pic1.setTransferHandler(picHandler);
    mugshots.add(pic1);
    pic2 = new DTPicture(createImageIcon("images/" + anyaString + ".jpg",
        anyaString).getImage());
    pic2.setTransferHandler(picHandler);
    mugshots.add(pic2);
    pic3 = new DTPicture(createImageIcon("images/" + laineString + ".jpg",
        laineString).getImage());
    pic3.setTransferHandler(picHandler);
    mugshots.add(pic3);
    pic4 = new DTPicture(createImageIcon("images/" + cosmoString + ".jpg",
        cosmoString).getImage());
    pic4.setTransferHandler(picHandler);
    mugshots.add(pic4);
    pic5 = new DTPicture(createImageIcon("images/" + adeleString + ".jpg",
        adeleString).getImage());
    pic5.setTransferHandler(picHandler);
    mugshots.add(pic5);
    pic6 = new DTPicture(createImageIcon("images/" + alexiString + ".jpg",
        alexiString).getImage());
    pic6.setTransferHandler(picHandler);
    mugshots.add(pic6);
    //These six components with no pictures provide handy
    //drop targets.
    pic7 = new DTPicture(null);
    pic7.setTransferHandler(picHandler);
    mugshots.add(pic7);
    pic8 = new DTPicture(null);
    pic8.setTransferHandler(picHandler);
    mugshots.add(pic8);
    pic9 = new DTPicture(null);
    pic9.setTransferHandler(picHandler);
    mugshots.add(pic9);
    pic10 = new DTPicture(null);
    pic10.setTransferHandler(picHandler);
    mugshots.add(pic10);
    pic11 = new DTPicture(null);
    pic11.setTransferHandler(picHandler);
    mugshots.add(pic11);
    pic12 = new DTPicture(null);
    pic12.setTransferHandler(picHandler);
    mugshots.add(pic12);
    setPreferredSize(new Dimension(450, 630));
    add(mugshots, BorderLayout.CENTER);
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }
  /** Returns an ImageIcon, or null if the path was invalid. */
  protected static ImageIcon createImageIcon(String path, String description) {
    java.net.URL imageURL = DragPictureDemo.class.getResource(path);
    if (imageURL == null) {
      System.err.println("Resource not found: " + path);
      return null;
    } else {
      return new ImageIcon(imageURL, description);
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("DragPictureDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the menu bar and content pane.
    DragPictureDemo demo = new DragPictureDemo();
    demo.setOpaque(true); //content panes must be opaque
    frame.setContentPane(demo);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
/*
 * PictureTransferHandler.java is used by the 1.4 DragPictureDemo.java example.
 */
class PictureTransferHandler extends TransferHandler {
  DataFlavor pictureFlavor = DataFlavor.imageFlavor;
  DTPicture sourcePic;
  boolean shouldRemove;
  public boolean importData(JComponent c, Transferable t) {
    Image image;
    if (canImport(c, t.getTransferDataFlavors())) {
      DTPicture pic = (DTPicture) c;
      //Don"t drop on myself.
      if (sourcePic == pic) {
        shouldRemove = false;
        return true;
      }
      try {
        image = (Image) t.getTransferData(pictureFlavor);
        //Set the component to the new picture.
        pic.setImage(image);
        return true;
      } catch (UnsupportedFlavorException ufe) {
        System.out.println("importData: unsupported data flavor");
      } catch (IOException ioe) {
        System.out.println("importData: I/O exception");
      }
    }
    return false;
  }
  protected Transferable createTransferable(JComponent c) {
    sourcePic = (DTPicture) c;
    shouldRemove = true;
    return new PictureTransferable(sourcePic);
  }
  public int getSourceActions(JComponent c) {
    return COPY_OR_MOVE;
  }
  protected void exportDone(JComponent c, Transferable data, int action) {
    if (shouldRemove && (action == MOVE)) {
      sourcePic.setImage(null);
    }
    sourcePic = null;
  }
  public boolean canImport(JComponent c, DataFlavor[] flavors) {
    for (int i = 0; i < flavors.length; i++) {
      if (pictureFlavor.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
  class PictureTransferable implements Transferable {
    private Image image;
    PictureTransferable(DTPicture pic) {
      image = pic.image;
    }
    public Object getTransferData(DataFlavor flavor)
        throws UnsupportedFlavorException {
      if (!isDataFlavorSupported(flavor)) {
        throw new UnsupportedFlavorException(flavor);
      }
      return image;
    }
    public DataFlavor[] getTransferDataFlavors() {
      return new DataFlavor[] { pictureFlavor };
    }
    public boolean isDataFlavorSupported(DataFlavor flavor) {
      return pictureFlavor.equals(flavor);
    }
  }
}
/*
 * DTPicture.java is used by the 1.4 DragPictureDemo.java example.
 */
//A subclass of Picture that supports Data Transfer.
class DTPicture extends Picture implements MouseMotionListener {
  private MouseEvent firstMouseEvent = null;
  private static boolean installInputMapBindings = true;
  public DTPicture(Image image) {
    super(image);
    addMouseMotionListener(this);
    //Add the cut/copy/paste key bindings to the input map.
    //Note that this step is redundant if you are installing
    //menu accelerators that cause these actions to be invoked.
    //DragPictureDemo does not use menu accelerators and, since
    //the default value of installInputMapBindings is true,
    //the bindings are installed. DragPictureDemo2 does use
    //menu accelerators and so calls setInstallInputMapBindings
    //with a value of false. Your program would do one or the
    //other, but not both.
    if (installInputMapBindings) {
      InputMap imap = this.getInputMap();
      imap.put(KeyStroke.getKeyStroke("ctrl X"), TransferHandler
          .getCutAction().getValue(Action.NAME));
      imap.put(KeyStroke.getKeyStroke("ctrl C"), TransferHandler
          .getCopyAction().getValue(Action.NAME));
      imap.put(KeyStroke.getKeyStroke("ctrl V"), TransferHandler
          .getPasteAction().getValue(Action.NAME));
    }
    //Add the cut/copy/paste actions to the action map.
    //This step is necessary because the menu"s action listener
    //looks for these actions to fire.
    ActionMap map = this.getActionMap();
    map.put(TransferHandler.getCutAction().getValue(Action.NAME),
        TransferHandler.getCutAction());
    map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
        TransferHandler.getCopyAction());
    map.put(TransferHandler.getPasteAction().getValue(Action.NAME),
        TransferHandler.getPasteAction());
  }
  public void setImage(Image image) {
    this.image = image;
    this.repaint();
  }
  public void mousePressed(MouseEvent e) {
    //Don"t bother to drag if there is no image.
    if (image == null)
      return;
    firstMouseEvent = e;
    e.consume();
  }
  public void mouseDragged(MouseEvent e) {
    //Don"t bother to drag if the component displays no image.
    if (image == null)
      return;
    if (firstMouseEvent != null) {
      e.consume();
      //If they are holding down the control key, COPY rather than MOVE
      int ctrlMask = InputEvent.CTRL_DOWN_MASK;
      int action = ((e.getModifiersEx() & ctrlMask) == ctrlMask) ? TransferHandler.COPY
          : TransferHandler.MOVE;
      int dx = Math.abs(e.getX() - firstMouseEvent.getX());
      int dy = Math.abs(e.getY() - firstMouseEvent.getY());
      //Arbitrarily define a 5-pixel shift as the
      //official beginning of a drag.
      if (dx > 5 || dy > 5) {
        //This is a drag, not a click.
        JComponent c = (JComponent) e.getSource();
        TransferHandler handler = c.getTransferHandler();
        //Tell the transfer handler to initiate the drag.
        handler.exportAsDrag(c, firstMouseEvent, action);
        firstMouseEvent = null;
      }
    }
  }
  public void mouseReleased(MouseEvent e) {
    firstMouseEvent = null;
  }
  public void mouseMoved(MouseEvent e) {
  }
  //This method is necessary because DragPictureDemo and
  //DragPictureDemo2 both use this class and DragPictureDemo
  //needs to have the input map bindings installed for
  //cut/copy/paste. DragPictureDemo2 uses menu accelerators
  //and does not need to have the input map bindings installed.
  //Your program would use one approach or the other, but not
  //both. The default for installInputMapBindings is true.
  public static void setInstallInputMapBindings(boolean flag) {
    installInputMapBindings = flag;
  }
  public static boolean getInstallInputMapBindingds() { //for completeness
    return installInputMapBindings;
  }
}
/*
 * Picture.java is used by the 1.4 TrackFocusDemo.java and DragPictureDemo.java
 * examples.
 */
class Picture extends JComponent implements MouseListener, FocusListener,
    Accessible {
  Image image;
  public Picture(Image image) {
    this.image = image;
    setFocusable(true);
    addMouseListener(this);
    addFocusListener(this);
  }
  public void mouseClicked(MouseEvent e) {
    //Since the user clicked on us, let"s get focus!
    requestFocusInWindow();
  }
  public void mouseEntered(MouseEvent e) {
  }
  public void mouseExited(MouseEvent e) {
  }
  public void mousePressed(MouseEvent e) {
  }
  public void mouseReleased(MouseEvent e) {
  }
  public void focusGained(FocusEvent e) {
    //Draw the component with a red border
    //indicating that it has focus.
    this.repaint();
  }
  public void focusLost(FocusEvent e) {
    //Draw the component with a black border
    //indicating that it doesn"t have focus.
    this.repaint();
  }
  protected void paintComponent(Graphics graphics) {
    Graphics g = graphics.create();
    //Draw in our entire space, even if isOpaque is false.
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, image == null ? 125 : image.getWidth(this),
        image == null ? 125 : image.getHeight(this));
    if (image != null) {
      //Draw image at its natural size of 125x125.
      g.drawImage(image, 0, 0, this);
    }
    //Add a border, red if picture currently has focus
    if (isFocusOwner()) {
      g.setColor(Color.RED);
    } else {
      g.setColor(Color.BLACK);
    }
    g.drawRect(0, 0, image == null ? 125 : image.getWidth(this),
        image == null ? 125 : image.getHeight(this));
    g.dispose();
  }
}





Drag Picture Demo 2

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * DragPictureDemo2.java is a 1.4 example that requires the following files:
 * Picture.java DTPicture.java PictureTransferHandler.java
 * TransferActionListener.java images/Maya.jpg images/Anya.jpg images/Laine.jpg
 * images/Cosmo.jpg images/Adele.jpg images/Alexi.jpg
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.KeyboardFocusManager;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import javax.accessibility.Accessible;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.TransferHandler;
//A version of DragPictureDemo that creates an
//Edit menu with cut/copy/paste actions.
//This demo adds a class called TransferActionDemo
//that transfers the cut/copy/paste menu action
//to the currently focused component.
public class DragPictureDemo2 extends JPanel {
  DTPicture pic1, pic2, pic3, pic4, pic5, pic6, pic7, pic8, pic9, pic10,
      pic11, pic12;
  static String mayaString = "Maya";
  static String anyaString = "Anya";
  static String laineString = "Laine";
  static String cosmoString = "Cosmo";
  static String adeleString = "Adele";
  static String alexiString = "Alexi";
  PictureTransferHandler picHandler;
  public DragPictureDemo2() {
    super(new BorderLayout());
    picHandler = new PictureTransferHandler();
    //Since we are using keyboard accelerators, we don"t
    //need the component to install its own input map
    //bindings.
    DTPicture.setInstallInputMapBindings(false);
    JPanel mugshots = new JPanel(new GridLayout(4, 3));
    pic1 = new DTPicture(createImageIcon("images/" + mayaString + ".jpg",
        mayaString).getImage());
    pic1.setTransferHandler(picHandler);
    mugshots.add(pic1);
    pic2 = new DTPicture(createImageIcon("images/" + anyaString + ".jpg",
        anyaString).getImage());
    pic2.setTransferHandler(picHandler);
    mugshots.add(pic2);
    pic3 = new DTPicture(createImageIcon("images/" + laineString + ".jpg",
        laineString).getImage());
    pic3.setTransferHandler(picHandler);
    mugshots.add(pic3);
    pic4 = new DTPicture(createImageIcon("images/" + cosmoString + ".jpg",
        cosmoString).getImage());
    pic4.setTransferHandler(picHandler);
    mugshots.add(pic4);
    pic5 = new DTPicture(createImageIcon("images/" + adeleString + ".jpg",
        adeleString).getImage());
    pic5.setTransferHandler(picHandler);
    mugshots.add(pic5);
    pic6 = new DTPicture(createImageIcon("images/" + alexiString + ".jpg",
        alexiString).getImage());
    pic6.setTransferHandler(picHandler);
    mugshots.add(pic6);
    //These six components with no pictures provide handy
    //drop targets.
    pic7 = new DTPicture(null);
    pic7.setTransferHandler(picHandler);
    mugshots.add(pic7);
    pic8 = new DTPicture(null);
    pic8.setTransferHandler(picHandler);
    mugshots.add(pic8);
    pic9 = new DTPicture(null);
    pic9.setTransferHandler(picHandler);
    mugshots.add(pic9);
    pic10 = new DTPicture(null);
    pic10.setTransferHandler(picHandler);
    mugshots.add(pic10);
    pic11 = new DTPicture(null);
    pic11.setTransferHandler(picHandler);
    mugshots.add(pic11);
    pic12 = new DTPicture(null);
    pic12.setTransferHandler(picHandler);
    mugshots.add(pic12);
    setPreferredSize(new Dimension(450, 630));
    add(mugshots, BorderLayout.CENTER);
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }
  //Create an Edit menu to support cut/copy/paste.
  public JMenuBar createMenuBar() {
    JMenuItem menuItem = null;
    JMenuBar menuBar = new JMenuBar();
    JMenu mainMenu = new JMenu("Edit");
    mainMenu.setMnemonic(KeyEvent.VK_E);
    TransferActionListener actionListener = new TransferActionListener();
    menuItem = new JMenuItem("Cut");
    menuItem.setActionCommand((String) TransferHandler.getCutAction()
        .getValue(Action.NAME));
    menuItem.addActionListener(actionListener);
    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
        ActionEvent.CTRL_MASK));
    menuItem.setMnemonic(KeyEvent.VK_T);
    mainMenu.add(menuItem);
    menuItem = new JMenuItem("Copy");
    menuItem.setActionCommand((String) TransferHandler.getCopyAction()
        .getValue(Action.NAME));
    menuItem.addActionListener(actionListener);
    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
        ActionEvent.CTRL_MASK));
    menuItem.setMnemonic(KeyEvent.VK_C);
    mainMenu.add(menuItem);
    menuItem = new JMenuItem("Paste");
    menuItem.setActionCommand((String) TransferHandler.getPasteAction()
        .getValue(Action.NAME));
    menuItem.addActionListener(actionListener);
    menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,
        ActionEvent.CTRL_MASK));
    menuItem.setMnemonic(KeyEvent.VK_P);
    mainMenu.add(menuItem);
    menuBar.add(mainMenu);
    return menuBar;
  }
  /** Returns an ImageIcon, or null if the path was invalid. */
  protected static ImageIcon createImageIcon(String path, String description) {
    java.net.URL imageURL = DragPictureDemo2.class.getResource(path);
    if (imageURL == null) {
      System.err.println("Resource not found: " + path);
      return null;
    } else {
      return new ImageIcon(imageURL, description);
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("DragPictureDemo2");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the menu bar and content pane.
    DragPictureDemo2 demo = new DragPictureDemo2();
    frame.setJMenuBar(demo.createMenuBar());
    demo.setOpaque(true); //content panes must be opaque
    frame.setContentPane(demo);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
/*
 * DTPicture.java is used by the 1.4 DragPictureDemo.java example.
 */
//A subclass of Picture that supports Data Transfer.
class DTPicture extends Picture implements MouseMotionListener {
  private MouseEvent firstMouseEvent = null;
  private static boolean installInputMapBindings = true;
  public DTPicture(Image image) {
    super(image);
    addMouseMotionListener(this);
    //Add the cut/copy/paste key bindings to the input map.
    //Note that this step is redundant if you are installing
    //menu accelerators that cause these actions to be invoked.
    //DragPictureDemo does not use menu accelerators and, since
    //the default value of installInputMapBindings is true,
    //the bindings are installed. DragPictureDemo2 does use
    //menu accelerators and so calls setInstallInputMapBindings
    //with a value of false. Your program would do one or the
    //other, but not both.
    if (installInputMapBindings) {
      InputMap imap = this.getInputMap();
      imap.put(KeyStroke.getKeyStroke("ctrl X"), TransferHandler
          .getCutAction().getValue(Action.NAME));
      imap.put(KeyStroke.getKeyStroke("ctrl C"), TransferHandler
          .getCopyAction().getValue(Action.NAME));
      imap.put(KeyStroke.getKeyStroke("ctrl V"), TransferHandler
          .getPasteAction().getValue(Action.NAME));
    }
    //Add the cut/copy/paste actions to the action map.
    //This step is necessary because the menu"s action listener
    //looks for these actions to fire.
    ActionMap map = this.getActionMap();
    map.put(TransferHandler.getCutAction().getValue(Action.NAME),
        TransferHandler.getCutAction());
    map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
        TransferHandler.getCopyAction());
    map.put(TransferHandler.getPasteAction().getValue(Action.NAME),
        TransferHandler.getPasteAction());
  }
  public void setImage(Image image) {
    this.image = image;
    this.repaint();
  }
  public void mousePressed(MouseEvent e) {
    //Don"t bother to drag if there is no image.
    if (image == null)
      return;
    firstMouseEvent = e;
    e.consume();
  }
  public void mouseDragged(MouseEvent e) {
    //Don"t bother to drag if the component displays no image.
    if (image == null)
      return;
    if (firstMouseEvent != null) {
      e.consume();
      //If they are holding down the control key, COPY rather than MOVE
      int ctrlMask = InputEvent.CTRL_DOWN_MASK;
      int action = ((e.getModifiersEx() & ctrlMask) == ctrlMask) ? TransferHandler.COPY
          : TransferHandler.MOVE;
      int dx = Math.abs(e.getX() - firstMouseEvent.getX());
      int dy = Math.abs(e.getY() - firstMouseEvent.getY());
      //Arbitrarily define a 5-pixel shift as the
      //official beginning of a drag.
      if (dx > 5 || dy > 5) {
        //This is a drag, not a click.
        JComponent c = (JComponent) e.getSource();
        TransferHandler handler = c.getTransferHandler();
        //Tell the transfer handler to initiate the drag.
        handler.exportAsDrag(c, firstMouseEvent, action);
        firstMouseEvent = null;
      }
    }
  }
  public void mouseReleased(MouseEvent e) {
    firstMouseEvent = null;
  }
  public void mouseMoved(MouseEvent e) {
  }
  //This method is necessary because DragPictureDemo and
  //DragPictureDemo2 both use this class and DragPictureDemo
  //needs to have the input map bindings installed for
  //cut/copy/paste. DragPictureDemo2 uses menu accelerators
  //and does not need to have the input map bindings installed.
  //Your program would use one approach or the other, but not
  //both. The default for installInputMapBindings is true.
  public static void setInstallInputMapBindings(boolean flag) {
    installInputMapBindings = flag;
  }
  public static boolean getInstallInputMapBindingds() { //for completeness
    return installInputMapBindings;
  }
}
/*
 * Picture.java is used by the 1.4 TrackFocusDemo.java and DragPictureDemo.java
 * examples.
 */
class Picture extends JComponent implements MouseListener, FocusListener,
    Accessible {
  Image image;
  public Picture(Image image) {
    this.image = image;
    setFocusable(true);
    addMouseListener(this);
    addFocusListener(this);
  }
  public void mouseClicked(MouseEvent e) {
    //Since the user clicked on us, let"s get focus!
    requestFocusInWindow();
  }
  public void mouseEntered(MouseEvent e) {
  }
  public void mouseExited(MouseEvent e) {
  }
  public void mousePressed(MouseEvent e) {
  }
  public void mouseReleased(MouseEvent e) {
  }
  public void focusGained(FocusEvent e) {
    //Draw the component with a red border
    //indicating that it has focus.
    this.repaint();
  }
  public void focusLost(FocusEvent e) {
    //Draw the component with a black border
    //indicating that it doesn"t have focus.
    this.repaint();
  }
  protected void paintComponent(Graphics graphics) {
    Graphics g = graphics.create();
    //Draw in our entire space, even if isOpaque is false.
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, image == null ? 125 : image.getWidth(this),
        image == null ? 125 : image.getHeight(this));
    if (image != null) {
      //Draw image at its natural size of 125x125.
      g.drawImage(image, 0, 0, this);
    }
    //Add a border, red if picture currently has focus
    if (isFocusOwner()) {
      g.setColor(Color.RED);
    } else {
      g.setColor(Color.BLACK);
    }
    g.drawRect(0, 0, image == null ? 125 : image.getWidth(this),
        image == null ? 125 : image.getHeight(this));
    g.dispose();
  }
}
/*
 * PictureTransferHandler.java is used by the 1.4 DragPictureDemo.java example.
 */
class PictureTransferHandler extends TransferHandler {
  DataFlavor pictureFlavor = DataFlavor.imageFlavor;
  DTPicture sourcePic;
  boolean shouldRemove;
  public boolean importData(JComponent c, Transferable t) {
    Image image;
    if (canImport(c, t.getTransferDataFlavors())) {
      DTPicture pic = (DTPicture) c;
      //Don"t drop on myself.
      if (sourcePic == pic) {
        shouldRemove = false;
        return true;
      }
      try {
        image = (Image) t.getTransferData(pictureFlavor);
        //Set the component to the new picture.
        pic.setImage(image);
        return true;
      } catch (UnsupportedFlavorException ufe) {
        System.out.println("importData: unsupported data flavor");
      } catch (IOException ioe) {
        System.out.println("importData: I/O exception");
      }
    }
    return false;
  }
  protected Transferable createTransferable(JComponent c) {
    sourcePic = (DTPicture) c;
    shouldRemove = true;
    return new PictureTransferable(sourcePic);
  }
  public int getSourceActions(JComponent c) {
    return COPY_OR_MOVE;
  }
  protected void exportDone(JComponent c, Transferable data, int action) {
    if (shouldRemove && (action == MOVE)) {
      sourcePic.setImage(null);
    }
    sourcePic = null;
  }
  public boolean canImport(JComponent c, DataFlavor[] flavors) {
    for (int i = 0; i < flavors.length; i++) {
      if (pictureFlavor.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
  class PictureTransferable implements Transferable {
    private Image image;
    PictureTransferable(DTPicture pic) {
      image = pic.image;
    }
    public Object getTransferData(DataFlavor flavor)
        throws UnsupportedFlavorException {
      if (!isDataFlavorSupported(flavor)) {
        throw new UnsupportedFlavorException(flavor);
      }
      return image;
    }
    public DataFlavor[] getTransferDataFlavors() {
      return new DataFlavor[] { pictureFlavor };
    }
    public boolean isDataFlavorSupported(DataFlavor flavor) {
      return pictureFlavor.equals(flavor);
    }
  }
}
/*
 * TransferActionListener.java is used by the 1.4 DragPictureDemo.java example.
 */
/*
 * A class that tracks the focused component. This is necessary to delegate the
 * menu cut/copy/paste commands to the right component. An instance of this
 * class is listening and when the user fires one of these commands, it calls
 * the appropriate action on the currently focused component.
 */
class TransferActionListener implements ActionListener, PropertyChangeListener {
  private JComponent focusOwner = null;
  public TransferActionListener() {
    KeyboardFocusManager manager = KeyboardFocusManager
        .getCurrentKeyboardFocusManager();
    manager.addPropertyChangeListener("permanentFocusOwner", this);
  }
  public void propertyChange(PropertyChangeEvent e) {
    Object o = e.getNewValue();
    if (o instanceof JComponent) {
      focusOwner = (JComponent) o;
    } else {
      focusOwner = null;
    }
  }
  public void actionPerformed(ActionEvent e) {
    if (focusOwner == null)
      return;
    String action = (String) e.getActionCommand();
    Action a = focusOwner.getActionMap().get(action);
    if (a != null) {
      a.actionPerformed(new ActionEvent(focusOwner,
          ActionEvent.ACTION_PERFORMED, null));
    }
  }
}





Dropper - show File Drop Target from Drag-n-Drop

 
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.TransferHandler;
/**
 * Dropper - show File Drop Target from Drag-n-Drop
 * 
 * @version $Id: Dropper.java,v 1.1 2004/04/10 00:12:25 ian Exp $
 */
public class Dropper extends JFrame {
  /**
   * Construct trivial GUI and connect a TransferHandler to it.
   */
  public Dropper() {
    super("Drop Target");
    JComponent cp = (JComponent) getContentPane();
    cp.setTransferHandler(new MyFileTransferHandler()); // see below
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(150, 150);
  }
  /** Instantiate and show the GUI */
  public static void main(String[] args) {
    new Dropper().setVisible(true);
  }
}
/** Non-public class to handle filename drops */
class MyFileTransferHandler extends TransferHandler {
  /**
   * @see javax.swing.TransferHandler#canImport(javax.swing.JComponent,
   *      java.awt.datatransfer.DataFlavor[])
   */
  public boolean canImport(JComponent arg0, DataFlavor[] arg1) {
    for (int i = 0; i < arg1.length; i++) {
      DataFlavor flavor = arg1[i];
      if (flavor.equals(DataFlavor.javaFileListFlavor)) {
        System.out.println("canImport: JavaFileList FLAVOR: " + flavor);
        return true;
      }
      if (flavor.equals(DataFlavor.stringFlavor)) {
        System.out.println("canImport: String FLAVOR: " + flavor);
        return true;
      }
      System.err.println("canImport: Rejected Flavor: " + flavor);
    }
    // Didn"t find any that match, so:
    return false;
  }
  /**
   * Do the actual import.
   * 
   * @see javax.swing.TransferHandler#importData(javax.swing.JComponent,
   *      java.awt.datatransfer.Transferable)
   */
  public boolean importData(JComponent comp, Transferable t) {
    DataFlavor[] flavors = t.getTransferDataFlavors();
    System.out.println("Trying to import:" + t);
    System.out.println("... which has " + flavors.length + " flavors.");
    for (int i = 0; i < flavors.length; i++) {
      DataFlavor flavor = flavors[i];
      try {
        if (flavor.equals(DataFlavor.javaFileListFlavor)) {
          System.out.println("importData: FileListFlavor");
          List l = (List) t
              .getTransferData(DataFlavor.javaFileListFlavor);
          Iterator iter = l.iterator();
          while (iter.hasNext()) {
            File file = (File) iter.next();
            System.out.println("GOT FILE: "
                + file.getCanonicalPath());
            // Now do something with the file...
          }
          return true;
        } else if (flavor.equals(DataFlavor.stringFlavor)) {
          System.out.println("importData: String Flavor");
          String fileOrURL = (String) t.getTransferData(flavor);
          System.out.println("GOT STRING: " + fileOrURL);
          try {
            URL url = new URL(fileOrURL);
            System.out.println("Valid URL: " + url.toString());
            // Do something with the contents...
            return true;
          } catch (MalformedURLException ex) {
            System.err.println("Not a valid URL");
            return false;
          }
          // now do something with the String.
        } else {
          System.out.println("importData rejected: " + flavor);
          // Don"t return; try next flavor.
        }
      } catch (IOException ex) {
        System.err.println("IOError getting data: " + ex);
      } catch (UnsupportedFlavorException e) {
        System.err.println("Unsupported Flavor: " + e);
      }
    }
    // If you get here, I didn"t like the flavor.
    Toolkit.getDefaultToolkit().beep();
    return false;
  }
}





Editor Drop Target

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.BorderLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
public class EditorDropTarget implements DropTargetListener {
  public EditorDropTarget(JEditorPane pane) {
    this.pane = pane;
    // Create the DropTarget and register
    // it with the JEditorPane.
    dropTarget = new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE,
        this, true, null);
  }
  // Implementation of the DropTargetListener interface
  public void dragEnter(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("dragEnter, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Get the type of object being transferred and determine
    // whether it is appropriate.
    checkTransferType(dtde);
    // Accept or reject the drag.
    acceptOrRejectDrag(dtde);
  }
  public void dragExit(DropTargetEvent dte) {
    DnDUtils.debugPrintln("DropTarget dragExit");
  }
  public void dragOver(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dragOver, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    acceptOrRejectDrag(dtde);
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dropActionChanged, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    acceptOrRejectDrag(dtde);
  }
  public void drop(DropTargetDropEvent dtde) {
    DnDUtils.debugPrintln("DropTarget drop, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Check the drop action
    if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
      // Accept the drop and get the transfer data
      dtde.acceptDrop(dtde.getDropAction());
      Transferable transferable = dtde.getTransferable();
      try {
        boolean result = dropFile(transferable);
        dtde.dropComplete(result);
        DnDUtils.debugPrintln("Drop completed, success: " + result);
      } catch (Exception e) {
        DnDUtils.debugPrintln("Exception while handling drop " + e);
        dtde.dropComplete(false);
      }
    } else {
      DnDUtils.debugPrintln("Drop target rejected drop");
      dtde.rejectDrop();
    }
  }
  // Internal methods start here
  protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
    int dropAction = dtde.getDropAction();
    int sourceActions = dtde.getSourceActions();
    boolean acceptedDrag = false;
    DnDUtils.debugPrintln("\tSource actions are "
        + DnDUtils.showActions(sourceActions) + ", drop action is "
        + DnDUtils.showActions(dropAction));
    // Reject if the object being transferred
    // or the operations available are not acceptable.
    if (!acceptableType
        || (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      // Not offering copy or move - suggest a copy
      DnDUtils.debugPrintln("Drop target offering COPY");
      dtde.acceptDrag(DnDConstants.ACTION_COPY);
      acceptedDrag = true;
    } else {
      // Offering an acceptable operation: accept
      DnDUtils.debugPrintln("Drop target accepting drag");
      dtde.acceptDrag(dropAction);
      acceptedDrag = true;
    }
    return acceptedDrag;
  }
  protected void checkTransferType(DropTargetDragEvent dtde) {
    // Only accept a list of files
    acceptableType = dtde
        .isDataFlavorSupported(DataFlavor.javaFileListFlavor);
    DnDUtils.debugPrintln("File type acceptable - " + acceptableType);
  }
  // This method handles a drop for a list of files
  protected boolean dropFile(Transferable transferable) throws IOException,
      UnsupportedFlavorException, MalformedURLException {
    List fileList = (List) transferable
        .getTransferData(DataFlavor.javaFileListFlavor);
    File transferFile = (File) fileList.get(0);
    final URL transferURL = transferFile.toURL();
    DnDUtils.debugPrintln("File URL is " + transferURL);
    pane.setPage(transferURL);
    return true;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    final JFrame f = new JFrame("JEditor Pane Drop Target Example 1");
    JEditorPane pane = new JEditorPane();
    // Add a drop target to the JEditorPane
    EditorDropTarget target = new EditorDropTarget(pane);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.getContentPane().add(new JScrollPane(pane), BorderLayout.CENTER);
    f.setSize(500, 400);
    f.setVisible(true);
  }
  protected JEditorPane pane;
  protected DropTarget dropTarget;
  protected boolean acceptableType; // Indicates whether data is acceptable
}
class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK | DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = (System
      .getProperty("DnDExamples.debug") != null);
}





Editor Drop Target 2

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.BorderLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
public class EditorDropTarget2 implements DropTargetListener {
  public EditorDropTarget2(JEditorPane pane) {
    this.pane = pane;
    // Create the DropTarget and register
    // it with the JEditorPane.
    dropTarget = new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE,
        this, true, null);
  }
  // Implementation of the DropTargetListener interface
  public void dragEnter(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("dragEnter, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Get the type of object being transferred and determine
    // whether it is appropriate.
    checkTransferType(dtde);
    // Accept or reject the drag.
    acceptOrRejectDrag(dtde);
  }
  public void dragExit(DropTargetEvent dte) {
    DnDUtils.debugPrintln("DropTarget dragExit");
  }
  public void dragOver(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dragOver, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    acceptOrRejectDrag(dtde);
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dropActionChanged, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    acceptOrRejectDrag(dtde);
  }
  public void drop(DropTargetDropEvent dtde) {
    DnDUtils.debugPrintln("DropTarget drop, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Check the drop action
    if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
      // Accept the drop and get the transfer data
      dtde.acceptDrop(dtde.getDropAction());
      Transferable transferable = dtde.getTransferable();
      try {
        boolean result = false;
        if (draggingFile) {
          result = dropFile(transferable);
        } else {
          result = dropContent(transferable, dtde);
        }
        dtde.dropComplete(result);
        DnDUtils.debugPrintln("Drop completed, success: " + result);
      } catch (Exception e) {
        DnDUtils.debugPrintln("Exception while handling drop " + e);
        dtde.dropComplete(false);
      }
    } else {
      DnDUtils.debugPrintln("Drop target rejected drop");
      dtde.rejectDrop();
    }
  }
  // Internal methods start here
  protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
    int dropAction = dtde.getDropAction();
    int sourceActions = dtde.getSourceActions();
    boolean acceptedDrag = false;
    DnDUtils.debugPrintln("\tSource actions are "
        + DnDUtils.showActions(sourceActions) + ", drop action is "
        + DnDUtils.showActions(dropAction));
    // Reject if the object being transferred
    // or the operations available are not acceptable
    if (!acceptableType
        || (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if (!draggingFile && !pane.isEditable()) {
      // Can"t drag text to a read-only JEditorPane
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      // Not offering copy or move - suggest a copy
      DnDUtils.debugPrintln("Drop target offering COPY");
      dtde.acceptDrag(DnDConstants.ACTION_COPY);
      acceptedDrag = true;
    } else {
      // Offering an acceptable operation: accept
      DnDUtils.debugPrintln("Drop target accepting drag");
      dtde.acceptDrag(dropAction);
      acceptedDrag = true;
    }
    return acceptedDrag;
  }
  protected void checkTransferType(DropTargetDragEvent dtde) {
    // Accept a list of files, or data content that
    // amounts to plain text or a Unicode text string
    acceptableType = false;
    draggingFile = false;
    if (DnDUtils.isDebugEnabled()) {
      DataFlavor[] flavors = dtde.getCurrentDataFlavors();
      for (int i = 0; i < flavors.length; i++) {
        DataFlavor flavor = flavors[i];
        DnDUtils.debugPrintln("Drop MIME type " + flavor.getMimeType()
            + " is available");
      }
    }
    if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      acceptableType = true;
      draggingFile = true;
    } else if (dtde.isDataFlavorSupported(DataFlavor.plainTextFlavor)
        || dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      acceptableType = true;
    }
    DnDUtils.debugPrintln("File type acceptable - " + acceptableType);
  }
  // This method handles a drop for a list of files
  protected boolean dropFile(Transferable transferable) throws IOException,
      UnsupportedFlavorException, MalformedURLException {
    List fileList = (List) transferable
        .getTransferData(DataFlavor.javaFileListFlavor);
    File transferFile = (File) fileList.get(0);
    final URL transferURL = transferFile.toURL();
    DnDUtils.debugPrintln("File URL is " + transferURL);
    pane.setPage(transferURL);
    return true;
  }
  // This method handles a drop with data content
  protected boolean dropContent(Transferable transferable,
      DropTargetDropEvent dtde) {
    if (!pane.isEditable()) {
      // Can"t drop content on a read-only text control
      return false;
    }
    try {
      // Check for a match with the current content type
      DataFlavor[] flavors = dtde.getCurrentDataFlavors();
      DataFlavor selectedFlavor = null;
      // Look for either plain text or a String.
      for (int i = 0; i < flavors.length; i++) {
        DataFlavor flavor = flavors[i];
        if (flavor.equals(DataFlavor.plainTextFlavor)
            || flavor.equals(DataFlavor.stringFlavor)) {
          selectedFlavor = flavor;
          break;
        }
      }
      if (selectedFlavor == null) {
        // No compatible flavor - should never happen
        return false;
      }
      DnDUtils.debugPrintln("Selected flavor is "
          + selectedFlavor.getHumanPresentableName());
      // Get the transferable and then obtain the data
      Object data = transferable.getTransferData(selectedFlavor);
      DnDUtils.debugPrintln("Transfer data type is "
          + data.getClass().getName());
      String insertData = null;
      if (data instanceof InputStream) {
        // Plain text flavor
        String charSet = selectedFlavor.getParameter("charset");
        InputStream is = (InputStream) data;
        byte[] bytes = new byte[is.available()];
        is.read(bytes);
        try {
          insertData = new String(bytes, charSet);
        } catch (UnsupportedEncodingException e) {
          // Use the platform default encoding
          insertData = new String(bytes);
        }
      } else if (data instanceof String) {
        // String flavor
        insertData = (String) data;
      }
      if (insertData != null) {
        int selectionStart = pane.getCaretPosition();
        pane.replaceSelection(insertData);
        pane.select(selectionStart, selectionStart
            + insertData.length());
        return true;
      }
      return false;
    } catch (Exception e) {
      return false;
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    final JFrame f = new JFrame("JEditor Pane Drop Target Example 2");
    final JEditorPane pane = new JEditorPane();
    // Add a drop target to the JEditorPane
    EditorDropTarget2 target = new EditorDropTarget2(pane);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    JPanel panel = new JPanel();
    final JCheckBox editable = new JCheckBox("Editable");
    editable.setSelected(true);
    panel.add(editable);
    editable.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEditable(editable.isSelected());
      }
    });
    f.getContentPane().add(new JScrollPane(pane), BorderLayout.CENTER);
    f.getContentPane().add(panel, BorderLayout.SOUTH);
    f.setSize(500, 400);
    f.setVisible(true);
  }
  protected JEditorPane pane;
  protected DropTarget dropTarget;
  protected boolean acceptableType; // Indicates whether data is acceptable
  protected boolean draggingFile; // True if dragging an entire file
}
class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK | DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = (System
      .getProperty("DnDExamples.debug") != null);
}





Editor Drop Target 3

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
public class EditorDropTarget3 implements DropTargetListener,
    PropertyChangeListener {
  public EditorDropTarget3(JEditorPane pane) {
    this.pane = pane;
    // Listen for changes in the enabled property
    pane.addPropertyChangeListener(this);
    // Save the JEditorPane"s background color
    backgroundColor = pane.getBackground();
    // Create the DropTarget and register
    // it with the JEditorPane.
    dropTarget = new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE,
        this, pane.isEnabled(), null);
  }
  // Implementation of the DropTargetListener interface
  public void dragEnter(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("dragEnter, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Get the type of object being transferred and determine
    // whether it is appropriate.
    checkTransferType(dtde);
    // Accept or reject the drag.
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void dragExit(DropTargetEvent dte) {
    DnDUtils.debugPrintln("DropTarget dragExit");
    // Do drag-under feedback
    dragUnderFeedback(null, false);
  }
  public void dragOver(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dragOver, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dropActionChanged, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void drop(DropTargetDropEvent dtde) {
    DnDUtils.debugPrintln("DropTarget drop, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Check the drop action
    if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
      // Accept the drop and get the transfer data
      dtde.acceptDrop(dtde.getDropAction());
      Transferable transferable = dtde.getTransferable();
      try {
        boolean result = false;
        if (draggingFile) {
          result = dropFile(transferable);
        } else {
          result = dropContent(transferable, dtde);
        }
        dtde.dropComplete(result);
        DnDUtils.debugPrintln("Drop completed, success: " + result);
      } catch (Exception e) {
        DnDUtils.debugPrintln("Exception while handling drop " + e);
        dtde.dropComplete(false);
      }
    } else {
      DnDUtils.debugPrintln("Drop target rejected drop");
      dtde.rejectDrop();
    }
  }
  // PropertyChangeListener interface
  public void propertyChange(PropertyChangeEvent evt) {
    String propertyName = evt.getPropertyName();
    if (propertyName.equals("enabled")) {
      // Enable the drop target if the JEditorPane is enabled
      // and vice versa.
      dropTarget.setActive(pane.isEnabled());
    } else if (!changingBackground && propertyName.equals("background")) {
      backgroundColor = pane.getBackground();
    }
  }
  // Internal methods start here
  protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
    int dropAction = dtde.getDropAction();
    int sourceActions = dtde.getSourceActions();
    boolean acceptedDrag = false;
    DnDUtils.debugPrintln("\tSource actions are "
        + DnDUtils.showActions(sourceActions) + ", drop action is "
        + DnDUtils.showActions(dropAction));
    // Reject if the object being transferred
    // or the operations available are not acceptable.
    if (!acceptableType
        || (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if (!draggingFile && !pane.isEditable()) {
      // Can"t drag text to a read-only JEditorPane
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      // Not offering copy or move - suggest a copy
      DnDUtils.debugPrintln("Drop target offering COPY");
      dtde.acceptDrag(DnDConstants.ACTION_COPY);
      acceptedDrag = true;
    } else {
      // Offering an acceptable operation: accept
      DnDUtils.debugPrintln("Drop target accepting drag");
      dtde.acceptDrag(dropAction);
      acceptedDrag = true;
    }
    return acceptedDrag;
  }
  protected void dragUnderFeedback(DropTargetDragEvent dtde,
      boolean acceptedDrag) {
    if (draggingFile) {
      // When dragging a file, change the background color
      Color newColor = (dtde != null && acceptedDrag ? feedbackColor
          : backgroundColor);
      if (newColor.equals(pane.getBackground()) == false) {
        changingBackground = true;
        pane.setBackground(newColor);
        changingBackground = false;
        pane.repaint();
      }
    } else {
      if (dtde != null && acceptedDrag) {
        // Dragging text - move the insertion cursor
        Point location = dtde.getLocation();
        pane.getCaret().setVisible(true);
        pane.setCaretPosition(pane.viewToModel(location));
      } else {
        pane.getCaret().setVisible(false);
      }
    }
  }
  protected void checkTransferType(DropTargetDragEvent dtde) {
    // Accept a list of files, or data content that
    // amounts to plain text or a Unicode text string
    acceptableType = false;
    draggingFile = false;
    if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      acceptableType = true;
      draggingFile = true;
    } else if (dtde.isDataFlavorSupported(DataFlavor.plainTextFlavor)
        || dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      acceptableType = true;
    }
    DnDUtils.debugPrintln("File type acceptable - " + acceptableType);
    DnDUtils.debugPrintln("Dragging a file - " + draggingFile);
  }
  // This method handles a drop for a list of files
  protected boolean dropFile(Transferable transferable) throws IOException,
      UnsupportedFlavorException, MalformedURLException {
    List fileList = (List) transferable
        .getTransferData(DataFlavor.javaFileListFlavor);
    File transferFile = (File) fileList.get(0);
    final URL transferURL = transferFile.toURL();
    DnDUtils.debugPrintln("File URL is " + transferURL);
    pane.setPage(transferURL);
    return true;
  }
  // This method handles a drop with data content
  protected boolean dropContent(Transferable transferable,
      DropTargetDropEvent dtde) {
    if (!pane.isEditable()) {
      // Can"t drop content on a read-only text control
      return false;
    }
    try {
      // Check for a match with the current content type
      DataFlavor[] flavors = dtde.getCurrentDataFlavors();
      DataFlavor selectedFlavor = null;
      // Look for either plain text or a String.
      for (int i = 0; i < flavors.length; i++) {
        DataFlavor flavor = flavors[i];
        DnDUtils.debugPrintln("Drop MIME type " + flavor.getMimeType()
            + " is available");
        if (flavor.equals(DataFlavor.plainTextFlavor)
            || flavor.equals(DataFlavor.stringFlavor)) {
          selectedFlavor = flavor;
          break;
        }
      }
      if (selectedFlavor == null) {
        // No compatible flavor - should never happen
        return false;
      }
      DnDUtils.debugPrintln("Selected flavor is "
          + selectedFlavor.getHumanPresentableName());
      // Get the transferable and then obtain the data
      Object data = transferable.getTransferData(selectedFlavor);
      DnDUtils.debugPrintln("Transfer data type is "
          + data.getClass().getName());
      String insertData = null;
      if (data instanceof InputStream) {
        // Plain text flavor
        String charSet = selectedFlavor.getParameter("charset");
        InputStream is = (InputStream) data;
        byte[] bytes = new byte[is.available()];
        is.read(bytes);
        try {
          insertData = new String(bytes, charSet);
        } catch (UnsupportedEncodingException e) {
          // Use the platform default encoding
          insertData = new String(bytes);
        }
      } else if (data instanceof String) {
        // String flavor
        insertData = (String) data;
      }
      if (insertData != null) {
        int selectionStart = pane.getCaretPosition();
        pane.replaceSelection(insertData);
        pane.select(selectionStart, selectionStart
            + insertData.length());
        return true;
      }
      return false;
    } catch (Exception e) {
      return false;
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    final JFrame f = new JFrame("JEditor Pane Drop Target Example 3");
    final JEditorPane pane = new JEditorPane();
    // Add a drop target to the JEditorPane
    EditorDropTarget3 target = new EditorDropTarget3(pane);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    JPanel panel = new JPanel();
    final JCheckBox editable = new JCheckBox("Editable");
    editable.setSelected(true);
    panel.add(editable);
    editable.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEditable(editable.isSelected());
      }
    });
    final JCheckBox enabled = new JCheckBox("Enabled");
    enabled.setSelected(true);
    panel.add(enabled);
    enabled.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEnabled(enabled.isSelected());
      }
    });
    f.getContentPane().add(new JScrollPane(pane), BorderLayout.CENTER);
    f.getContentPane().add(panel, BorderLayout.SOUTH);
    f.setSize(500, 400);
    f.setVisible(true);
  }
  protected JEditorPane pane;
  protected DropTarget dropTarget;
  protected boolean acceptableType; // Indicates whether data is acceptable
  protected boolean draggingFile; // True if dragging an entire file
  protected Color backgroundColor; // Original background color of JEditorPane
  protected boolean changingBackground;
  protected static final Color feedbackColor = Color.gray;
}
class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK | DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = (System
      .getProperty("DnDExamples.debug") != null);
}





Editor Drop Target 4

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class EditorDropTarget4 implements DropTargetListener,
    PropertyChangeListener {
  public EditorDropTarget4(JEditorPane pane) {
    this.pane = pane;
    // Listen for changes in the enabled property
    pane.addPropertyChangeListener(this);
    // Save the JEditorPane"s background color
    backgroundColor = pane.getBackground();
    // Create the DropTarget and register
    // it with the JEditorPane.
    dropTarget = new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE,
        this, pane.isEnabled(), null);
  }
  // Implementation of the DropTargetListener interface
  public void dragEnter(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("dragEnter, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Get the type of object being transferred and determine
    // whether it is appropriate.
    checkTransferType(dtde);
    // Accept or reject the drag.
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void dragExit(DropTargetEvent dte) {
    DnDUtils.debugPrintln("DropTarget dragExit");
    // Do drag-under feedback
    dragUnderFeedback(null, false);
  }
  public void dragOver(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dragOver, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dropActionChanged, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void drop(DropTargetDropEvent dtde) {
    DnDUtils.debugPrintln("DropTarget drop, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Check the drop action
    if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
      // Accept the drop and get the transfer data
      dtde.acceptDrop(dtde.getDropAction());
      Transferable transferable = dtde.getTransferable();
      try {
        boolean result = false;
        if (draggingFile) {
          result = dropFile(transferable);
        } else {
          result = dropContent(transferable, dtde);
        }
        dtde.dropComplete(result);
        DnDUtils.debugPrintln("Drop completed, success: " + result);
      } catch (Exception e) {
        DnDUtils.debugPrintln("Exception while handling drop " + e);
        dtde.rejectDrop();
      }
    } else {
      DnDUtils.debugPrintln("Drop target rejected drop");
      dtde.dropComplete(false);
    }
  }
  // PropertyChangeListener interface
  public void propertyChange(PropertyChangeEvent evt) {
    String propertyName = evt.getPropertyName();
    if (propertyName.equals("enabled")) {
      // Enable the drop target if the JEditorPane is enabled
      // and vice versa.
      dropTarget.setActive(pane.isEnabled());
    } else if (!changingBackground && propertyName.equals("background")) {
      backgroundColor = pane.getBackground();
    }
  }
  // Internal methods start here
  protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
    int dropAction = dtde.getDropAction();
    int sourceActions = dtde.getSourceActions();
    boolean acceptedDrag = false;
    DnDUtils.debugPrintln("\tSource actions are "
        + DnDUtils.showActions(sourceActions) + ", drop action is "
        + DnDUtils.showActions(dropAction));
    // Reject if the object being transferred
    // or the operations available are not acceptable.
    if (!acceptableType
        || (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if (!draggingFile && !pane.isEditable()) {
      // Can"t drag text to a read-only JEditorPane
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      // Not offering copy or move - suggest a copy
      DnDUtils.debugPrintln("Drop target offering COPY");
      dtde.acceptDrag(DnDConstants.ACTION_COPY);
      acceptedDrag = true;
    } else {
      // Offering an acceptable operation: accept
      DnDUtils.debugPrintln("Drop target accepting drag");
      dtde.acceptDrag(dropAction);
      acceptedDrag = true;
    }
    return acceptedDrag;
  }
  protected void dragUnderFeedback(DropTargetDragEvent dtde,
      boolean acceptedDrag) {
    if (draggingFile) {
      // When dragging a file, change the background color
      Color newColor = (dtde != null && acceptedDrag ? feedbackColor
          : backgroundColor);
      if (newColor.equals(pane.getBackground()) == false) {
        changingBackground = true;
        pane.setBackground(newColor);
        changingBackground = false;
        pane.repaint();
      }
    } else {
      if (dtde != null && acceptedDrag) {
        // Dragging text - move the insertion cursor
        Point location = dtde.getLocation();
        pane.getCaret().setVisible(true);
        pane.setCaretPosition(pane.viewToModel(location));
      } else {
        pane.getCaret().setVisible(false);
      }
    }
  }
  protected void checkTransferType(DropTargetDragEvent dtde) {
    // Accept a list of files, or data content that
    // amounts to plain text or a Unicode text string
    acceptableType = false;
    draggingFile = false;
    if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      acceptableType = true;
      draggingFile = true;
    } else if (dtde.isDataFlavorSupported(DataFlavor.plainTextFlavor)
        || dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      acceptableType = true;
    }
    DnDUtils.debugPrintln("File type acceptable - " + acceptableType);
    DnDUtils.debugPrintln("Dragging a file - " + draggingFile);
  }
  // This method handles a drop for a list of files
  protected boolean dropFile(Transferable transferable) throws IOException,
      UnsupportedFlavorException, MalformedURLException {
    List fileList = (List) transferable
        .getTransferData(DataFlavor.javaFileListFlavor);
    File transferFile = (File) fileList.get(0);
    final URL transferURL = transferFile.toURL();
    DnDUtils.debugPrintln("File URL is " + transferURL);
    pane.setPage(transferURL);
    return true;
  }
  // This method handles a drop with data content
  protected boolean dropContent(Transferable transferable,
      DropTargetDropEvent dtde) {
    if (!pane.isEditable()) {
      // Can"t drop content on a read-only text control
      return false;
    }
    try {
      // Check for a match with the current content type
      DataFlavor[] flavors = dtde.getCurrentDataFlavors();
      DataFlavor selectedFlavor = null;
      // Look for either plain text or a String.
      for (int i = 0; i < flavors.length; i++) {
        DataFlavor flavor = flavors[i];
        DnDUtils.debugPrintln("Drop MIME type " + flavor.getMimeType()
            + " is available");
        if (flavor.equals(DataFlavor.plainTextFlavor)
            || flavor.equals(DataFlavor.stringFlavor)) {
          selectedFlavor = flavor;
          break;
        }
      }
      if (selectedFlavor == null) {
        // No compatible flavor - should never happen
        return false;
      }
      DnDUtils.debugPrintln("Selected flavor is "
          + selectedFlavor.getHumanPresentableName());
      // Get the transferable and then obtain the data
      Object data = transferable.getTransferData(selectedFlavor);
      DnDUtils.debugPrintln("Transfer data type is "
          + data.getClass().getName());
      String insertData = null;
      if (data instanceof InputStream) {
        // Plain text flavor
        String charSet = selectedFlavor.getParameter("charset");
        InputStream is = (InputStream) data;
        byte[] bytes = new byte[is.available()];
        is.read(bytes);
        try {
          insertData = new String(bytes, charSet);
        } catch (UnsupportedEncodingException e) {
          // Use the platform default encoding
          insertData = new String(bytes);
        }
      } else if (data instanceof String) {
        // String flavor
        insertData = (String) data;
      }
      if (insertData != null) {
        int selectionStart = pane.getCaretPosition();
        pane.replaceSelection(insertData);
        pane.select(selectionStart, selectionStart
            + insertData.length());
        return true;
      }
      return false;
    } catch (Exception e) {
      return false;
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    final JFrame f = new JFrame("JEditor Pane Drop Target Example 4");
    // Create an editor with autoscrolling support
    final JEditorPane pane = new AutoScrollingEditorPane();
    // Add a drop target to the JEditorPane
    EditorDropTarget4 target = new EditorDropTarget4(pane);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    JPanel panel = new JPanel();
    final JCheckBox editable = new JCheckBox("Editable");
    editable.setSelected(true);
    panel.add(editable);
    editable.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEditable(editable.isSelected());
      }
    });
    final JCheckBox enabled = new JCheckBox("Enabled");
    enabled.setSelected(true);
    panel.add(enabled);
    enabled.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        pane.setEnabled(enabled.isSelected());
      }
    });
    f.getContentPane().add(new JScrollPane(pane), BorderLayout.CENTER);
    f.getContentPane().add(panel, BorderLayout.SOUTH);
    f.setSize(500, 400);
    f.setVisible(true);
  }
  protected JEditorPane pane;
  protected DropTarget dropTarget;
  protected boolean acceptableType; // Indicates whether data is acceptable
  protected boolean draggingFile; // True if dragging an entire file
  protected Color backgroundColor; // Original background color of JEditorPane
  protected boolean changingBackground;
  protected static final Color feedbackColor = Color.gray;
}
class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK | DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = (System
      .getProperty("DnDExamples.debug") != null);
}
class AutoScrollingEditorPane extends JEditorPane implements Autoscroll {
  public static final Insets defaultScrollInsets = new Insets(8, 8, 8, 8);
  protected Insets scrollInsets = defaultScrollInsets;
  public AutoScrollingEditorPane() {
  }
  public void setScrollInsets(Insets insets) {
    this.scrollInsets = insets;
  }
  public Insets getScrollInsets() {
    return scrollInsets;
  }
  // Implementation of Autoscroll interface
  public Insets getAutoscrollInsets() {
    Rectangle r = getVisibleRect();
    Dimension size = getSize();
    Insets i = new Insets(r.y + scrollInsets.top, r.x + scrollInsets.left,
        size.height - r.y - r.height + scrollInsets.bottom, size.width
            - r.x - r.width + scrollInsets.right);
    return i;
  }
  public void autoscroll(Point location) {
    JScrollPane scroller = (JScrollPane) SwingUtilities.getAncestorOfClass(
        JScrollPane.class, this);
    if (scroller != null) {
      JScrollBar hBar = scroller.getHorizontalScrollBar();
      JScrollBar vBar = scroller.getVerticalScrollBar();
      Rectangle r = getVisibleRect();
      if (location.x <= r.x + scrollInsets.left) {
        // Need to scroll left
        hBar.setValue(hBar.getValue() - hBar.getUnitIncrement(-1));
      }
      if (location.y <= r.y + scrollInsets.top) {
        // Need to scroll up
        vBar.setValue(vBar.getValue() - vBar.getUnitIncrement(-1));
      }
      if (location.x >= r.x + r.width - scrollInsets.right) {
        // Need to scroll right
        hBar.setValue(hBar.getValue() + hBar.getUnitIncrement(1));
      }
      if (location.y >= r.y + r.height - scrollInsets.bottom) {
        // Need to scroll down
        vBar.setValue(vBar.getValue() + vBar.getUnitIncrement(1));
      }
    }
  }
}





Extended DnD (Drag and Drop) Demo

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * ExtendedDnDDemo.java is a 1.4 example that requires the following files:
 * StringTransferHandler.java ListTransferHandler.java TableTransferHandler.java
 */
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.table.DefaultTableModel;
public class ExtendedDnDDemo extends JPanel {
  public ExtendedDnDDemo() {
    super(new GridLayout(3, 1));
    add(createArea());
    add(createList());
    add(createTable());
  }
  private JPanel createList() {
    DefaultListModel listModel = new DefaultListModel();
    listModel.addElement("List 0");
    listModel.addElement("List 1");
    listModel.addElement("List 2");
    listModel.addElement("List 3");
    listModel.addElement("List 4");
    listModel.addElement("List 5");
    listModel.addElement("List 6");
    listModel.addElement("List 7");
    listModel.addElement("List 8");
    JList list = new JList(listModel);
    list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    JScrollPane scrollPane = new JScrollPane(list);
    scrollPane.setPreferredSize(new Dimension(400, 100));
    list.setDragEnabled(true);
    list.setTransferHandler(new ListTransferHandler());
    JPanel panel = new JPanel(new BorderLayout());
    panel.add(scrollPane, BorderLayout.CENTER);
    panel.setBorder(BorderFactory.createTitledBorder("List"));
    return panel;
  }
  private JPanel createArea() {
    String text = "This is the text that I want to show.";
    JTextArea area = new JTextArea();
    area.setText(text);
    area.setDragEnabled(true);
    JScrollPane scrollPane = new JScrollPane(area);
    scrollPane.setPreferredSize(new Dimension(400, 100));
    JPanel panel = new JPanel(new BorderLayout());
    panel.add(scrollPane, BorderLayout.CENTER);
    panel.setBorder(BorderFactory.createTitledBorder("Text Area"));
    return panel;
  }
  private JPanel createTable() {
    DefaultTableModel model = new DefaultTableModel();
    model.addColumn("Column 0");
    model.addColumn("Column 1");
    model.addColumn("Column 2");
    model.addColumn("Column 3");
    model.addRow(new String[] { "Table 00", "Table 01", "Table 02",
        "Table 03" });
    model.addRow(new String[] { "Table 10", "Table 11", "Table 12",
        "Table 13" });
    model.addRow(new String[] { "Table 20", "Table 21", "Table 22",
        "Table 23" });
    model.addRow(new String[] { "Table 30", "Table 31", "Table 32",
        "Table 33" });
    JTable table = new JTable(model);
    table.getTableHeader().setReorderingAllowed(false);
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    JScrollPane scrollPane = new JScrollPane(table);
    scrollPane.setPreferredSize(new Dimension(400, 100));
    table.setDragEnabled(true);
    table.setTransferHandler(new TableTransferHandler());
    JPanel panel = new JPanel(new BorderLayout());
    panel.add(scrollPane, BorderLayout.CENTER);
    panel.setBorder(BorderFactory.createTitledBorder("Table"));
    return panel;
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("ExtendedDnDDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    JComponent newContentPane = new ExtendedDnDDemo();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
/*
 * ListTransferHandler.java is used by the 1.4 ExtendedDnDDemo.java example.
 */
class ListTransferHandler extends StringTransferHandler {
  private int[] indices = null;
  private int addIndex = -1; //Location where items were added
  private int addCount = 0; //Number of items added.
  //Bundle up the selected items in the list
  //as a single string, for export.
  protected String exportString(JComponent c) {
    JList list = (JList) c;
    indices = list.getSelectedIndices();
    Object[] values = list.getSelectedValues();
    StringBuffer buff = new StringBuffer();
    for (int i = 0; i < values.length; i++) {
      Object val = values[i];
      buff.append(val == null ? "" : val.toString());
      if (i != values.length - 1) {
        buff.append("\n");
      }
    }
    return buff.toString();
  }
  //Take the incoming string and wherever there is a
  //newline, break it into a separate item in the list.
  protected void importString(JComponent c, String str) {
    JList target = (JList) c;
    DefaultListModel listModel = (DefaultListModel) target.getModel();
    int index = target.getSelectedIndex();
    //Prevent the user from dropping data back on itself.
    //For example, if the user is moving items #4,#5,#6 and #7 and
    //attempts to insert the items after item #5, this would
    //be problematic when removing the original items.
    //So this is not allowed.
    if (indices != null && index >= indices[0] - 1
        && index <= indices[indices.length - 1]) {
      indices = null;
      return;
    }
    int max = listModel.getSize();
    if (index < 0) {
      index = max;
    } else {
      index++;
      if (index > max) {
        index = max;
      }
    }
    addIndex = index;
    String[] values = str.split("\n");
    addCount = values.length;
    for (int i = 0; i < values.length; i++) {
      listModel.add(index++, values[i]);
    }
  }
  //If the remove argument is true, the drop has been
  //successful and it"s time to remove the selected items
  //from the list. If the remove argument is false, it
  //was a Copy operation and the original list is left
  //intact.
  protected void cleanup(JComponent c, boolean remove) {
    if (remove && indices != null) {
      JList source = (JList) c;
      DefaultListModel model = (DefaultListModel) source.getModel();
      //If we are moving items around in the same list, we
      //need to adjust the indices accordingly, since those
      //after the insertion point have moved.
      if (addCount > 0) {
        for (int i = 0; i < indices.length; i++) {
          if (indices[i] > addIndex) {
            indices[i] += addCount;
          }
        }
      }
      for (int i = indices.length - 1; i >= 0; i--) {
        model.remove(indices[i]);
      }
    }
    indices = null;
    addCount = 0;
    addIndex = -1;
  }
}
/*
 * StringTransferHandler.java is used by the 1.4 ExtendedDnDDemo.java example.
 */
abstract class StringTransferHandler extends TransferHandler {
  protected abstract String exportString(JComponent c);
  protected abstract void importString(JComponent c, String str);
  protected abstract void cleanup(JComponent c, boolean remove);
  protected Transferable createTransferable(JComponent c) {
    return new StringSelection(exportString(c));
  }
  public int getSourceActions(JComponent c) {
    return COPY_OR_MOVE;
  }
  public boolean importData(JComponent c, Transferable t) {
    if (canImport(c, t.getTransferDataFlavors())) {
      try {
        String str = (String) t
            .getTransferData(DataFlavor.stringFlavor);
        importString(c, str);
        return true;
      } catch (UnsupportedFlavorException ufe) {
      } catch (IOException ioe) {
      }
    }
    return false;
  }
  protected void exportDone(JComponent c, Transferable data, int action) {
    cleanup(c, action == MOVE);
  }
  public boolean canImport(JComponent c, DataFlavor[] flavors) {
    for (int i = 0; i < flavors.length; i++) {
      if (DataFlavor.stringFlavor.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
}
/*
 * TableTransferHandler.java is used by the 1.4 ExtendedDnDDemo.java example.
 */
class TableTransferHandler extends StringTransferHandler {
  private int[] rows = null;
  private int addIndex = -1; //Location where items were added
  private int addCount = 0; //Number of items added.
  protected String exportString(JComponent c) {
    JTable table = (JTable) c;
    rows = table.getSelectedRows();
    int colCount = table.getColumnCount();
    StringBuffer buff = new StringBuffer();
    for (int i = 0; i < rows.length; i++) {
      for (int j = 0; j < colCount; j++) {
        Object val = table.getValueAt(rows[i], j);
        buff.append(val == null ? "" : val.toString());
        if (j != colCount - 1) {
          buff.append(",");
        }
      }
      if (i != rows.length - 1) {
        buff.append("\n");
      }
    }
    return buff.toString();
  }
  protected void importString(JComponent c, String str) {
    JTable target = (JTable) c;
    DefaultTableModel model = (DefaultTableModel) target.getModel();
    int index = target.getSelectedRow();
    //Prevent the user from dropping data back on itself.
    //For example, if the user is moving rows #4,#5,#6 and #7 and
    //attempts to insert the rows after row #5, this would
    //be problematic when removing the original rows.
    //So this is not allowed.
    if (rows != null && index >= rows[0] - 1
        && index <= rows[rows.length - 1]) {
      rows = null;
      return;
    }
    int max = model.getRowCount();
    if (index < 0) {
      index = max;
    } else {
      index++;
      if (index > max) {
        index = max;
      }
    }
    addIndex = index;
    String[] values = str.split("\n");
    addCount = values.length;
    int colCount = target.getColumnCount();
    for (int i = 0; i < values.length && i < colCount; i++) {
      model.insertRow(index++, values[i].split(","));
    }
  }
  protected void cleanup(JComponent c, boolean remove) {
    JTable source = (JTable) c;
    if (remove && rows != null) {
      DefaultTableModel model = (DefaultTableModel) source.getModel();
      //If we are moving items around in the same table, we
      //need to adjust the rows accordingly, since those
      //after the insertion point have moved.
      if (addCount > 0) {
        for (int i = 0; i < rows.length; i++) {
          if (rows[i] > addIndex) {
            rows[i] += addCount;
          }
        }
      }
      for (int i = rows.length - 1; i >= 0; i--) {
        model.removeRow(rows[i]);
      }
    }
    rows = null;
    addCount = 0;
    addIndex = -1;
  }
}





File Tree Drag Source

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ruparator;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
public class FileTreeDragSource implements DragGestureListener,
    DragSourceListener {
  public FileTreeDragSource(FileTree tree) {
    this.tree = tree;
    // Use the default DragSource
    DragSource dragSource = DragSource.getDefaultDragSource();
    // Create a DragGestureRecognizer and
    // register as the listener
    dragSource.createDefaultDragGestureRecognizer(tree,
        DnDConstants.ACTION_COPY_OR_MOVE, this);
  }
  // Implementation of DragGestureListener interface.
  public void dragGestureRecognized(DragGestureEvent dge) {
    // Get the mouse location and convert it to
    // a location within the tree.
    Point location = dge.getDragOrigin();
    TreePath dragPath = tree.getPathForLocation(location.x, location.y);
    if (dragPath != null && tree.isPathSelected(dragPath)) {
      // Get the list of selected files and create a Transferable
      // The list of files and the is saved for use when
      // the drop completes.
      paths = tree.getSelectionPaths();
      if (paths != null && paths.length > 0) {
        dragFiles = new File[paths.length];
        for (int i = 0; i < paths.length; i++) {
          String pathName = tree.getPathName(paths[i]);
          dragFiles[i] = new File(pathName);
        }
        Transferable transferable = new FileListTransferable(dragFiles);
        dge.startDrag(null, transferable, this);
      }
    }
  }
  // Implementation of DragSourceListener interface
  public void dragEnter(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dragEnter, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragOver(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dragOver, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragExit(DragSourceEvent dse) {
    DnDUtils.debugPrintln("Drag Source: dragExit");
  }
  public void dropActionChanged(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dropActionChanged, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragDropEnd(DragSourceDropEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: drop completed, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()) + ", success: "
        + dsde.getDropSuccess());
    // If the drop action was ACTION_MOVE,
    // the tree might need to be updated.
    if (dsde.getDropAction() == DnDConstants.ACTION_MOVE) {
      final File[] draggedFiles = dragFiles;
      final TreePath[] draggedPaths = paths;
      Timer tm = new Timer(200, new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          // Check whether each of the dragged files exists.
          // If it does not, we need to remove the node
          // that represents it from the tree.
          for (int i = 0; i < draggedFiles.length; i++) {
            if (draggedFiles[i].exists() == false) {
              // Remove this node
              DefaultMutableTreeNode node = (DefaultMutableTreeNode) draggedPaths[i]
                  .getLastPathComponent();
              ((DefaultTreeModel) tree.getModel())
                  .removeNodeFromParent(node);
            }
          }
        }
      });
      tm.setRepeats(false);
      tm.start();
    }
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Draggable File Tree");
    try {
      FileTree tree = new FileTree("D:\\");
      f.getContentPane().add(new JScrollPane(tree));
      // Attach the drag source
      FileTreeDragSource dragSource = new FileTreeDragSource(tree);
    } catch (Exception e) {
    }
    f.pack();
    f.setVisible(true);
  }
  protected FileTree tree; // The associated tree
  protected File[] dragFiles; // Dragged files
  protected TreePath[] paths; // Dragged paths
}
class FileTree extends JTree implements Autoscroll {
  public static final Insets defaultScrollInsets = new Insets(8, 8, 8, 8);
  protected Insets scrollInsets = defaultScrollInsets;
  public FileTree(String path) throws FileNotFoundException,
      SecurityException {
    super((TreeModel) null); // Create the JTree itself
    // Use horizontal and vertical lines
    putClientProperty("JTree.lineStyle", "Angled");
    // Create the first node
    FileTreeNode rootNode = new FileTreeNode(null, path);
    // Populate the root node with its subdirectories
    boolean addedNodes = rootNode.populateDirectories(true);
    setModel(new DefaultTreeModel(rootNode));
    // Listen for Tree Selection Events
    addTreeExpansionListener(new TreeExpansionHandler());
  }
  // Returns the full pathname for a path, or null if not a known path
  public String getPathName(TreePath path) {
    Object o = path.getLastPathComponent();
    if (o instanceof FileTreeNode) {
      return ((FileTreeNode) o).fullName;
    }
    return null;
  }
  // Adds a new node to the tree after construction.
  // Returns the inserted node, or null if the parent
  // directory has not been expanded.
  public FileTreeNode addNode(FileTreeNode parent, String name) {
    int index = parent.addNode(name);
    if (index != -1) {
      ((DefaultTreeModel) getModel()).nodesWereInserted(parent,
          new int[] { index });
      return (FileTreeNode) parent.getChildAt(index);
    }
    // No node was created
    return null;
  }
  // Autoscrolling support
  public void setScrollInsets(Insets insets) {
    this.scrollInsets = insets;
  }
  public Insets getScrollInsets() {
    return scrollInsets;
  }
  // Implementation of Autoscroll interface
  public Insets getAutoscrollInsets() {
    Rectangle r = getVisibleRect();
    Dimension size = getSize();
    Insets i = new Insets(r.y + scrollInsets.top, r.x + scrollInsets.left,
        size.height - r.y - r.height + scrollInsets.bottom, size.width
            - r.x - r.width + scrollInsets.right);
    return i;
  }
  public void autoscroll(Point location) {
    JScrollPane scroller = (JScrollPane) SwingUtilities.getAncestorOfClass(
        JScrollPane.class, this);
    if (scroller != null) {
      JScrollBar hBar = scroller.getHorizontalScrollBar();
      JScrollBar vBar = scroller.getVerticalScrollBar();
      Rectangle r = getVisibleRect();
      if (location.x <= r.x + scrollInsets.left) {
        // Need to scroll left
        hBar.setValue(hBar.getValue() - hBar.getUnitIncrement(-1));
      }
      if (location.y <= r.y + scrollInsets.top) {
        // Need to scroll up
        vBar.setValue(vBar.getValue() - vBar.getUnitIncrement(-1));
      }
      if (location.x >= r.x + r.width - scrollInsets.right) {
        // Need to scroll right
        hBar.setValue(hBar.getValue() + hBar.getUnitIncrement(1));
      }
      if (location.y >= r.y + r.height - scrollInsets.bottom) {
        // Need to scroll down
        vBar.setValue(vBar.getValue() + vBar.getUnitIncrement(1));
      }
    }
  }
  // Inner class that represents a node in this file system tree
  public static class FileTreeNode extends DefaultMutableTreeNode {
    public FileTreeNode(String parent, String name)
        throws SecurityException, FileNotFoundException {
      this.name = name;
      // See if this node exists and whether it is a directory
      fullName = parent == null ? name : parent + File.separator + name;
      File f = new File(fullName);
      if (f.exists() == false) {
        throw new FileNotFoundException("File " + fullName
            + " does not exist");
      }
      isDir = f.isDirectory();
      // Hack for Windows which doesn"t consider a drive to be a
      // directory!
      if (isDir == false && f.isFile() == false) {
        isDir = true;
      }
    }
    // Override isLeaf to check whether this is a directory
    public boolean isLeaf() {
      return !isDir;
    }
    // Override getAllowsChildren to check whether this is a directory
    public boolean getAllowsChildren() {
      return isDir;
    }
    // Return whether this is a directory
    public boolean isDir() {
      return isDir;
    }
    // Get full path
    public String getFullName() {
      return fullName;
    }
    // For display purposes, we return our own name
    public String toString() {
      return name;
    }
    // If we are a directory, scan our contents and populate
    // with children. In addition, populate those children
    // if the "descend" flag is true. We only descend once,
    // to avoid recursing the whole subtree.
    // Returns true if some nodes were added
    boolean populateDirectories(boolean descend) {
      boolean addedNodes = false;
      // Do this only once
      if (populated == false) {
        File f;
        try {
          f = new File(fullName);
        } catch (SecurityException e) {
          populated = true;
          return false;
        }
        if (interim == true) {
          // We have had a quick look here before:
          // remove the dummy node that we added last time
          removeAllChildren();
          interim = false;
        }
        String[] names = f.list(); // Get list of contents
        // Process the contents
        ArrayList list = new ArrayList();
        for (int i = 0; i < names.length; i++) {
          String name = names[i];
          File d = new File(fullName, name);
          try {
            FileTreeNode node = new FileTreeNode(fullName, name);
            list.add(node);
            if (descend && d.isDirectory()) {
              node.populateDirectories(false);
            }
            addedNodes = true;
            if (descend == false) {
              // Only add one node if not descending
              break;
            }
          } catch (Throwable t) {
            // Ignore phantoms or access problems
          }
        }
        if (addedNodes == true) {
          // Now sort the list of contained files and directories
          Object[] nodes = list.toArray();
          Arrays.sort(nodes, new Comparator() {
            public boolean equals(Object o) {
              return false;
            }
            public int compare(Object o1, Object o2) {
              FileTreeNode node1 = (FileTreeNode) o1;
              FileTreeNode node2 = (FileTreeNode) o2;
              // Directories come first
              if (node1.isDir != node2.isDir) {
                return node1.isDir ? -1 : +1;
              }
              // Both directories or both files -
              // compare based on pathname
              return node1.fullName.rupareTo(node2.fullName);
            }
          });
          // Add sorted items as children of this node
          for (int j = 0; j < nodes.length; j++) {
            this.add((FileTreeNode) nodes[j]);
          }
        }
        // If we were scanning to get all subdirectories,
        // or if we found no content, there is no
        // reason to look at this directory again, so
        // set populated to true. Otherwise, we set interim
        // so that we look again in the future if we need to
        if (descend == true || addedNodes == false) {
          populated = true;
        } else {
          // Just set interim state
          interim = true;
        }
      }
      return addedNodes;
    }
    // Adding a new file or directory after
    // constructing the FileTree. Returns
    // the index of the inserted node.
    public int addNode(String name) {
      // If not populated yet, do nothing
      if (populated == true) {
        // Do not add a new node if
        // the required node is already there
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
          FileTreeNode node = (FileTreeNode) getChildAt(i);
          if (node.name.equals(name)) {
            // Already exists - ensure
            // we repopulate
            if (node.isDir()) {
              node.interim = true;
              node.populated = false;
            }
            return -1;
          }
        }
        // Add a new node
        try {
          FileTreeNode node = new FileTreeNode(fullName, name);
          add(node);
          return childCount;
        } catch (Exception e) {
        }
      }
      return -1;
    }
    protected String name; // Name of this component
    protected String fullName; // Full pathname
    protected boolean populated;// true if we have been populated
    protected boolean interim; // true if we are in interim state
    protected boolean isDir; // true if this is a directory
  }
  // Inner class that handles Tree Expansion Events
  protected class TreeExpansionHandler implements TreeExpansionListener {
    public void treeExpanded(TreeExpansionEvent evt) {
      TreePath path = evt.getPath(); // The expanded path
      JTree tree = (JTree) evt.getSource(); // The tree
      // Get the last component of the path and
      // arrange to have it fully populated.
      FileTreeNode node = (FileTreeNode) path.getLastPathComponent();
      if (node.populateDirectories(true)) {
        ((DefaultTreeModel) tree.getModel()).nodeStructureChanged(node);
      }
    }
    public void treeCollapsed(TreeExpansionEvent evt) {
      // Nothing to do
    }
  }
}
class FileListTransferable implements Transferable {
  public FileListTransferable(File[] files) {
    fileList = new ArrayList();
    for (int i = 0; i < files.length; i++) {
      fileList.add(files[i]);
    }
  }
  // Implementation of the Transferable interface
  public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[] { DataFlavor.javaFileListFlavor };
  }
  public boolean isDataFlavorSupported(DataFlavor fl) {
    return fl.equals(DataFlavor.javaFileListFlavor);
  }
  public Object getTransferData(DataFlavor fl) {
    if (!isDataFlavorSupported(fl)) {
      return null;
    }
    return fileList;
  }
  List fileList; // The list of files
}
class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK|DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = 
    (System.getProperty("DnDExamples.debug") != null);
}





File Tree Drop Target

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ruparator;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
public class FileTreeDropTarget implements DropTargetListener, 
                  PropertyChangeListener {
  public FileTreeDropTarget(FileTree tree) {
    this.tree = tree;
    
    // Listen for changes in the enabled property
    tree.addPropertyChangeListener(this);
    // Create the DropTarget and register 
    // it with the FileTree.
    dropTarget = new DropTarget(tree,
                  DnDConstants.ACTION_COPY_OR_MOVE, 
                  this, 
                  tree.isEnabled(), null);
  }
  // Implementation of the DropTargetListener interface
  public void dragEnter(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("dragEnter, drop action = " 
            + DnDUtils.showActions(dtde.getDropAction()));
    // Save the list of selected items
    saveTreeSelection();
    // Get the type of object being transferred and determine
    // whether it is appropriate.
    checkTransferType(dtde);
    // Accept or reject the drag.
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
        
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void dragExit(DropTargetEvent dte) {
    DnDUtils.debugPrintln("DropTarget dragExit");
    
    // Do drag-under feedback
    dragUnderFeedback(null, false);
    // Restore the original selections
    restoreTreeSelection();
  }
  public void dragOver(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dragOver, drop action = "
            + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dropActionChanged, drop action = "
            + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    boolean acceptedDrag = acceptOrRejectDrag(dtde);
    
    // Do drag-under feedback
    dragUnderFeedback(dtde, acceptedDrag);
  }
  public void drop(DropTargetDropEvent dtde) {
    DnDUtils.debugPrintln("DropTarget drop, drop action = "
            + DnDUtils.showActions(dtde.getDropAction()));
    // Check the drop action
    if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
      // Accept the drop and get the transfer data
      dtde.acceptDrop(dtde.getDropAction());
      Transferable transferable = dtde.getTransferable();
      boolean dropSucceeded = false;
      
      try {
        tree.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        // Save the user"s selections
        saveTreeSelection();
                              
        dropSucceeded = dropFile(dtde.getDropAction(),
                transferable, dtde.getLocation());
        
        DnDUtils.debugPrintln("Drop completed, success: " 
                    + dropSucceeded);
      } catch (Exception e) {
        DnDUtils.debugPrintln("Exception while handling drop " + e);
      } finally {
        tree.setCursor(Cursor.getDefaultCursor());
        // Restore the user"s selections
        restoreTreeSelection();
        dtde.dropComplete(dropSucceeded);
      }
    } else {
      DnDUtils.debugPrintln("Drop target rejected drop");
      dtde.dropComplete(false);
    }
  }
  
  // PropertyChangeListener interface
  public void propertyChange(PropertyChangeEvent evt) {
    String propertyName = evt.getPropertyName();
    if (propertyName.equals("enabled")) {
      // Enable the drop target if the FileTree is enabled
      // and vice versa.    
      dropTarget.setActive(tree.isEnabled());
    }
  }
  // Internal methods start here
  protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
    int dropAction = dtde.getDropAction();
    int sourceActions = dtde.getSourceActions();
    boolean acceptedDrag = false;
    DnDUtils.debugPrintln("\tSource actions are " + 
              DnDUtils.showActions(sourceActions) + 
              ", drop action is " + 
              DnDUtils.showActions(dropAction));
    
    Point location = dtde.getLocation();
    boolean acceptableDropLocation = isAcceptableDropLocation(location);
    // Reject if the object being transferred 
    // or the operations available are not acceptable.
    if (!acceptableType || 
      (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if (!tree.isEditable()) {
      // Can"t drag to a read-only FileTree
      DnDUtils.debugPrintln("Drop target rejecting drag");      
      dtde.rejectDrag();
    } else if (!acceptableDropLocation) {
      // Can only drag to writable directory
      DnDUtils.debugPrintln("Drop target rejecting drag");      
      dtde.rejectDrag();
    } else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      // Not offering copy or move - suggest a copy
      DnDUtils.debugPrintln("Drop target offering COPY");
      dtde.acceptDrag(DnDConstants.ACTION_COPY);
      acceptedDrag = true;
    } else {
      // Offering an acceptable operation: accept
      DnDUtils.debugPrintln("Drop target accepting drag");
      dtde.acceptDrag(dropAction);
      acceptedDrag = true;
    }
    return acceptedDrag;
  }
  protected void dragUnderFeedback(DropTargetDragEvent dtde, 
                  boolean acceptedDrag) {
    if (dtde != null && acceptedDrag) {
      Point location = dtde.getLocation();
      if (isAcceptableDropLocation(location)) {
        tree.setSelectionRow(
          tree.getRowForLocation(location.x, location.y));
      } else {
        tree.clearSelection();
      }
    } else {
      tree.clearSelection();
    }
  }
    
  protected void checkTransferType(DropTargetDragEvent dtde) {
    // Accept a list of files
    acceptableType = false;
    if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      acceptableType = true;
    }
    DnDUtils.debugPrintln("Data type acceptable - " + acceptableType);
  }
  // This method handles a drop for a list of files
  protected boolean dropFile(int action,
                 Transferable transferable, Point location) 
              throws IOException, UnsupportedFlavorException,
                MalformedURLException {
    List files = (List)transferable.getTransferData(
                DataFlavor.javaFileListFlavor);
    TreePath treePath = tree.getPathForLocation(
                location.x, location.y);
    File targetDirectory = findTargetDirectory(location); 
    if (treePath == null || targetDirectory == null) {
      return false;
    }
    FileTree.FileTreeNode node = 
          (FileTree.FileTreeNode)treePath.getLastPathComponent();
    
    // Highlight the drop location while we perform the drop
    tree.setSelectionPath(treePath);
    // Get File objects for all files being
    // transferred, eliminating duplicates.
    File[] fileList = getFileList(files);
  
    // Don"t overwrite files by default
    copyOverExistingFiles = false;
    
    // Copy or move each source object to the target
    for (int i = 0; i < fileList.length; i++) {
      File f = fileList[i];
      if (f.isDirectory()) {
        transferDirectory(action, f, targetDirectory, node);
      } else {
        try {
          transferFile(action, fileList[i], 
                 targetDirectory, node);
        } catch (IllegalStateException e) {
          // Cancelled by user
          return false;
        }
      }
    }
    
    return true;
  }
  protected File findTargetDirectory(Point location) {
    TreePath treePath = tree.getPathForLocation(location.x, location.y);
    if(treePath != null) {
      FileTree.FileTreeNode node = 
          (FileTree.FileTreeNode)treePath.getLastPathComponent();
      // Only allow a drop on a writable directory
      if (node.isDir()) {
        try {
          File f = new File(node.getFullName());
          if (f.canWrite()) {
            return f;
          }
        } catch (Exception e) {
        }
      }
    }
    return null;
  }
  
  protected boolean isAcceptableDropLocation(Point location) {
    return findTargetDirectory(location) != null;
  }
  
  protected void saveTreeSelection() {
    selections = tree.getSelectionPaths();
    leadSelection = tree.getLeadSelectionPath();
    tree.clearSelection();
  }
  protected void restoreTreeSelection() {
    tree.setSelectionPaths(selections);
    // Restore the lead selection
    if (leadSelection != null) {
      tree.removeSelectionPath(leadSelection);
      tree.addSelectionPath(leadSelection);
    }
  }
  // Get the list of files being transferred and
  // remove any duplicates. For example, if the
  // list contains /a/b/c and /a/b/c/d, the
  // second entry is removed.
  protected File[] getFileList(List files) {
    int size = files.size();
    // Get the files into an array for sorting
    File[] f = new File[size];
    Iterator iter = files.iterator();
    int count = 0;
    while (iter.hasNext()) {
      f[count++] = (File)iter.next();
    }
    // Sort the files into alphabetical order
    // based on pathnames.
    Arrays.sort(f, new Comparator() {
      public boolean equals(Object o1) {
        return false;
      }
      public int compare(Object o1, Object o2) {
        return ((File)o1).getAbsolutePath().rupareTo(
                ((File)o2).getAbsolutePath());
      }
    });
    // Remove duplicates, retaining the results in a Vector
    Vector v = new Vector();
    char separator = System.getProperty("file.separator").charAt(0);
outer:
    for (int i = f.length - 1 ; i >= 0; i--) {
      String secondPath = f[i].getAbsolutePath();
      int secondLength = secondPath.length();
      for (int j = i - 1 ; j >= 0; j--) {
        String firstPath = f[j].getAbsolutePath();
        int firstLength = firstPath.length();
        if (secondPath.startsWith(firstPath) 
          && firstLength != secondLength
          && secondPath.charAt(firstLength) == separator) {
          continue outer;
        }
      }
      v.add(f[i]);
    }
    
    // Copy the retained files into an array
    f = new File[v.size()];
    v.copyInto(f);
    return f;
  }
  // Copy or move a file 
  protected void transferFile(int action, File srcFile,
                File targetDirectory,
                FileTree.FileTreeNode targetNode) {
    DnDUtils.debugPrintln(
            (action == DnDConstants.ACTION_COPY ? "Copy" : "Move") +
            " file " + srcFile.getAbsolutePath() +
            " to " + targetDirectory.getAbsolutePath());
    
    // Create a File entry for the target
    String name = srcFile.getName();
    File newFile = new File(targetDirectory, name);
    if (newFile.exists()) {
      // Already exists - is it the same file?
      if (newFile.equals(srcFile)) {
        // Exactly the same file - ignore
        return;
      }
      // File of this name exists in this directory
      if (copyOverExistingFiles == false) {
        int res = JOptionPane.showOptionDialog(tree,
              "A file called\n   " + name +
              "\nalready exists in the directory\n   " +
              targetDirectory.getAbsolutePath() +
              "\nOverwrite it?",
              "File Exists",
              JOptionPane.DEFAULT_OPTION,
              JOptionPane.QUESTION_MESSAGE,
              null, new String[] {
                "Yes", "Yes to All", "No", "Cancel"
              }, 
              "No");
        switch (res) {
        case 1:  // Yes to all
          copyOverExistingFiles = true;
        case 0:  // Yes
          break;
        case 2:  // No
          return;
        default: // Cancel
          throw new IllegalStateException("Cancelled");
        }
      }      
    } else {
      // New file - create it
      try {
        newFile.createNewFile();
      } catch (IOException e) {
        JOptionPane.showMessageDialog(tree, 
          "Failed to create new file\n  " +
          newFile.getAbsolutePath(),
          "File Creation Failed",
          JOptionPane.ERROR_MESSAGE);
        return;
      }
    }
    
    // Copy the data and close file.
    BufferedInputStream is = null;
    BufferedOutputStream os = null;
    
    try {
      is = new BufferedInputStream(
            new FileInputStream(srcFile));
      os = new BufferedOutputStream(
            new FileOutputStream(newFile));
      int size = 4096;
      byte[] buffer = new byte[size];
      int len;
      while ((len = is.read(buffer, 0, size)) > 0) {
        os.write(buffer, 0, len);
      }
    } catch (IOException e) {
      JOptionPane.showMessageDialog(tree, 
          "Failed to copy file\n  " +
          name + "\nto directory\n  " +
          targetDirectory.getAbsolutePath(),
          "File Copy Failed",
          JOptionPane.ERROR_MESSAGE);
      return;
    } finally {
      try {
        if (is != null) {
          is.close();
        }
        if (os != null) {
          os.close();
        }
      } catch (IOException e) {
      }      
    }
    
    // Remove the source if this is a move operation.
    if (action == DnDConstants.ACTION_MOVE &&
      System.getProperty("DnDExamples.allowRemove") != null) {
      srcFile.delete();
    }
    
    // Update the tree display
    if (targetNode != null) {
      tree.addNode(targetNode, name);
    }
  }
  protected void transferDirectory(int action, File srcDir,
                File targetDirectory,
                FileTree.FileTreeNode targetNode) {
    DnDUtils.debugPrintln(
            (action == DnDConstants.ACTION_COPY ? "Copy" : "Move") +
            " directory " + srcDir.getAbsolutePath() +
            " to " + targetDirectory.getAbsolutePath());
    // Do not copy a directory into itself or 
    // a subdirectory of itself.
    File parentDir = targetDirectory;
    while (parentDir != null) {
      if (parentDir.equals(srcDir)) {
        DnDUtils.debugPrintln("-- SUPPRESSED");
        return;
      }
      parentDir = parentDir.getParentFile();
    }
    
    // Copy the directory itself, then its contents
    
    // Create a File entry for the target
    String name = srcDir.getName();
    File newDir = new File(targetDirectory, name);
    if (newDir.exists()) {
      // Already exists - is it the same directory?
      if (newDir.equals(srcDir)) {
        // Exactly the same file - ignore
        return;
      }
    } else {
      // Directory does not exist - create it
      if (newDir.mkdir() == false) {
        // Failed to create - abandon this directory
        JOptionPane.showMessageDialog(tree, 
          "Failed to create target directory\n  " +
          newDir.getAbsolutePath(),
          "Directory creation Failed",
          JOptionPane.ERROR_MESSAGE);
        return;    
      }
    }
    
    // Add a node for the new directory
    if (targetNode != null) {
      targetNode = tree.addNode(targetNode, name);
    }
    
    // Now copy the directory content.
    File[] files = srcDir.listFiles();
    for (int i = 0; i < files.length; i++) {
      File f = files[i];
      if (f.isFile()) {
        transferFile(action, f, newDir, targetNode);
      } else if (f.isDirectory()) {
        transferDirectory(action, f, newDir, targetNode);
      }
    }
    
    // Remove the source directory after moving
    if (action == DnDConstants.ACTION_MOVE &&
      System.getProperty("DnDExamples.allowRemove") != null) {
      srcDir.delete();
    }
  }
  
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    final JFrame f = new JFrame("FileTree Drop Target Example");
    try {
      final FileTree tree = new FileTree("D:\\");
      
      // Add a drop target to the FileTree
      FileTreeDropTarget target = new FileTreeDropTarget(tree);
      tree.setEditable(true);
      f.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent evt) {
          System.exit(0);
        }
      });
      JPanel panel = new JPanel();
      final JCheckBox editable = new JCheckBox("Editable");
      editable.setSelected(true);
      panel.add(editable);
      editable.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          tree.setEditable(editable.isSelected());
        }
      });
      
      final JCheckBox enabled = new JCheckBox("Enabled");
      enabled.setSelected(true);
      panel.add(enabled);
      enabled.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          tree.setEnabled(enabled.isSelected());
        }
      });
      
      f.getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
      f.getContentPane().add(panel, BorderLayout.SOUTH);
      f.setSize(500, 400);
      f.setVisible(true);
    } catch (Exception e) {
      System.out.println("Failed to build GUI: " + e);
    }
  }
  protected FileTree tree;
  protected DropTarget dropTarget;
  protected boolean acceptableType;  // Indicates whether data is acceptable
  TreePath[] selections;        // Initially selected rows
  TreePath leadSelection;        // Initial lead selection
  boolean copyOverExistingFiles;    
}


class FileTree extends JTree implements Autoscroll {
  public static final Insets defaultScrollInsets = new Insets(8, 8, 8, 8);
  protected Insets scrollInsets = defaultScrollInsets;
  public FileTree(String path) throws FileNotFoundException, SecurityException {
    super((TreeModel)null);      // Create the JTree itself
    // Use horizontal and vertical lines
    putClientProperty("JTree.lineStyle", "Angled");
    
    // Create the first node
    FileTreeNode rootNode = new FileTreeNode(null, path);
    
    // Populate the root node with its subdirectories
    boolean addedNodes = rootNode.populateDirectories(true);
    setModel(new DefaultTreeModel(rootNode));
    // Listen for Tree Selection Events
    addTreeExpansionListener(new TreeExpansionHandler());
  }
  // Returns the full pathname for a path, or null if not a known path
  public String getPathName(TreePath path) {
    Object o = path.getLastPathComponent();
    if (o instanceof FileTreeNode) {
      return ((FileTreeNode)o).fullName;
    }
    return null;
  }
  
  // Adds a new node to the tree after construction.
  // Returns the inserted node, or null if the parent
  // directory has not been expanded.
  public FileTreeNode addNode(FileTreeNode parent, String name) {
    int index = parent.addNode(name);
    if (index != -1) {
      ((DefaultTreeModel)getModel()).nodesWereInserted(
              parent, new int[] { index });
      return (FileTreeNode)parent.getChildAt(index);
    }
    
    // No node was created
    return null;
  }
  
  // Autoscrolling support
  public void setScrollInsets(Insets insets) {
    this.scrollInsets = insets;
  }
  public Insets getScrollInsets() {
    return scrollInsets;
  }
  // Implementation of Autoscroll interface
  public Insets getAutoscrollInsets() {
    Rectangle r = getVisibleRect();
    Dimension size = getSize();
    Insets i = new Insets(r.y + scrollInsets.top, r.x + scrollInsets.left, 
        size.height - r.y - r.height + scrollInsets.bottom, 
        size.width - r.x - r.width + scrollInsets.right);
    return i;
  }
  public void autoscroll(Point location) {
    JScrollPane scroller = 
        (JScrollPane)SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
    if (scroller != null) {
      JScrollBar hBar = scroller.getHorizontalScrollBar();
      JScrollBar vBar = scroller.getVerticalScrollBar();
      Rectangle r = getVisibleRect();
      if (location.x <= r.x + scrollInsets.left) {
        // Need to scroll left
        hBar.setValue(hBar.getValue() - hBar.getUnitIncrement(-1));
      }
      if (location.y <= r.y + scrollInsets.top) {
        // Need to scroll up
        vBar.setValue(vBar.getValue() - vBar.getUnitIncrement(-1));
      }
      if (location.x >= r.x + r.width - scrollInsets.right) {
        // Need to scroll right
        hBar.setValue(hBar.getValue() + hBar.getUnitIncrement(1));
      }
      if (location.y >= r.y + r.height - scrollInsets.bottom) {
        // Need to scroll down
        vBar.setValue(vBar.getValue() + vBar.getUnitIncrement(1));
      }
    }
  }
  // Inner class that represents a node in this file system tree
  public static class FileTreeNode extends DefaultMutableTreeNode {
    public FileTreeNode(String parent, String name) throws SecurityException,
                              FileNotFoundException {
      this.name = name;
      
      // See if this node exists and whether it is a directory
      fullName = parent == null ? name : parent + File.separator + name;      
      File f = new File(fullName);
      if (f.exists() == false) {
        throw new FileNotFoundException("File " + fullName + " does not exist");
      }
      isDir = f.isDirectory();
      // Hack for Windows which doesn"t consider a drive to be a directory!
      if (isDir == false && f.isFile() == false) {
        isDir = true;
      }      
    }
    // Override isLeaf to check whether this is a directory
    public boolean isLeaf() {
      return !isDir;
    }
    // Override getAllowsChildren to check whether this is a directory
    public boolean getAllowsChildren() {
      return isDir;
    }
    // Return whether this is a directory
    public boolean isDir() {
      return isDir;
    }
    // Get full path
    public String getFullName() {
      return fullName;
    }
    // For display purposes, we return our own name
    public String toString() {      
      return name;
    }
    // If we are a directory, scan our contents and populate 
    // with children. In addition, populate those children
    // if the "descend" flag is true. We only descend once,
    // to avoid recursing the whole subtree. 
    // Returns true if some nodes were added
    boolean populateDirectories(boolean descend) {
      boolean addedNodes = false;
      // Do this only once
      if (populated == false) {
        File f;
        try {
          f = new File(fullName);          
        } catch (SecurityException e) {
          populated = true;
          return false;
        }
        if (interim == true) {
          // We have had a quick look here before:
          // remove the dummy node that we added last time
          removeAllChildren();
          interim = false;          
        }        
        
        String[] names = f.list();    // Get list of contents
        
        // Process the contents
        ArrayList list = new ArrayList();          
        for (int i = 0; i < names.length; i++) {
          String name = names[i];
          File d = new File(fullName, name);
          try {
            FileTreeNode node = new FileTreeNode(fullName, name);
            list.add(node);
            if (descend && d.isDirectory()) {
              node.populateDirectories(false);
            }
            addedNodes = true;
            if (descend == false) {
              // Only add one node if not descending
              break;
            }
          } catch (Throwable t) {
            // Ignore phantoms or access problems
          }
        }
        if (addedNodes == true) {
          // Now sort the list of contained files and directories
          Object[] nodes = list.toArray();
          Arrays.sort(nodes, new Comparator() {
            public boolean equals(Object o) {
              return false;
            }
            public int compare(Object o1, Object o2) {
              FileTreeNode node1 = (FileTreeNode)o1;
              FileTreeNode node2 = (FileTreeNode)o2;
              // Directories come first
              if (node1.isDir != node2.isDir) {
                return node1.isDir ? -1 : +1;
              }
              // Both directories or both files -
              // compare based on pathname
              return node1.fullName.rupareTo(node2.fullName);
            }
          });
          
          // Add sorted items as children of this node
          for (int j = 0; j < nodes.length; j++) {
            this.add((FileTreeNode)nodes[j]);
          }
        }
        
        // If we were scanning to get all subdirectories,
        // or if we found no content, there is no
        // reason to look at this directory again, so
        // set populated to true. Otherwise, we set interim
        // so that we look again in the future if we need to
        if (descend == true || addedNodes == false) {
          populated = true;          
        } else {
          // Just set interim state
          interim = true;          
        }
      }
      return addedNodes;
    }
    
    // Adding a new file or directory after
    // constructing the FileTree. Returns
    // the index of the inserted node.
    public int addNode(String name) {
      // If not populated yet, do nothing
      if (populated == true) {
        // Do not add a new node if
        // the required node is already there
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
          FileTreeNode node = (FileTreeNode)getChildAt(i);
          if (node.name.equals(name)) {
            // Already exists - ensure
            // we repopulate
            if (node.isDir()) {
              node.interim = true;
              node.populated = false;
            }
            return -1;
          }
        }
        
        // Add a new node
        try {
          FileTreeNode node = new FileTreeNode(fullName, name);
          add(node);
          return childCount;
        } catch (Exception e) {
        }
      }
      return -1;
    }
    protected String name;    // Name of this component
    protected String fullName;  // Full pathname
    protected boolean populated;// true if we have been populated
    protected boolean interim;  // true if we are in interim state
    protected boolean isDir;  // true if this is a directory
  }
  // Inner class that handles Tree Expansion Events
  protected class TreeExpansionHandler implements TreeExpansionListener {
    public void treeExpanded(TreeExpansionEvent evt) {
      TreePath path = evt.getPath();      // The expanded path
      JTree tree = (JTree)evt.getSource();  // The tree
      // Get the last component of the path and
      // arrange to have it fully populated.
      FileTreeNode node = (FileTreeNode)path.getLastPathComponent();
      if (node.populateDirectories(true)) {
        ((DefaultTreeModel)tree.getModel()).nodeStructureChanged(node);  
      }
    }
    public void treeCollapsed(TreeExpansionEvent evt) {
      // Nothing to do
    }
  }
}
class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK|DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = 
    (System.getProperty("DnDExamples.debug") != null);
}





Getting and Setting Text on the System Clipboard

 
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
public class Main {
  public static void main(String[] argv) throws Exception {
    Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
    if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      String text = (String) t.getTransferData(DataFlavor.stringFlavor);
      System.out.println(text);
    }
  }
}





Implement drag & drop functionality in your application

 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
public class Main extends JFrame implements DropTargetListener {
  DropTarget dt;
  JTextArea ta = new JTextArea();
  public Main() {
    super("Drop Test");
    setSize(300, 300);
    getContentPane()
        .add(new JLabel("Drop something here:"), BorderLayout.NORTH);
    
    ta.setBackground(Color.white);
    getContentPane().add(ta, BorderLayout.CENTER);
    dt = new DropTarget(ta, this);
    setVisible(true);
  }
  public void dragEnter(DropTargetDragEvent dtde) {
    System.out.println("Drag Enter");
  }
  public void dragExit(DropTargetEvent dte) {
    System.out.println("Drag Exit");
  }
  public void dragOver(DropTargetDragEvent dtde) {
    System.out.println("Drag Over");
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    System.out.println("Drop Action Changed");
  }
  public void drop(DropTargetDropEvent dtde) {
    try {
      Transferable tr = dtde.getTransferable();
      DataFlavor[] flavors = tr.getTransferDataFlavors();
      for (int i = 0; i < flavors.length; i++) {
        if (flavors[i].isFlavorJavaFileListType()) {
          dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
          List list = (List) tr.getTransferData(flavors[i]);
          for (int j = 0; j < list.size(); j++) {
            ta.append(list.get(j) + "\n");
          }
          dtde.dropComplete(true);
          return;
        } else if (flavors[i].isFlavorSerializedObjectType()) {
          dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
          Object o = tr.getTransferData(flavors[i]);
          ta.append("Object: " + o);
          dtde.dropComplete(true);
          return;
        } else if (flavors[i].isRepresentationClassInputStream()) {
          dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
          ta.read(new InputStreamReader((InputStream) tr.getTransferData(flavors[i])),
              "from system clipboard");
          dtde.dropComplete(true);
          return;
        }
      }
      dtde.rejectDrop();
    } catch (Exception e) {
      e.printStackTrace();
      dtde.rejectDrop();
    }
  }
  public static void main(String args[]) {
    new Main();
  }
}





implements DragGestureListener, Transferable

 
import java.awt.Cursor;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class DragGesture extends JFrame implements DragGestureListener, Transferable {
  public DragGesture() {
    setTitle("Drag Gesture");
    JLabel left = new JLabel("text");
    DragSource ds = new DragSource();
    ds.createDefaultDragGestureRecognizer(left, DnDConstants.ACTION_COPY, this);
    add(left);
    pack();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
  }
  public void dragGestureRecognized(DragGestureEvent event) {
    Cursor cursor = null;
    if (event.getDragAction() == DnDConstants.ACTION_COPY) {
      cursor = DragSource.DefaultCopyDrop;
    }
    event.startDrag(cursor, this);
  }
  public Object getTransferData(DataFlavor flavor) {
    return null;
  }
  public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[0];
  }
  public boolean isDataFlavorSupported(DataFlavor flavor) {
    return false;
  }
  public static void main(String[] args) {
    new DragGesture();
  }
}





JLabel Drag Source

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Font;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
public class JLabelDragSource implements DragGestureListener,
    DragSourceListener {
  public JLabelDragSource(JLabel label) {
    this.label = label;
    // Use the default DragSource
    DragSource dragSource = DragSource.getDefaultDragSource();
    // Create a DragGestureRecognizer and
    // register as the listener
    dragSource.createDefaultDragGestureRecognizer(label,
        DnDConstants.ACTION_COPY_OR_MOVE, this);
  }
  // Implementation of DragGestureListener interface.
  public void dragGestureRecognized(DragGestureEvent dge) {
    if (DnDUtils.isDebugEnabled()) {
      DnDUtils.debugPrintln("Initiating event is "
          + dge.getTriggerEvent());
      DnDUtils.debugPrintln("Complete event set is:");
      Iterator iter = dge.iterator();
      while (iter.hasNext()) {
        DnDUtils.debugPrintln("\t" + iter.next());
      }
    }
    Transferable transferable = new JLabelTransferable(label);
    dge.startDrag(null, transferable, this);
  }
  // Implementation of DragSourceListener interface
  public void dragEnter(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dragEnter, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragOver(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dragOver, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragExit(DragSourceEvent dse) {
    DnDUtils.debugPrintln("Drag Source: dragExit");
  }
  public void dropActionChanged(DragSourceDragEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: dropActionChanged, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()));
  }
  public void dragDropEnd(DragSourceDropEvent dsde) {
    DnDUtils.debugPrintln("Drag Source: drop completed, drop action = "
        + DnDUtils.showActions(dsde.getDropAction()) + ", success: "
        + dsde.getDropSuccess());
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Draggable JLabel");
    JLabel label = new JLabel("Drag this text", JLabel.CENTER);
    label.setFont(new Font("Serif", Font.BOLD, 32));
    f.getContentPane().add(label);
    f.pack();
    f.setVisible(true);
    // Attach the drag source
    JLabelDragSource dragSource = new JLabelDragSource(label);
  }
  protected JLabel label; // The associated JLabel
}
class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK | DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = (System
      .getProperty("DnDExamples.debug") != null);
}
class JLabelTransferable implements Transferable {
  public JLabelTransferable(JLabel label) {
    this.label = label;
  }
  // Implementation of the Transferable interface
  public DataFlavor[] getTransferDataFlavors() {
    return flavors;
  }
  public boolean isDataFlavorSupported(DataFlavor fl) {
    for (int i = 0; i < flavors.length; i++) {
      if (fl.equals(flavors[i])) {
        return true;
      }
    }
    return false;
  }
  public Object getTransferData(DataFlavor fl) {
    if (!isDataFlavorSupported(fl)) {
      return null;
    }
    if (fl.equals(DataFlavor.stringFlavor)) {
      // String - return the text as a String
      return label.getText() + " (DataFlavor.stringFlavor)";
    } else if (fl.equals(jLabelFlavor)) {
      // The JLabel itself - just return the label.
      return label;
    } else {
      // Plain text - return an InputStream
      try {
        String targetText = label.getText() + " (plain text flavor)";
        int length = targetText.length();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStreamWriter w = new OutputStreamWriter(os);
        w.write(targetText, 0, length);
        w.flush();
        byte[] bytes = os.toByteArray();
        w.close();
        return new ByteArrayInputStream(bytes);
      } catch (IOException e) {
        return null;
      }
    }
  }
  // A flavor that transfers a copy of the JLabel
  public static final DataFlavor jLabelFlavor = new DataFlavor(JLabel.class,
      "Swing JLabel");
  private JLabel label; // The label being transferred
  private static final DataFlavor[] flavors = new DataFlavor[] {
      DataFlavor.stringFlavor,
      new DataFlavor("text/plain; charset=ascii", "ASCII text"),
      jLabelFlavor };
}





JTextArea subclass allows TransferableColor objects to

 
/*
 * This example is from the book "Java Foundation Classes in a Nutshell".
 * Written by David Flanagan. Copyright (c) 1999 by O"Reilly & Associates.  
 * You may distribute this source code for non-commercial purposes only.
 * You may study, modify, and use this example for any purpose, as long as
 * this notice is retained.  Note that this example is provided "as is",
 * WITHOUT WARRANTY of any kind either expressed or implied.
 */
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.*;
import java.util.List;
/** 
 * This simple JTextArea subclass allows TransferableColor objects to
 * be pasted or dropped into it.  It also supports the pasting of
 * text, and the dropping of File objects.  
 */
public class ColorSink extends JTextArea implements DropTargetListener {
  /** Create a new ColorSink object */
  public ColorSink() {
    // Listen for double clicks.  Use them to trigger a paste action.
    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) { pastecolor(); e.consume(); }
      }
    });
    
    // We have to create a DropTarget object to support Drag-and-Drop
    // It will listen for drops on top of us, and notify our DropTargetListener
    // methods when drag-and-drop related events occur.
    setDropTarget(new DropTarget(this, this));
  }
  // This method is invoked when the user double-clicks on us.  It attempts
  // to paste a color or text.  Note that the JTextArea we extend
  // already supports cut-and-paste of text through the Ctrl-V keystroke.
  // This adds a different kind of cut-and-paste for demonstration purposes.
  public void pastecolor() {
    // Get the clipboard, and read its contents
    Clipboard c = this.getToolkit().getSystemClipboard();
    Transferable t = c.getContents(this);
    if (t == null) {             // If nothing to paste
      this.getToolkit().beep();  // then beep and do nothing
      return;
    }
    try {
      // If the clipboard contained a color, use it as the background color
      if (t.isDataFlavorSupported(TransferableColor.colorFlavor)) {
        Color color = (Color) t.getTransferData(TransferableColor.colorFlavor);
        this.setBackground(color);
      }
      // If the clipboard contained text, insert it.
      else if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
        String s = (String) t.getTransferData(DataFlavor.stringFlavor);
        this.replaceSelection(s);
      }
      // Otherwise, we don"t know how to paste the data, so just beep.
      else this.getToolkit().beep();
    }
    catch (UnsupportedFlavorException ex) { this.getToolkit().beep(); }
    catch (IOException ex) { this.getToolkit().beep(); }
  }
  // The methods below are the methods of DropTargetListener.
  // They are invoked at various times when something is being
  // dragged over us, and allow us an opportunity to respond to the drag
  // This is the border we display when the user is dragging over us.
  protected static Border dropBorder = new BevelBorder(BevelBorder.LOWERED);
  // Something is being dragged over us.  If we can support this data type
  // tell the drag-and-drop system that we are interested, and display
  // a special border to tell the user that we"re intereted.
  public void dragEnter(DropTargetDragEvent e) {
    if (e.isDataFlavorSupported(TransferableColor.colorFlavor) ||
        e.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      e.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
      this.setBorder(dropBorder);
    }
  }
  /** The user is no longer dragging over us, so restore the default border */
  public void dragExit(DropTargetEvent e) { this.setBorder(null); }
  
  /** This method is invoked when the user drops something on us */
  public void drop(DropTargetDropEvent e){
    this.setBorder(null);                  // Restore the default border
    Transferable t = e.getTransferable();  // Get the data that was dropped
    // Check for types of data that we support
    if (t.isDataFlavorSupported(TransferableColor.colorFlavor)) {
      // If it was a color, accept it, and use it as the background color
      e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
      try {
        Color c = (Color) t.getTransferData(TransferableColor.colorFlavor);
        this.setBackground(c);
        e.dropComplete(true);
      }
      catch (Exception ex) { e.dropComplete(false); }
    }
    else if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      // If it was a file list, accept it, read the first file in the list
      // and display the file contents
      e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
      try {
        List files = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
        File f = (File) files.get(0);
        BufferedReader in = new BufferedReader(new FileReader(f));
        String s;
        this.setText("");
        while((s = in.readLine()) != null) this.append(s);
        e.dropComplete(true);
      }
      catch (Exception ex) { e.dropComplete(false); }
    }
    else {  // If it wasn"t a color or a file list, reject it.
      e.rejectDrop();
      return;
    }
  }
  // These are unused DropTargetListener methods
  public void dragOver(DropTargetDragEvent e) {}
  public void dropActionChanged(DropTargetDragEvent e) {}
  /** This is a simple test program for ColorSource and ColorSink */
  public static void main(String[] args) {
    // Create a window
    JFrame f = new JFrame("ColorSourceTest");
    f.getContentPane().setLayout(new BorderLayout());
    // Add some ColorSources
    JPanel panel = new JPanel();
    f.getContentPane().add(panel, BorderLayout.NORTH);
    panel.add(new ColorSource(Color.yellow));
    panel.add(new ColorSource(Color.pink));
    panel.add(new ColorSource(Color.white));
    panel.add(new ColorSource(Color.gray));
    // Add a ColorSink
    ColorSink sink = new ColorSink();
    f.getContentPane().add(sink, BorderLayout.CENTER);
    // Pop it all up
    f.setSize(400, 300);
    f.show();
  }
}





LabelDnD2 allows dropping color onto the foreground of the JLabel

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * LabelDnD2.java is a 1.4 example that requires no other files.
 */
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.TransferHandler;
import javax.swing.border.TitledBorder;
//LabelDnD2 allows dropping color onto the foreground
//of the JLabel.
public class LabelDnD2 extends JPanel {
  JTextField textField;
  JLabel label;
  public LabelDnD2() {
    super(new BorderLayout());
    JColorChooser chooser = new JColorChooser();
    chooser.setDragEnabled(true);
    label = new JLabel("I"m a Label and I accept color!",
        SwingConstants.LEADING);
    label.setTransferHandler(new TransferHandler("foreground"));
    MouseListener listener = new DragMouseAdapter();
    label.addMouseListener(listener);
    JPanel lpanel = new JPanel(new GridLayout(1, 1));
    TitledBorder t2 = BorderFactory
        .createTitledBorder("JLabel: drop color onto the label");
    lpanel.add(label);
    lpanel.setBorder(t2);
    add(chooser, BorderLayout.CENTER);
    add(lpanel, BorderLayout.PAGE_END);
    setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  }
  private class DragMouseAdapter extends MouseAdapter {
    public void mousePressed(MouseEvent e) {
      JComponent c = (JComponent) e.getSource();
      TransferHandler handler = c.getTransferHandler();
      handler.exportAsDrag(c, e, TransferHandler.COPY);
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("LabelDnD2");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    JComponent newContentPane = new LabelDnD2();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}





Label DnD (Drag and Drop)

 
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * LabelDnD.java is a 1.4 example that requires no other files.
 */
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.TransferHandler;
import javax.swing.border.TitledBorder;
public class LabelDnD extends JPanel {
  JTextField textField;
  JLabel label;
  public LabelDnD() {
    super(new GridLayout(2, 1));
    textField = new JTextField(40);
    textField.setDragEnabled(true);
    JPanel tfpanel = new JPanel(new GridLayout(1, 1));
    TitledBorder t1 = BorderFactory
        .createTitledBorder("JTextField: drag and drop is enabled");
    tfpanel.add(textField);
    tfpanel.setBorder(t1);
    label = new JLabel("I"m a Label!", SwingConstants.LEADING);
    label.setTransferHandler(new TransferHandler("text"));
    MouseListener listener = new DragMouseAdapter();
    label.addMouseListener(listener);
    JPanel lpanel = new JPanel(new GridLayout(1, 1));
    TitledBorder t2 = BorderFactory
        .createTitledBorder("JLabel: drag from or drop to this label");
    lpanel.add(label);
    lpanel.setBorder(t2);
    add(tfpanel);
    add(lpanel);
    setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  }
  private class DragMouseAdapter extends MouseAdapter {
    public void mousePressed(MouseEvent e) {
      JComponent c = (JComponent) e.getSource();
      TransferHandler handler = c.getTransferHandler();
      handler.exportAsDrag(c, e, TransferHandler.COPY);
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("LabelDnD");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    JComponent newContentPane = new LabelDnD();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}





Making a Component Draggable

 
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Main {
  public static void main(String[] argv) throws Exception {
    JComponent com = new DraggableComponent();
    JFrame f = new JFrame();
    f.add(com);
    f.setSize(300, 300);
    f.setVisible(true);
  }
}
class DraggableComponent extends JComponent implements DragGestureListener, DragSourceListener {
  DragSource dragSource;
  public DraggableComponent() {
    dragSource = new DragSource();
    dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
  }
  public void dragGestureRecognized(DragGestureEvent evt) {
    Transferable t = new StringSelection("aString");
    dragSource.startDrag(evt, DragSource.DefaultCopyDrop, t, this);
  }
  public void dragEnter(DragSourceDragEvent evt) {
    System.out.println("enters");
  }
  public void dragOver(DragSourceDragEvent evt) {
    System.out.println("over");
  }
  public void dragExit(DragSourceEvent evt) {
    System.out.println("leaves");
  }
  public void dropActionChanged(DragSourceDragEvent evt) {
    System.out.println("changes the drag action between copy or move");
  }
  public void dragDropEnd(DragSourceDropEvent evt) {
    System.out.println("finishes or cancels the drag operation");
  }
}





Panel Drop Target

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
public class PanelDropTarget implements DropTargetListener {
  public PanelDropTarget(JPanel pane) {
    this.pane = pane;
    // Create the DropTarget and register
    // it with the JPanel.
    dropTarget = new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE,
        this, true, null);
  }
  // Implementation of the DropTargetListener interface
  public void dragEnter(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("dragEnter, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Get the type of object being transferred and determine
    // whether it is appropriate.
    checkTransferType(dtde);
    // Accept or reject the drag.
    acceptOrRejectDrag(dtde);
  }
  public void dragExit(DropTargetEvent dte) {
    DnDUtils.debugPrintln("DropTarget dragExit");
  }
  public void dragOver(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dragOver, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    acceptOrRejectDrag(dtde);
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
    DnDUtils.debugPrintln("DropTarget dropActionChanged, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Accept or reject the drag
    acceptOrRejectDrag(dtde);
  }
  public void drop(DropTargetDropEvent dtde) {
    DnDUtils.debugPrintln("DropTarget drop, drop action = "
        + DnDUtils.showActions(dtde.getDropAction()));
    // Check the drop action
    if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
      // Accept the drop and get the transfer data
      dtde.acceptDrop(dtde.getDropAction());
      Transferable transferable = dtde.getTransferable();
      try {
        boolean result = dropComponent(transferable);
        dtde.dropComplete(result);
        DnDUtils.debugPrintln("Drop completed, success: " + result);
      } catch (Exception e) {
        DnDUtils.debugPrintln("Exception while handling drop " + e);
        dtde.dropComplete(false);
      }
    } else {
      DnDUtils.debugPrintln("Drop target rejected drop");
      dtde.rejectDrop();
    }
  }
  // Internal methods start here
  protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
    int dropAction = dtde.getDropAction();
    int sourceActions = dtde.getSourceActions();
    boolean acceptedDrag = false;
    DnDUtils.debugPrintln("\tSource actions are "
        + DnDUtils.showActions(sourceActions) + ", drop action is "
        + DnDUtils.showActions(dropAction));
    // Reject if the object being transferred
    // or the operations available are not acceptable.
    if (!acceptableType
        || (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      DnDUtils.debugPrintln("Drop target rejecting drag");
      dtde.rejectDrag();
    } else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
      // Not offering copy or move - suggest a copy
      DnDUtils.debugPrintln("Drop target offering COPY");
      dtde.acceptDrag(DnDConstants.ACTION_COPY);
      acceptedDrag = true;
    } else {
      // Offering an acceptable operation: accept
      DnDUtils.debugPrintln("Drop target accepting drag");
      dtde.acceptDrag(dropAction);
      acceptedDrag = true;
    }
    return acceptedDrag;
  }
  protected void checkTransferType(DropTargetDragEvent dtde) {
    // Only accept a flavor that returns a Component
    acceptableType = false;
    DataFlavor[] fl = dtde.getCurrentDataFlavors();
    for (int i = 0; i < fl.length; i++) {
      Class dataClass = fl[i].getRepresentationClass();
      if (Component.class.isAssignableFrom(dataClass)) {
        // This flavor returns a Component - accept it.
        targetFlavor = fl[i];
        acceptableType = true;
        break;
      }
    }
    DnDUtils.debugPrintln("File type acceptable - " + acceptableType);
  }
  protected boolean dropComponent(Transferable transferable)
      throws IOException, UnsupportedFlavorException {
    Object o = transferable.getTransferData(targetFlavor);
    if (o instanceof Component) {
      DnDUtils.debugPrintln("Dragged component class is "
          + o.getClass().getName());
      pane.add((Component) o);
      pane.validate();
      return true;
    }
    return false;
  }
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    final JFrame f = new JFrame("Component drop target example");
    JPanel pane = new JPanel();
    // Add a drop target to the JPanel
    PanelDropTarget target = new PanelDropTarget(pane);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.getContentPane().add(new JScrollPane(pane), BorderLayout.CENTER);
    f.setSize(500, 400);
    f.setVisible(true);
  }
  protected JPanel pane;
  protected DropTarget dropTarget;
  protected boolean acceptableType; // Indicates whether data is acceptable
  protected DataFlavor targetFlavor; // Flavor to use for transfer
}
class DnDUtils {
  public static String showActions(int action) {
    String actions = "";
    if ((action & (DnDConstants.ACTION_LINK | DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
      return "None";
    }
    if ((action & DnDConstants.ACTION_COPY) != 0) {
      actions += "Copy ";
    }
    if ((action & DnDConstants.ACTION_MOVE) != 0) {
      actions += "Move ";
    }
    if ((action & DnDConstants.ACTION_LINK) != 0) {
      actions += "Link";
    }
    return actions;
  }
  public static boolean isDebugEnabled() {
    return debugEnabled;
  }
  public static void debugPrintln(String s) {
    if (debugEnabled) {
      System.out.println(s);
    }
  }
  private static boolean debugEnabled = (System
      .getProperty("DnDExamples.debug") != null);
}





Setting text drag in a JTextArea

  
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Main {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    JTextArea textarea = new JTextArea();
    textarea.setDragEnabled(true);
    textarea.setText("Drag target");
    frame.getContentPane().add(BorderLayout.CENTER, textarea);
    JTextField textarea1 = new JTextField();
    textarea1.setText("Drop target");
    frame.getContentPane().add(BorderLayout.SOUTH, textarea1);
    frame.setSize(500, 300);
    frame.setVisible(true);
    frame.setLocation(100, 100);
  }
}





Test of the DragGesture classes and JList to see if we

 
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// GestureTest.java
//A simple (?) test of the DragGesture classes to see if we
//can recognize a simple drag gesture.
//
import java.awt.BorderLayout;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
public class GestureTest extends JFrame implements DragGestureListener {
  DragSource ds;
  JList jl;
  String[] items = { "Java", "C", "C++", "Lisp", "Perl", "Python" };
  public GestureTest() {
    super("Gesture Test");
    setSize(200, 150);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent we) {
        System.exit(0);
      }
    });
    jl = new JList(items);
    jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    getContentPane().add(new JScrollPane(jl), BorderLayout.CENTER);
    ds = new DragSource();
    DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(jl,
        DnDConstants.ACTION_COPY, this);
    setVisible(true);
  }
  public void dragGestureRecognized(DragGestureEvent dge) {
    System.out.println("Drag Gesture Recognized!");
  }
  public static void main(String args[]) {
    new GestureTest();
  }
}





Transferable Color

 
/*
 * This example is from the book "Java Foundation Classes in a Nutshell".
 * Written by David Flanagan. Copyright (c) 1999 by O"Reilly & Associates.  
 * You may distribute this source code for non-commercial purposes only.
 * You may study, modify, and use this example for any purpose, as long as
 * this notice is retained.  Note that this example is provided "as is",
 * WITHOUT WARRANTY of any kind either expressed or implied.
 */
import java.awt.Color;
import java.awt.datatransfer.*;
import java.io.*;
/**
 * This class is used to transfer a Color object via cut-and-paste or
 * drag-and-drop.  It allows a color to be transfered as a Color object,
 * or as a string. Due to a long-standing bug in Java 1.1 and Java 2, 
 * transferring a color as a string to native Windows applications will
 * not work.
 */
public class TransferableColor implements Transferable {
  // This DataFlavor object is used when we transfer Color objects directly
  protected static DataFlavor colorFlavor =
    new DataFlavor(Color.class, "Java Color Object");
  // These are the data flavors we support.
  protected static DataFlavor[] supportedFlavors = {
    colorFlavor,                  // Transfer as a Color object
    DataFlavor.stringFlavor,      // Transfer as a String object
    DataFlavor.plainTextFlavor,   // Transfer as a stream of unicode text
  };
  Color color;                    // The color we encapsulate and transfer
  /** Create a new TransferableColor that encapsulates the specified color */
  public TransferableColor(Color color) { this.color = color; }
  /** Return a list of DataFlavors we can support */
  public DataFlavor[] getTransferDataFlavors() { return supportedFlavors; }
  /** Check whether a specified DataFlavor is available */
  public boolean isDataFlavorSupported(DataFlavor flavor) {
    if (flavor.equals(colorFlavor) || 
        flavor.equals(DataFlavor.stringFlavor) ||
        flavor.equals(DataFlavor.plainTextFlavor)) return true;
    return false;
  }
  /** 
   * Transfer the data.  Given a specified DataFlavor, return an Object
   * appropriate for that flavor.  Throw UnsupportedFlavorException if we
   * don"t support the requested flavor.
   */
  public Object getTransferData(DataFlavor flavor) 
       throws UnsupportedFlavorException, IOException
  {
    if (flavor.equals(colorFlavor)) return color;
    else if (flavor.equals(DataFlavor.stringFlavor)) return color.toString();
    else if (flavor.equals(DataFlavor.plainTextFlavor))
      return new ByteArrayInputStream(color.toString().getBytes("Unicode"));
    else throw new UnsupportedFlavorException(flavor);
  }
}





TransferHandler subclass wraps another TransferHandler and delegates most of its operations to the wrapped handler

 
 
/*
 * 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.ru/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);
  }
}





Use drag and drop to reorder a list

 

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.TransferHandler;
public class DragDropList extends JList {
  DefaultListModel model;
  public DragDropList() {
    super(new DefaultListModel());
    model = (DefaultListModel) getModel();
    setDragEnabled(true);
    setDropMode(DropMode.INSERT);
    setTransferHandler(new MyListDropHandler(this));
    new MyDragListener(this);
    
    model.addElement("a");
    model.addElement("b");
    model.addElement("c");
  }
  public static void main(String[] a){
    JFrame f = new JFrame();
    f.add(new JScrollPane(new DragDropList()));
    f.setSize(300,300);
    f.setVisible(true);
  }
}
class MyDragListener implements DragSourceListener, DragGestureListener {
  DragDropList list;
  DragSource ds = new DragSource();
  public MyDragListener(DragDropList list) {
    this.list = list;
    DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(list,
        DnDConstants.ACTION_MOVE, this);
  }
  public void dragGestureRecognized(DragGestureEvent dge) {
    StringSelection transferable = new StringSelection(Integer.toString(list.getSelectedIndex()));
    ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, this);
  }
  public void dragEnter(DragSourceDragEvent dsde) {
  }
  public void dragExit(DragSourceEvent dse) {
  }
  public void dragOver(DragSourceDragEvent dsde) {
  }
  public void dragDropEnd(DragSourceDropEvent dsde) {
    if (dsde.getDropSuccess()) {
      System.out.println("Succeeded");
    } else {
      System.out.println("Failed");
    }
  }
  public void dropActionChanged(DragSourceDragEvent dsde) {
  }
}
class MyListDropHandler extends TransferHandler {
  DragDropList list;
  public MyListDropHandler(DragDropList list) {
    this.list = list;
  }
  public boolean canImport(TransferHandler.TransferSupport support) {
    if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      return false;
    }
    JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
    if (dl.getIndex() == -1) {
      return false;
    } else {
      return true;
    }
  }
  public boolean importData(TransferHandler.TransferSupport support) {
    if (!canImport(support)) {
      return false;
    }
    Transferable transferable = support.getTransferable();
    String indexString;
    try {
      indexString = (String) transferable.getTransferData(DataFlavor.stringFlavor);
    } catch (Exception e) {
      return false;
    }
    int index = Integer.parseInt(indexString);
    JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
    int dropTargetIndex = dl.getIndex();
    System.out.println(dropTargetIndex + " : ");
    System.out.println("inserted");
    return true;
  }
}