Mega Code Archive

 
Categories / Java / Swing JFC
 

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.Comparator; 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.compareTo(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().compareTo(             ((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 }