package jcgp.gui.population; import javafx.event.EventHandler; import javafx.scene.input.MouseDragEvent; import javafx.scene.input.MouseEvent; import javafx.scene.paint.Paint; import javafx.scene.shape.Circle; import jcgp.backend.population.Connection; import jcgp.backend.population.Input; import jcgp.gui.GUI; public class GUIInput extends GUIGene { private Input input; public GUIInput(ChromosomePane parentRef, final Input input) { super(); this.parent = parentRef; this.input = input; relocate(NODE_RADIUS, (input.getIndex() * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS); updateText(); Circle outputSocket = new Circle(NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white")); outputSocket.setId(String.valueOf(0)); outputSocket.setStroke(Paint.valueOf("black")); getChildren().addAll(mainCircle, text, outputSocket); /* * Mouse event handlers on whole gene */ addEventFilter(MouseDragEvent.MOUSE_DRAG_ENTERED, new EventHandler() { @Override public void handle(MouseDragEvent event) { // the drag has entered this node, react appropriately // this happens even if we are the source of the drag ((GUIGene) event.getGestureSource()).setConnectionLine((GUIGene) event.getSource()); Connection source = ((GUIGene) event.getGestureSource()).getChangingConnection(); if (input == source) { setState(GUIGeneState.NO_CHANGE_TARGET); } else { setState(GUIGeneState.TARGET); } } }); addEventFilter(MouseDragEvent.MOUSE_DRAG_EXITED, new EventHandler() { @Override 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 (getState() == GUIGeneState.NO_CHANGE_TARGET) { setState(GUIGeneState.INDIRECT_HOVER); } else { setState(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 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 (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(input); addLocks(source.getLocks()); } else { source.setChangingConnection(input); } source.updateLines(); setState(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 (getState() == GUIGeneState.NEUTRAL) { setState(GUIGeneState.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 (getState() == GUIGeneState.HOVER) { setState(GUIGeneState.NEUTRAL); setConnections(GUIGeneState.NEUTRAL); } } }); } @Override public void setState(GUIGeneState newState) { super.setState(newState); switch (newState) { case ACTIVE_HOVER: if (locked > 0) { setState(GUIGeneState.LOCKED_HOVER); } else { mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR)); } break; case FORBIDDEN_TARGET: mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR)); break; case LOCKED_HOVER: mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR)); break; case HOVER: mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR)); break; case INDIRECT_HOVER: mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR)); break; case NEUTRAL: if (locked > 0) { setState(GUIGeneState.HOVER); } else { mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR)); } break; case NO_CHANGE_TARGET: parent.setTarget(true); mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR)); break; case SOURCE: mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR)); break; case TARGET: parent.setTarget(true); mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR)); break; default: break; } } @Override public Input getGene() { return input; } /** * Set all connections to a given state. * * @param newState the state to set connections to. */ @Override public void setConnections(GUIGeneState newState) { // nothing } @Override public void resetState() { setState(GUIGeneState.NEUTRAL); } @Override void setLocked(boolean value) { locked += value ? 1 : -1; setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER); } @Override public void setChangingConnection(Connection newConnection) { // do nothing } @Override public Connection getChangingConnection() { return null; } @Override public void addLocks(int value) { locked += value; setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER); } @Override public void updateLines() { // nothing } @Override public void removeLocks(int value) { locked -= value; setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL); } @Override public void setConnectionLine(GUIGene gene) { // nothing } public void setValue(Object newValue) { value = newValue; input.setValue(newValue); } @Override public void updateText() { if (parent.isEvaluating()) { text.setText("I: " + input.getIndex() + "\n" + value.toString()); } else { text.setText("I: " + input.getIndex()); } } }