Java tutorial
/* Java Swing, 2nd Edition By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole ISBN: 0-596-00408-7 Publisher: O'Reilly */ // TreeDragTest.java //A simple starting point for testing the DnD JTree code. // import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; 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.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 java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetContext; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.io.IOException; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class TreeDragTest extends JFrame { TreeDragSource ds; TreeDropTarget dt; JTree tree; public TreeDragTest() { super("Rearrangeable Tree"); setSize(300, 200); setDefaultCloseOperation(EXIT_ON_CLOSE); // If you want autoscrolling, use this line: tree = new AutoScrollingJTree(); // Otherwise, use this line: //tree = new JTree(); getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER); // If we only support move operations... //ds = new TreeDragSource(tree, DnDConstants.ACTION_MOVE); ds = new TreeDragSource(tree, DnDConstants.ACTION_COPY_OR_MOVE); dt = new TreeDropTarget(tree); setVisible(true); } public class AutoScrollingJTree extends JTree implements Autoscroll { private int margin = 12; public AutoScrollingJTree() { super(); } public void autoscroll(Point p) { int realrow = getRowForLocation(p.x, p.y); Rectangle outer = getBounds(); realrow = (p.y + outer.y <= margin ? realrow < 1 ? 0 : realrow - 1 : realrow < getRowCount() - 1 ? realrow + 1 : realrow); scrollRowToVisible(realrow); } public Insets getAutoscrollInsets() { Rectangle outer = getBounds(); Rectangle inner = getParent().getBounds(); return new Insets(inner.y - outer.y + margin, inner.x - outer.x + margin, outer.height - inner.height - inner.y + outer.y + margin, outer.width - inner.width - inner.x + outer.x + margin); } // Use this method if you want to see the boundaries of the // autoscroll active region public void paintComponent(Graphics g) { super.paintComponent(g); Rectangle outer = getBounds(); Rectangle inner = getParent().getBounds(); g.setColor(Color.red); g.drawRect(-outer.x + 12, -outer.y + 12, inner.width - 24, inner.height - 24); } } public static void main(String args[]) { new TreeDragTest(); } } //TreeDragSource.java //A drag source wrapper for a JTree. This class can be used to make //a rearrangeable DnD tree with the TransferableTreeNode class as the //transfer data type. class TreeDragSource implements DragSourceListener, DragGestureListener { DragSource source; DragGestureRecognizer recognizer; TransferableTreeNode transferable; DefaultMutableTreeNode oldNode; JTree sourceTree; public TreeDragSource(JTree tree, int actions) { sourceTree = tree; source = new DragSource(); recognizer = source.createDefaultDragGestureRecognizer(sourceTree, actions, this); } /* * Drag Gesture Handler */ public void dragGestureRecognized(DragGestureEvent dge) { TreePath path = sourceTree.getSelectionPath(); if ((path == null) || (path.getPathCount() <= 1)) { // We can't move the root node or an empty selection return; } oldNode = (DefaultMutableTreeNode) path.getLastPathComponent(); transferable = new TransferableTreeNode(path); source.startDrag(dge, DragSource.DefaultMoveNoDrop, transferable, this); // If you support dropping the node anywhere, you should probably // start with a valid move cursor: //source.startDrag(dge, DragSource.DefaultMoveDrop, transferable, // this); } /* * Drag Event Handlers */ public void dragEnter(DragSourceDragEvent dsde) { } public void dragExit(DragSourceEvent dse) { } public void dragOver(DragSourceDragEvent dsde) { } public void dropActionChanged(DragSourceDragEvent dsde) { System.out.println("Action: " + dsde.getDropAction()); System.out.println("Target Action: " + dsde.getTargetActions()); System.out.println("User Action: " + dsde.getUserAction()); } public void dragDropEnd(DragSourceDropEvent dsde) { /* * to support move or copy, we have to check which occurred: */ System.out.println("Drop Action: " + dsde.getDropAction()); if (dsde.getDropSuccess() && (dsde.getDropAction() == DnDConstants.ACTION_MOVE)) { ((DefaultTreeModel) sourceTree.getModel()).removeNodeFromParent(oldNode); } /* * to support move only... if (dsde.getDropSuccess()) { * ((DefaultTreeModel)sourceTree.getModel()).removeNodeFromParent(oldNode); } */ } } //TreeDropTarget.java //A quick DropTarget that's looking for drops from draggable JTrees. // class TreeDropTarget implements DropTargetListener { DropTarget target; JTree targetTree; public TreeDropTarget(JTree tree) { targetTree = tree; target = new DropTarget(targetTree, this); } /* * Drop Event Handlers */ private TreeNode getNodeForEvent(DropTargetDragEvent dtde) { Point p = dtde.getLocation(); DropTargetContext dtc = dtde.getDropTargetContext(); JTree tree = (JTree) dtc.getComponent(); TreePath path = tree.getClosestPathForLocation(p.x, p.y); return (TreeNode) path.getLastPathComponent(); } public void dragEnter(DropTargetDragEvent dtde) { TreeNode node = getNodeForEvent(dtde); if (node.isLeaf()) { dtde.rejectDrag(); } else { // start by supporting move operations //dtde.acceptDrag(DnDConstants.ACTION_MOVE); dtde.acceptDrag(dtde.getDropAction()); } } public void dragOver(DropTargetDragEvent dtde) { TreeNode node = getNodeForEvent(dtde); if (node.isLeaf()) { dtde.rejectDrag(); } else { // start by supporting move operations //dtde.acceptDrag(DnDConstants.ACTION_MOVE); dtde.acceptDrag(dtde.getDropAction()); } } public void dragExit(DropTargetEvent dte) { } public void dropActionChanged(DropTargetDragEvent dtde) { } public void drop(DropTargetDropEvent dtde) { Point pt = dtde.getLocation(); DropTargetContext dtc = dtde.getDropTargetContext(); JTree tree = (JTree) dtc.getComponent(); TreePath parentpath = tree.getClosestPathForLocation(pt.x, pt.y); DefaultMutableTreeNode parent = (DefaultMutableTreeNode) parentpath.getLastPathComponent(); if (parent.isLeaf()) { dtde.rejectDrop(); return; } try { Transferable tr = dtde.getTransferable(); DataFlavor[] flavors = tr.getTransferDataFlavors(); for (int i = 0; i < flavors.length; i++) { if (tr.isDataFlavorSupported(flavors[i])) { dtde.acceptDrop(dtde.getDropAction()); TreePath p = (TreePath) tr.getTransferData(flavors[i]); DefaultMutableTreeNode node = (DefaultMutableTreeNode) p.getLastPathComponent(); DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); model.insertNodeInto(node, parent, 0); dtde.dropComplete(true); return; } } dtde.rejectDrop(); } catch (Exception e) { e.printStackTrace(); dtde.rejectDrop(); } } } //TransferableTreeNode.java //A Transferable TreePath to be used with Drag & Drop applications. // class TransferableTreeNode implements Transferable { public static DataFlavor TREE_PATH_FLAVOR = new DataFlavor(TreePath.class, "Tree Path"); DataFlavor flavors[] = { TREE_PATH_FLAVOR }; TreePath path; public TransferableTreeNode(TreePath tp) { path = tp; } public synchronized DataFlavor[] getTransferDataFlavors() { return flavors; } public boolean isDataFlavorSupported(DataFlavor flavor) { return (flavor.getRepresentationClass() == TreePath.class); } public synchronized Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (isDataFlavorSupported(flavor)) { return (Object) path; } else { throw new UnsupportedFlavorException(flavor); } } }