package edu.harvard.wcfia.yoshikoder.ui; import java.awt.Point; 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 javax.swing.JTree; import javax.swing.tree.TreePath; import edu.harvard.wcfia.yoshikoder.dictionary.CategoryNode; import edu.harvard.wcfia.yoshikoder.dictionary.DuplicateException; import edu.harvard.wcfia.yoshikoder.dictionary.Node; import edu.harvard.wcfia.yoshikoder.dictionary.PatternNode; import edu.harvard.wcfia.yoshikoder.dictionary.YKDictionary; /** * Slightly augmented drag and drop code from O'Reilly's Swing book. * @author will */ public class TreeDropTarget implements DropTargetListener { DropTarget target; JTree targetTree; public TreeDropTarget(JTree tree) { targetTree = tree; target = new DropTarget(targetTree, this); } private Node getNodeForEvent(DropTargetDragEvent dtde){ Point p = dtde.getLocation(); TreePath path = targetTree.getClosestPathForLocation(p.x, p.y); return (Node)path.getLastPathComponent(); } // Drop event handlers public void dragEnter(DropTargetDragEvent dtde) { dragOver(dtde); } public void dragOver(DropTargetDragEvent dtde) { Node node = getNodeForEvent(dtde); if (node instanceof PatternNode) dtde.rejectDrag(); else dtde.acceptDrag(DnDConstants.ACTION_MOVE); } public void dragExit(DropTargetEvent dte) { } public void dropActionChanged(DropTargetDragEvent dtde) { } public void drop(DropTargetDropEvent dtde) { // Figure out where the drop occurred (in relation to the target tree). Point pt = dtde.getLocation(); TreePath parentpath = targetTree.getClosestPathForLocation(pt.x, pt.y); // For simplicity's sake, we'll assume that the tree uses the // DefaultTreeModel // and DefaultMutableTreeNode classes. Node parent = (Node)parentpath.getLastPathComponent(); // Now check to see if it was dropped on a folder. If not, reject it. if (parent instanceof PatternNode) { dtde.rejectDrop(); return; } try { // Grab the data. Transferable tr = dtde.getTransferable(); DataFlavor[] flavors = tr.getTransferDataFlavors(); for (int i = 0; i < flavors.length; i++) { if (tr.isDataFlavorSupported(flavors[i])) { // It's a usable node, so pull it out of the transferable // object and add it // to our tree. dtde.acceptDrop(DnDConstants.ACTION_MOVE); TreePath p = (TreePath)tr.getTransferData(flavors[i]); Node node = (Node)p.getLastPathComponent(); YKDictionary dict = (YKDictionary)targetTree.getModel(); if (node instanceof PatternNode) dict.addPattern((PatternNode)node, (CategoryNode)parent); else if (node instanceof CategoryNode) dict.addCategory((CategoryNode)node, (CategoryNode)parent); // Last but not least, mark the drop a success. dtde.dropComplete(true); return; } } dtde.rejectDrop(); } catch (DuplicateException de){ System.err.println("DuplicateException, probably caused by" + " dragging onto our parent"); dtde.rejectDrop(); } catch (Exception e) { e.printStackTrace(); // Just for debugging, really dtde.rejectDrop(); } } }