From bc4fafb9d3c60993253f7e78c10338c901de653a Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Mon, 24 Mar 2014 17:16:51 +0000 Subject: Node grid all done and apparently stable. --- src/jcgp/gui/population/GUINode.java | 230 +++++++++++++++++++++-------------- 1 file changed, 140 insertions(+), 90 deletions(-) (limited to 'src/jcgp/gui/population/GUINode.java') diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java index c5ab43a..dd20006 100644 --- a/src/jcgp/gui/population/GUINode.java +++ b/src/jcgp/gui/population/GUINode.java @@ -13,7 +13,6 @@ import javafx.scene.shape.Line; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; -import jcgp.CGP.Resources; import jcgp.GUI; import jcgp.function.Function; import jcgp.population.Connection; @@ -22,7 +21,7 @@ import jcgp.population.Node; import jcgp.population.Output; public class GUINode extends GUIGene { - + private Circle[] sockets; private Circle output; @@ -31,23 +30,23 @@ public class GUINode extends GUIGene { private Label connectionNumber; private Node node; - - private int connectionIndex; - - public GUINode(ChromosomePane parentRef, final Node node, Resources resources, Line[] connectionLines) { + + private int connectionIndex = 0; + + public GUINode(ChromosomePane parentRef, final Node node, Line[] connectionLines) { // store references this.parent = parentRef; this.node = node; this.lines = connectionLines; - + // move the GUIGene to the right position relocate(((node.getColumn() + 1) * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS, (node.getRow() * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS); // set the line ends correctly updateLines(); - + connectionNumber = new Label(); connectionNumber.setStyle("-fx-background-color:rgb(255, 255, 255); -fx-border-color:rgba(0, 0, 0, 0.5); "); connectionNumber.setVisible(false); @@ -73,20 +72,20 @@ public class GUINode extends GUIGene { text.setX(-NODE_RADIUS); text.setVisible(true); - sockets = new Circle[(int) resources.get("arity")]; + sockets = new Circle[(int) GUI.resources.get("arity")]; double angle, xPos, yPos; for (int l = 0; l < sockets.length; l++) { - angle = ((((double) (l + 1)) / ((double) ((int) resources.get("arity") + 1))) * THETA) - (THETA / 2); + angle = ((((double) (l + 1)) / ((double) ((int) GUI.resources.get("arity") + 1))) * THETA) - (THETA / 2); xPos = -Math.cos(angle) * NODE_RADIUS; yPos = Math.sin(angle) * NODE_RADIUS; sockets[l] = new Circle(xPos, yPos, GUIGene.SOCKET_RADIUS, Paint.valueOf("white")); sockets[l].setId(String.valueOf(l)); sockets[l].setStroke(Paint.valueOf("black")); - + final Circle s = sockets[l]; final int index = l; - + /* * Mouse event handlers on sockets * @@ -98,7 +97,7 @@ public class GUINode extends GUIGene { startFullDrag(); } }); - + s.addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler() { @Override public void handle(MouseEvent event) { @@ -108,7 +107,7 @@ public class GUINode extends GUIGene { connectionNumber.setVisible(true); } }); - + s.addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler() { @Override public void handle(MouseEvent event) { @@ -116,24 +115,26 @@ public class GUINode extends GUIGene { connectionNumber.setVisible(false); } }); - + s.addEventFilter(MouseDragEvent.MOUSE_PRESSED, new EventHandler() { @Override public void handle(MouseEvent event) { // mouse was pressed on the socket stateProperty.set(GUIGeneState.SOURCE); connectionIndex = index; - } + } }); - + s.addEventFilter(MouseDragEvent.MOUSE_DRAGGED, new EventHandler() { @Override public void handle(MouseEvent event) { - lines[connectionIndex].setEndX(event.getX() + ((Circle) event.getSource()).getParent().getLayoutX()); - lines[connectionIndex].setEndY(event.getY() + ((Circle) event.getSource()).getParent().getLayoutY()); + if (!parent.isTarget()) { + lines[connectionIndex].setEndX(event.getX() + ((Circle) event.getSource()).getParent().getLayoutX()); + lines[connectionIndex].setEndY(event.getY() + ((Circle) event.getSource()).getParent().getLayoutY()); + } } }); - + s.addEventFilter(MouseDragEvent.MOUSE_RELEASED, new EventHandler() { @Override public void handle(MouseEvent event) { @@ -142,10 +143,10 @@ public class GUINode extends GUIGene { updateLine(index); stateProperty.set(GUIGeneState.HOVER); } - } + } }); } - + /* * Mouse event handlers on whole gene */ @@ -155,13 +156,12 @@ public class GUINode extends GUIGene { // the drag has entered this node, react appropriately // this happens even if we are the source of the drag if (isAllowed((GUIGene) event.getGestureSource(), (GUIGene) event.getSource())) { + ((GUIGene) event.getGestureSource()).setConnectionLine((GUIGene) event.getSource()); if (event.getGestureSource() instanceof GUINode) { - Node source = ((GUINode) event.getGestureSource()).getGene(); - for (int i = 0; i < lines.length; i++) { - if (node == source.getConnection(i)) { - stateProperty.set(GUIGeneState.NO_CHANGE_TARGET); - return; - } + Connection source = ((GUINode) event.getGestureSource()).getChangingConnection(); + if (node == source) { + stateProperty.set(GUIGeneState.NO_CHANGE_TARGET); + return; } } else if (event.getGestureSource() instanceof GUIOutput) { Output source = ((GUIOutput) event.getGestureSource()).getGene(); @@ -181,6 +181,7 @@ public class GUINode extends GUIGene { public void handle(MouseDragEvent event) { // the drag has exited this node, react appropriately // this happens even if we are the source of the drag + parent.setTarget(false); if (event.isPrimaryButtonDown()) { if (event.getGestureSource() == event.getSource()) { stateProperty.set(GUIGeneState.SOURCE); @@ -189,58 +190,74 @@ public class GUINode extends GUIGene { stateProperty.set(GUIGeneState.INDIRECT_HOVER); } else { stateProperty.set(GUIGeneState.NEUTRAL); + ((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.INDIRECT_HOVER); } } } } }); - + addEventFilter(MouseDragEvent.MOUSE_DRAG_RELEASED, new EventHandler() { @Override public void handle(MouseDragEvent event) { + GUIGene source = ((GUIGene) event.getGestureSource()); // set states to reflect the new situation - ((GUIGene) event.getGestureSource()).setState(GUIGeneState.NEUTRAL); - ((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.NEUTRAL); - stateProperty.set(GUIGeneState.HOVER); + if (source.isLocked()) { + source.setState(GUIGeneState.HOVER); + source.setConnections(GUIGeneState.HOVER); + } else { + source.setState(GUIGeneState.NEUTRAL); + source.setConnections(GUIGeneState.NEUTRAL); + } + // the user released the drag gesture on this node, react appropriately if (isAllowed((GUIGene) event.getGestureSource(), (GUIGene) event.getSource())) { - if (event.getGestureSource() instanceof GUINode) { - ((GUINode) event.getGestureSource()).setChangingConnection(node); - } else if (event.getGestureSource() instanceof GUIOutput) { - ((GUIOutput) event.getGestureSource()).getGene().setConnection(0, node); + if (source.isLocked()) { + // remove locks from the old connection, add the to the new + // note that the old connection may still have locks after this + parent.getGuiGene(source.getChangingConnection()).removeLocks(source.getLocks()); + source.setChangingConnection(node); + addLocks(source.getLocks()); + } else { + if (source instanceof GUIOutput) { + source.resetState(); + } + source.setChangingConnection(node); } + } - if (event.getGestureSource() instanceof GUINode) { - ((GUINode) event.getGestureSource()).updateLines(); - } else if (event.getGestureSource() instanceof GUIOutput) { - ((GUIOutput) event.getGestureSource()).updateLine(); - } - + source.updateLines(); + stateProperty.set(GUIGeneState.HOVER); } }); - - + + addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler() { @Override public void handle(MouseEvent event) { // cursor has entered this node without dragging, or it is dragging and this is the source if (stateProperty.get() == GUIGeneState.NEUTRAL) { stateProperty.set(GUIGeneState.HOVER); + } else if (locked > 0) { + setConnections(GUIGeneState.LOCKED_HOVER); } } }); - + addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler() { @Override public void handle(MouseEvent event) { // cursor has left this node without dragging, or it is dragging and this is the source - if (stateProperty.get() == GUIGeneState.HOVER) { - if (isLocked()) { - + if (stateProperty.get() == GUIGeneState.HOVER && locked <= 0) { + stateProperty.set(GUIGeneState.NEUTRAL); + setConnections(GUIGeneState.NEUTRAL); + } else if (locked > 0) { + if (stateProperty.get() == GUIGeneState.SOURCE || stateProperty.get() == GUIGeneState.FORBIDDEN_TARGET) { + setConnections(GUIGeneState.INDIRECT_HOVER); } else { - stateProperty.set(GUIGeneState.NEUTRAL); - setConnections(GUIGeneState.NEUTRAL); + setConnections(GUIGeneState.HOVER); } + } } }); @@ -248,54 +265,67 @@ public class GUINode extends GUIGene { getChildren().addAll(mainCircle, text); getChildren().addAll(sockets); getChildren().addAll(output, connectionNumber); - + stateProperty.addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, GUIGeneState oldValue, GUIGeneState newValue) { - + switch (newValue) { case ACTIVE_HOVER: - mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR)); - showLines(true); + if (locked > 0) { + stateProperty().set(GUIGeneState.LOCKED_HOVER); + } else { + mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR)); + showLines(true); + } setConnections(GUIGeneState.ACTIVE_HOVER); break; + case LOCKED_HOVER: + mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR)); + break; case FORBIDDEN_TARGET: mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR)); break; case HOVER: - mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR)); + mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR)); showLines(true); - if (!isLocked()) { + if ((oldValue != GUIGeneState.LOCKED_HOVER || oldValue != GUIGeneState.SOURCE) && locked <= 0) { setConnections(GUIGeneState.INDIRECT_HOVER); + } else { + setConnections(GUIGeneState.HOVER); } - break; case INDIRECT_HOVER: mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR)); break; case NEUTRAL: - mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR)); - showLines(false); - if (oldValue == GUIGeneState.ACTIVE_HOVER) { - setConnections(GUIGeneState.NEUTRAL); + if (locked > 0) { + stateProperty.set(GUIGeneState.HOVER); + } else { + mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR)); + showLines(false); + if (oldValue == GUIGeneState.ACTIVE_HOVER) { + setConnections(GUIGeneState.NEUTRAL); + } } break; case NO_CHANGE_TARGET: + parent.setTarget(true); mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR)); break; case SOURCE: mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR)); break; case TARGET: + parent.setTarget(true); mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR)); break; default: break; - } } }); - + for (int c = 0; c < lines.length; c++) { final int i = c; node.connections().get(c).addListener(new ChangeListener() { @@ -306,10 +336,15 @@ public class GUINode extends GUIGene { } }); } - + } - - + + @Override + public Connection getChangingConnection() { + return node.getConnection(connectionIndex); + } + + private boolean isAllowed(GUIGene source, GUIGene target) { if (source instanceof GUINode) { // if the source is a node, all inputs and some nodes are valid @@ -368,7 +403,7 @@ public class GUINode extends GUIGene { updateLine(c); } } - + /** * Toggle visibility of all connection lines. * @@ -389,22 +424,11 @@ public class GUINode extends GUIGene { @Override public void setConnections(GUIGeneState newState) { for (int i = 0; i < lines.length; i++) { - if (node.getConnection(i) instanceof Node) { - if (!parent.getGuiNode(((Node) node.getConnection(i)).getRow(), ((Node) node.getConnection(i)).getColumn()).isLocked()) { - parent.getGuiNode(((Node) node.getConnection(i)).getRow(), ((Node) node.getConnection(i)).getColumn()).setState(newState); - } - } else if (node.getConnection(i) instanceof Input) { - if (!parent.getGuiInput(((Input) node.getConnection(i)).getIndex()).isLocked()) { - parent.getGuiInput(((Input) node.getConnection(i)).getIndex()).setState(newState); - } - } + parent.getGuiGene(node.getConnection(i)).setState(newState); } } - - /** - * This method sets the connection currently being changed to the - * specified value. - */ + + @Override public void setChangingConnection(Connection newConnection) { node.setConnection(connectionIndex, newConnection); } @@ -412,22 +436,48 @@ public class GUINode extends GUIGene { @Override public void resetState() { - stateProperty.set(GUIGeneState.NEUTRAL); - setConnections(GUIGeneState.NEUTRAL); - } + if (locked > 0) { + stateProperty.set(GUIGeneState.HOVER); + } else { + stateProperty.set(GUIGeneState.NEUTRAL); + setConnections(GUIGeneState.NEUTRAL); + } + } @Override public void setLocked(boolean value) { locked += value ? 1 : -1; stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER); - + for (int i = 0; i < lines.length; i++) { - if (node.getConnection(i) instanceof Node) { - parent.getGuiNode(((Node) node.getConnection(i)).getRow(), ((Node) node.getConnection(i)).getColumn()).setLocked(value); - } else if (node.getConnection(i) instanceof Input) { - parent.getGuiInput(((Input) node.getConnection(i)).getIndex()).setLocked(value); - } + parent.getGuiGene(node.getConnection(i)).setLocked(value); + } + } + + @Override + public void addLocks(int value) { + locked += value; + stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER); + + for (int i = 0; i < lines.length; i++) { + parent.getGuiGene(node.getConnection(i)).addLocks(value); + } + } + + @Override + public void removeLocks(int value) { + locked -= value; + stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL); + + for (int i = 0; i < lines.length; i++) { + parent.getGuiGene(node.getConnection(i)).removeLocks(value); } } + + @Override + public void setConnectionLine(GUIGene gene) { + lines[connectionIndex].setEndX(gene.getLayoutX() + NODE_RADIUS); + lines[connectionIndex].setEndY(gene.getLayoutY()); + } } -- cgit v1.2.3