Created
May 7, 2012 13:40
-
-
Save brokendish/2627832 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package test; | |
import java.awt.*; | |
import java.awt.datatransfer.*; | |
import java.awt.dnd.*; | |
import java.io.*; | |
import javax.swing.*; | |
import javax.swing.tree.*; | |
public class dragOver extends JPanel{ | |
public dragOver() { | |
super(new BorderLayout()); | |
DefaultTreeModel model = makeModel(); | |
DnDTree tree = new DnDTree(); | |
tree.setModel(model); | |
for(int i=0;i<tree.getRowCount();i++) { | |
tree.expandRow(i); | |
} | |
add(new JScrollPane(tree)); | |
setPreferredSize(new Dimension(320, 240)); | |
} | |
private DefaultTreeModel makeModel() { | |
DefaultMutableTreeNode root = new DefaultMutableTreeNode("RootABC"); | |
DefaultMutableTreeNode set1 = new DefaultMutableTreeNode("SetDir 001"); | |
DefaultMutableTreeNode set2 = new DefaultMutableTreeNode("SetDir 002"); | |
DefaultMutableTreeNode set3 = new DefaultMutableTreeNode("SetDir 003"); | |
DefaultMutableTreeNode set4 = new DefaultMutableTreeNode("SetDir 004"); | |
set1.add(new DefaultMutableTreeNode("001-1111111")); | |
set1.add(new DefaultMutableTreeNode("001-2222222")); | |
set1.add(new DefaultMutableTreeNode("001-3333333")); | |
set2.add(new DefaultMutableTreeNode("002-1111111")); | |
set2.add(new DefaultMutableTreeNode("002-2222222")); | |
set3.add(new DefaultMutableTreeNode("003-1111111")); | |
set3.add(new DefaultMutableTreeNode("003-2222222")); | |
set3.add(new DefaultMutableTreeNode("003-3333333")); | |
root.add(set1); | |
root.add(set2); | |
set2.add(set3); | |
root.add(set4); | |
return new DefaultTreeModel(root); | |
} | |
public static void main(String[] args) { | |
EventQueue.invokeLater(new Runnable() { | |
@Override public void run() { | |
createAndShowGUI(); | |
} | |
}); | |
} | |
public static void createAndShowGUI() { | |
try{ | |
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); | |
}catch(Exception e) { | |
e.printStackTrace(); | |
} | |
JFrame frame = new JFrame("JavaJtreeDragOver"); | |
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); | |
frame.getContentPane().add(new dragOver()); | |
frame.pack(); | |
frame.setLocationRelativeTo(null); | |
frame.setVisible(true); | |
} | |
} | |
class DnDTree extends JTree implements DragSourceListener, DropTargetListener, DragGestureListener { | |
private static final String NAME = "TREE-TEST"; | |
private static final DataFlavor localObjectFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME); | |
private static final DataFlavor[] supportedFlavors = { localObjectFlavor }; | |
//private DragSource dragSource; | |
//private DropTarget dropTarget; | |
private TreeNode dropTargetNode = null; | |
private TreeNode draggedNode = null; | |
public DnDTree() { | |
super(); | |
setCellRenderer(new DnDTreeCellRenderer()); | |
setModel(new DefaultTreeModel(new DefaultMutableTreeNode("default"))); | |
//dragSource = new DragSource(); | |
//DragGestureRecognizer dgr = | |
new DragSource().createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this); | |
//dropTarget = | |
new DropTarget(this, this); | |
} | |
// DragGestureListener ----> | |
@Override public void dragGestureRecognized(DragGestureEvent dge) { | |
//System.out.println("dragGestureRecognized"); | |
Point pt = dge.getDragOrigin(); | |
TreePath path = getPathForLocation(pt.x, pt.y); | |
if(path==null || path.getParentPath()==null) { | |
return; | |
} | |
//System.out.println("start "+path.toString()); | |
draggedNode = (TreeNode) path.getLastPathComponent(); | |
Transferable trans = new RJLTransferable(draggedNode); | |
new DragSource().startDrag(dge, Cursor.getDefaultCursor(), trans, this); | |
} | |
// <---- DragGestureListener | |
// DragSourceListener ----> | |
@Override public void dragDropEnd(DragSourceDropEvent dsde) { | |
dropTargetNode = null; | |
draggedNode = null; | |
repaint(); | |
} | |
@Override public void dragEnter(DragSourceDragEvent dsde) { | |
dsde.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop); | |
} | |
@Override public void dragExit(DragSourceEvent dse) { | |
dse.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop); | |
} | |
@Override public void dragOver(DragSourceDragEvent dsde) {} | |
@Override public void dropActionChanged(DragSourceDragEvent dsde) {} | |
// <---- DragSourceListener | |
// DropTargetListener ----> | |
@Override public void dropActionChanged(DropTargetDragEvent dtde) {} | |
@Override public void dragEnter(DropTargetDragEvent dtde) {} | |
@Override public void dragExit(DropTargetEvent dte) {} | |
@Override public void dragOver(DropTargetDragEvent dtde) { | |
DataFlavor[] f = dtde.getCurrentDataFlavors(); | |
boolean isDataFlavorSupported = f[0].getHumanPresentableName().equals(NAME); | |
if(!isDataFlavorSupported) { | |
//サポートされていないDataFlavor(例えばデスクトップからファイルなど) | |
rejectDrag(dtde); | |
return; | |
} | |
// figure out which cell it's over, no drag to self | |
Point pt = dtde.getLocation(); | |
TreePath path = getPathForLocation(pt.x, pt.y); | |
if(path==null) { | |
//ノード以外の場所(例えばJTreeの余白など) | |
rejectDrag(dtde); | |
return; | |
} | |
Object draggingObject = getSelectionPath().getLastPathComponent(); | |
MutableTreeNode draggingNode = (MutableTreeNode) draggingObject; | |
DefaultMutableTreeNode targetNode = (DefaultMutableTreeNode) path.getLastPathComponent(); | |
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) targetNode.getParent(); | |
while(parentNode!=null) { | |
if(draggingNode.equals(parentNode)) { | |
//親ノードを子ノードにドロップしようとしている | |
rejectDrag(dtde); | |
return; | |
} | |
parentNode = (DefaultMutableTreeNode)parentNode.getParent(); | |
} | |
//dropTargetNode は、描画用(Rectangle2D、Line)のflag | |
dropTargetNode = targetNode; //(TreeNode) path.getLastPathComponent(); | |
dtde.acceptDrag(dtde.getDropAction()); | |
repaint(); | |
} | |
@Override public void drop(DropTargetDropEvent dtde) { | |
Object draggingObject = getSelectionPath().getLastPathComponent(); | |
DefaultTreeModel model = (DefaultTreeModel) getModel(); | |
Point p = dtde.getLocation(); | |
TreePath path = getPathForLocation(p.x, p.y); | |
if(path==null || !(draggingObject instanceof MutableTreeNode)) { | |
dtde.dropComplete(false); | |
return; | |
} | |
//System.out.println("drop path is " + path); | |
MutableTreeNode draggingNode = (MutableTreeNode) draggingObject; | |
DefaultMutableTreeNode targetNode = (DefaultMutableTreeNode) path.getLastPathComponent(); | |
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) targetNode.getParent(); | |
if(targetNode.equals(draggingNode)) { | |
// | |
dtde.dropComplete(false); | |
return; | |
} | |
dtde.acceptDrop(DnDConstants.ACTION_MOVE); | |
model.removeNodeFromParent(draggingNode); | |
if(parentNode!=null && targetNode.isLeaf()) { | |
model.insertNodeInto(draggingNode, parentNode, parentNode.getIndex(targetNode)); | |
}else{ | |
model.insertNodeInto(draggingNode, targetNode, targetNode.getChildCount()); | |
} | |
dtde.dropComplete(true); | |
} | |
private void rejectDrag(DropTargetDragEvent dtde) { | |
dtde.rejectDrag(); | |
dropTargetNode = null; // dropTargetNode(flag)をnullにして | |
repaint(); // Rectangle2D、Lineを消すためJTreeを再描画 | |
} | |
// <---- DropTargetListener | |
static class RJLTransferable implements Transferable { | |
Object object; | |
public RJLTransferable(Object o) { | |
object = o; | |
} | |
@Override public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException { | |
if(isDataFlavorSupported(df)) { | |
return object; | |
}else{ | |
throw new UnsupportedFlavorException(df); | |
} | |
} | |
@Override public boolean isDataFlavorSupported(DataFlavor df) { | |
return (df.getHumanPresentableName().equals(NAME)); | |
//return (df.equals(localObjectFlavor)); | |
} | |
@Override public DataFlavor[] getTransferDataFlavors() { | |
return supportedFlavors; | |
} | |
} | |
// custom renderer | |
class DnDTreeCellRenderer extends DefaultTreeCellRenderer { | |
private static final int BOTTOM_PAD = 30; | |
private boolean isTargetNode; | |
private boolean isTargetNodeLeaf; | |
private boolean isLastItem; | |
private Insets normalInsets; | |
private Insets lastItemInsets; | |
public DnDTreeCellRenderer() { | |
super(); | |
normalInsets = super.getInsets(); | |
lastItemInsets = new Insets( | |
normalInsets.top, | |
normalInsets.left, | |
normalInsets.bottom + BOTTOM_PAD, | |
normalInsets.right); | |
} | |
@Override public Component getTreeCellRendererComponent(JTree tree, Object value, | |
boolean isSelected, boolean isExpanded, boolean isLeaf, | |
int row, boolean hasFocus) { | |
isTargetNode = (value == dropTargetNode); | |
isTargetNodeLeaf = (isTargetNode && ((TreeNode)value).isLeaf()); | |
// isLastItem = (index == list.getModel().getSize()-1); | |
//boolean showSelected = isSelected & (dropTargetNode == null); | |
return super.getTreeCellRendererComponent(tree, value, isSelected, isExpanded, isLeaf, row, hasFocus); | |
} | |
@Override public void paintComponent(Graphics g) { | |
super.paintComponent(g); | |
if(isTargetNode) { | |
g.setColor(Color.BLACK); | |
if(isTargetNodeLeaf) { | |
g.drawLine(0, 0, getSize().width, 0); | |
}else{ | |
g.drawRect(0, 0, getSize().width-1, getSize().height-1); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment