import javax.swing.*; import se.chalmers.cs.gf.linearize.Linearizer; public class NodeView extends JLabel { private static NodeTransferHandler nodeHandler = new NodeTransferHandler(); private static DragMouseAdapter nodeMouseListener = new DragMouseAdapter(); private Node node; private Linearizer linearizer; public NodeView(Node node, Linearizer linearizer) { this.node = node; this.linearizer = linearizer; setTransferHandler(nodeHandler); addMouseListener(nodeMouseListener); } public Node getNode() { return node; } public boolean canAttach(Node child) { return getAttachPos(child) != -1; } /** * Get the first free position of the same type as the given node. * If there is no free slot, the first slot of the right type * is returned. If there is no slot of the right type, * -1 is returned. */ public int getAttachPos(Node child) { for (int pos = 0; pos < node.getArity(); pos++) if (node.isFree(pos) && node.canAttach(pos, child)) return pos; for (int pos = 0; pos < node.getArity(); pos++) if (node.canAttach(pos, child)) return pos; return -1; } /** * Attach a node as a child of our node, if possible. * The first free slot of the right type is taken. * If there is no free slot, the child in the first * free slot of the right type is removed. * FIXME: we should detach the removed child into a * separate node. * @return true if the node could be added, false otherwise. */ public boolean attachNode(Node child) { // FIXME: make sure we are not trying to attach a node to itself // or its own children. int pos = getAttachPos(child); if (pos != -1) { Node oldChild = node.attachChild(pos, child); if (oldChild != null) { // FIXME: detach oldChild to a separate view } updateText(); return true; } return false; } public void updateText() { setText(node.getFun() + ": " + node.getText(linearizer)); } }