1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
|
package learninginterface;
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.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
public class DragAndDropTree extends JTree implements Autoscroll {
static final long serialVersionUID = 1L;
@SuppressWarnings("unused")
private TreeDragSource ds;
@SuppressWarnings("unused")
private TreeDropTarget dt;
private TreePath newPath;
private TreePath oldPath;
private int margin = 12;
public static DataFlavor TREE_PATH_FLAVOR = new DataFlavor(TreePath.class,"Tree Path");
public DragAndDropTree(DefaultTreeModel treeModel) {
super(treeModel);
ds = new TreeDragSource(this, DnDConstants.ACTION_COPY_OR_MOVE);
dt = new TreeDropTarget(this);
}
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);
} */
class TreeDragSource implements DragSourceListener, DragGestureListener {
private DragSource source;
private TransferableTreeNode transferable;
private JTree tree;
@SuppressWarnings("unused")
private DragGestureRecognizer recognizer;
public TreeDragSource(JTree _tree, int actions) {
tree = _tree;
source = new DragSource();
recognizer = source.createDefaultDragGestureRecognizer(tree,actions, this);
}
/*
* Drag Gesture Handler
*/
public void dragGestureRecognized(DragGestureEvent dge) {
oldPath = tree.getSelectionPath();
if ((oldPath == null) || (oldPath.getPathCount() <= 1)) {
// We can't move the root node or an empty selection
return;
}
transferable = new TransferableTreeNode(oldPath);
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) {
Point p = new Point(dsde.getX(), dsde.getY());
SwingUtilities.convertPointFromScreen(p,tree);
TreePath selPath = tree.getPathForLocation((int)p.getX(), (int)p.getY());
//System.out.println(selPath);
tree.setSelectionPath(selPath);
tree.updateUI();
}
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)) {
if (newPath.getPathCount() != oldPath.getPathCount()-1){
//tree.setCursor(DragSource.DefaultMoveNoDrop );
}
}
/*
* 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 {
@SuppressWarnings("unused")
private DropTarget target;
private JTree tree;
public TreeDropTarget(JTree _tree) {
tree = _tree;
target = new DropTarget(tree, this);
}
/*
* Drop Event Handlers
*/
public void dragEnter(DropTargetDragEvent dtde) {
System.out.println("drop handler : dragEnter");
}
public void dragOver(DropTargetDragEvent dtde) {
//System.out.println("dragOver");
Point p = dtde.getLocation();
newPath = tree.getClosestPathForLocation(p.x, p.y);
//dtde.acceptDrag(DnDConstants.ACTION_MOVE);
DefaultMutableTreeNode newNode = (DefaultMutableTreeNode) newPath.getLastPathComponent();
//System.out.println(newNode);
// if we are on a leave we reject
if (newNode.isLeaf()) {
dtde.rejectDrag();
return;
} else if (newPath.getPathCount() != oldPath.getPathCount()-1){
// return if drop not at the good place
dtde.rejectDrag();
return;
} else {
dtde.acceptDrag(dtde.getDropAction());
}
}
public void dragExit(DropTargetEvent dte) {}
public void dropActionChanged(DropTargetDragEvent dtde) {}
public void drop(DropTargetDropEvent dtde) {
DefaultMutableTreeNode newNode = (DefaultMutableTreeNode) newPath.getLastPathComponent();
System.out.println(newNode);
// if we are on a leave we reject
if (newNode.isLeaf()) {
dtde.rejectDrop();
return;
}
// return if drop not at the good place
if (newPath.getPathCount() != oldPath.getPathCount()-1){
dtde.rejectDrop();
return;
}
try {
// supress the oldNode
DefaultMutableTreeNode oldNode = (DefaultMutableTreeNode) oldPath.getLastPathComponent();
((DefaultTreeModel) tree.getModel()).removeNodeFromParent(oldNode);
// add the newNode
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, newNode, 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 {
private DataFlavor flavors[] = { TREE_PATH_FLAVOR };
private 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);
}
}
}
} |
Partager