package jcgp.gui.population; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.EventHandler; import javafx.geometry.VPos; import javafx.scene.input.MouseDragEvent; import javafx.scene.input.MouseEvent; import javafx.scene.paint.Paint; import javafx.scene.shape.Circle; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; import jcgp.GUI; import jcgp.population.Input; import jcgp.population.Node; import jcgp.population.Output; public class GUIInput extends GUIGene { private Circle outputSocket; private Input input; public GUIInput(ChromosomePane parentRef, final Input input) { this.parent = parentRef; this.input = input; relocate(NODE_RADIUS, (input.getIndex() * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS); mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white")); mainCircle.setStroke(Paint.valueOf("black")); text = new Text("I: " + input.getIndex()); text.setFont(Font.font("Arial", 12)); text.setTextOrigin(VPos.CENTER); text.setTextAlignment(TextAlignment.CENTER); text.setWrappingWidth(NODE_RADIUS * 2); text.setX(-NODE_RADIUS); text.setVisible(true); 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 if (event.getGestureSource() instanceof GUINode) { Node source = ((GUINode) event.getGestureSource()).getGene(); for (int i = 0; i < (int) GUI.resources.get("arity"); i++) { if (input == source.getConnection(i)) { stateProperty.set(GUIGeneState.NO_CHANGE_TARGET); return; } } } else if (event.getGestureSource() instanceof GUIOutput) { Output source = ((GUIOutput) event.getGestureSource()).getGene(); if (((GUIGene) event.getSource()).getGene() == source.getSource()) { ((GUIGene) event.getSource()).setState(GUIGeneState.NO_CHANGE_TARGET); } } stateProperty.set(GUIGeneState.TARGET); } }); addEventFilter(MouseDragEvent.MOUSE_DRAG_OVER, new EventHandler() { @Override public void handle(MouseDragEvent event) { // the user is dragging over this node, react appropriately // this happens even if we are the source of the drag } }); 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 if (stateProperty.get() == GUIGeneState.NO_CHANGE_TARGET) { stateProperty.set(GUIGeneState.INDIRECT_HOVER); } else { stateProperty.set(GUIGeneState.NEUTRAL); } } }); addEventFilter(MouseDragEvent.MOUSE_DRAG_RELEASED, new EventHandler() { @Override public void handle(MouseDragEvent event) { // set states to reflect the new situation ((GUIGene) event.getGestureSource()).setState(GUIGeneState.NEUTRAL); ((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.NEUTRAL); stateProperty.set(GUIGeneState.HOVER); // the user released the drag gesture on this node, react appropriately if (event.getGestureSource() instanceof GUINode) { ((GUINode) event.getGestureSource()).setChangingConnection(input); } else if (event.getGestureSource() instanceof GUIOutput) { ((GUIOutput) event.getGestureSource()).getGene().setConnection(0, input); } } }); 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.INDIRECT_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.INDIRECT_HOVER) { stateProperty.set(GUIGeneState.NEUTRAL); setConnections(GUIGeneState.NEUTRAL); } } }); 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)); break; case FORBIDDEN_TARGET: mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR)); break; case HOVER: mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR)); break; case INDIRECT_HOVER: mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR)); break; case NEUTRAL: mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR)); break; case NO_CHANGE_TARGET: mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR)); break; case SOURCE: mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR)); break; case TARGET: 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() { stateProperty.set(GUIGeneState.NEUTRAL); } }