diff --git a/src/main/java/com/marginallyclever/ro3/node/Node.java b/src/main/java/com/marginallyclever/ro3/node/Node.java index 07b6ad640..e7fb9e4dd 100644 --- a/src/main/java/com/marginallyclever/ro3/node/Node.java +++ b/src/main/java/com/marginallyclever/ro3/node/Node.java @@ -37,19 +37,32 @@ public Node(String name) { this.name = name; } + /** + * Append a child to this node. + * @param child the child to add. + */ public void addChild(Node child) { - children.add(child); + addChild(children.size(),child); + } + + /** + * Add a child to this node at the given index. + * @param index the index to add the child at. + * @param child the child to add. + */ + public void addChild(int index,Node child) { + if(index<0|| index>children.size()) { + throw new IndexOutOfBoundsException("Index "+index+" is out of bounds."); + } + + children.add(index,child); child.setParent(this); fireAttachEvent(child); child.onAttach(); if(child.children.isEmpty()) { fireReadyEvent(child); child.onReady(); - }/* else { - for(Node grandchild : child.children) { - child.addChild(grandchild); - } - }*/ + } } private void fireReadyEvent(Node child) { diff --git a/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeTransferHandler.java b/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeTransferHandler.java index f1a7a22a1..0d211930e 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeTransferHandler.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeTransferHandler.java @@ -1,11 +1,14 @@ package com.marginallyclever.ro3.node.nodetreeview; import com.marginallyclever.ro3.node.Node; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.swing.*; import javax.swing.tree.*; import java.awt.datatransfer.*; public class NodeTreeTransferHandler extends TransferHandler { + private static final Logger logger = LoggerFactory.getLogger(NodeTreeTransferHandler.class); @Override public int getSourceActions(JComponent c) { return MOVE; @@ -41,26 +44,46 @@ public boolean importData(TransferHandler.TransferSupport support) { } JTree tree = (JTree) support.getComponent(); - DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation(); TreePath destPath = dl.getPath(); - Node newParent = ((NodeTreeBranch) destPath.getLastPathComponent()).getNode(); + NodeTreeBranch newParentBranch = (NodeTreeBranch) destPath.getLastPathComponent(); + Node newParent = newParentBranch.getNode(); try { Transferable transferable = support.getTransferable(); - Node sourceNode = (Node) transferable.getTransferData(NodeTransferable.nodeFlavor); + Node beingMoved = (Node) transferable.getTransferData(NodeTransferable.nodeFlavor); + + // Prevent a node from being dragged to itself + if (beingMoved == newParent) { + return false; + } // Remove node from its current parent - Node oldParent = sourceNode.getParent(); + Node oldParent = beingMoved.getParent(); + int oldIndex = -1; if (oldParent != null) { - oldParent.removeChild(sourceNode); + oldIndex = oldParent.getChildren().indexOf(beingMoved); + oldParent.removeChild(beingMoved); + logger.debug("oldIndex: {}", oldIndex); } - // Add node to the new parent - newParent.addChild(sourceNode); + // Get the index at which the source node will be added + int newIndex = dl.getChildIndex(); + logger.debug("newIndex: {}", newIndex); + if (newIndex == -1) { + // If the drop location is a node, add the node at the end + newParent.addChild(beingMoved); + } else { + // If oldParent and newParent are the same instance, adjust the index accordingly + if (oldParent == newParent && oldIndex < newIndex) { + newIndex--; + } + // If the drop location is an index, add the node at the specified index + newParent.addChild(newIndex, beingMoved); + } return true; } catch (Exception e) { - e.printStackTrace(); + logger.error("importData", e); } return false; } diff --git a/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeView.java b/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeView.java index b6eed63f5..477e5fd52 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeView.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeView.java @@ -1,7 +1,5 @@ package com.marginallyclever.ro3.node.nodetreeview; -import com.marginallyclever.ro3.DockingPanel; -import com.marginallyclever.ro3.FactoryPanel; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.SceneChangeListener; import com.marginallyclever.ro3.actions.AddNode; @@ -17,7 +15,6 @@ import javax.swing.event.EventListenerList; import javax.swing.tree.*; import java.awt.*; -import java.awt.event.ActionEvent; import java.security.InvalidParameterException; import java.util.*; import java.util.List; @@ -105,7 +102,7 @@ public void scanTree(Node toScan) { NodeTreeBranch parentBranch = findTreeNode(toScan); if(parentBranch == null) { - logger.error("node has no branch"); + logger.error("Node has no branch"); return; } @@ -160,42 +157,48 @@ private void fireSelectionChangeEvent(List newSelection) { } @Override - public void nodeAttached(Node source) { - logger.debug("attached "+source.getAbsolutePath()); - Node parent = source.getParent(); + public void nodeAttached(Node child) { + logger.debug("Attached "+child.getAbsolutePath()); + Node parent = child.getParent(); if(parent==null) throw new RuntimeException("source node has no parent"); NodeTreeBranch branchParent = findTreeNode(parent); if(branchParent==null) throw new RuntimeException("parent node has no branch"); - NodeTreeBranch branchChild = new NodeTreeBranch(source); - branchParent.add(branchChild); + NodeTreeBranch branchChild = new NodeTreeBranch(child); + int index = parent.getChildren().indexOf(child); + branchParent.insert(branchChild,index); - source.addAttachListener(this); - source.addDetachListener(this); - source.addRenameListener(this); + child.addAttachListener(this); + child.addDetachListener(this); + child.addRenameListener(this); - scanTree(source); + scanTree(child); ((DefaultTreeModel) tree.getModel()).nodeStructureChanged(branchParent); } @Override - public void nodeDetached(Node source) { - logger.debug("detached "+source.getAbsolutePath()); - source.removeAttachListener(this); - source.removeDetachListener(this); - source.removeRenameListener(this); - - Node parent = source.getParent(); - if(parent==null) throw new RuntimeException("source node has no parent"); + public void nodeDetached(Node child) { + logger.debug("Detached "+child.getAbsolutePath()); + child.removeAttachListener(this); + child.removeDetachListener(this); + child.removeRenameListener(this); + + Node parent = child.getParent(); + if(parent==null) throw new RuntimeException("Source node has no parent"); NodeTreeBranch branchParent = findTreeNode(parent); - if(branchParent==null) throw new RuntimeException("parent node has no branch"); - branchParent.remove(findTreeNode(source)); + if(branchParent==null) throw new RuntimeException("Parent node has no branch"); + NodeTreeBranch branchChild = findTreeNode(child); + if(branchChild==null) { + logger.warn("No branch for "+child.getAbsolutePath()); + return; + } + branchParent.remove(branchChild); ((DefaultTreeModel) tree.getModel()).nodeStructureChanged(branchParent); } @Override public void nodeRenamed(Node source) { - logger.debug("renamed "+source.getAbsolutePath()); + logger.debug("Renamed "+source.getAbsolutePath()); NodeTreeBranch branch = findTreeNode(source); if (branch != null) { ((DefaultTreeModel) tree.getModel()).nodeChanged(branch);