package jcgp.gui.population; import java.util.ArrayList; import javafx.scene.control.ScrollPane; import javafx.scene.layout.Pane; import javafx.scene.shape.Line; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Node; import jcgp.gui.GUI; /** * This extension of {@code ScrollPane} contains a series of * nodes, inputs and outputs spread across a grid. It also contains * all of the connection lines laid over the nodes, inputs and outputs. * * * @author Eduardo Pedroni * */ public class ChromosomePane extends ScrollPane { private GUIInput[] guiInputs; private GUINode[][] guiNodes; private GUIOutput[] guiOutputs; private Pane content; private boolean target = false; public ChromosomePane(Chromosome chromosome) { super(); ArrayList connectionLines = new ArrayList(); int rows = GUI.resources.rows(); int columns = GUI.resources.columns(); content = new Pane(); content.setId("content pane for genes"); /* * inputs */ guiInputs = new GUIInput[GUI.resources.inputs()]; for (int i = 0; i < guiInputs.length; i++) { guiInputs[i] = new GUIInput(chromosome.getInput(i)); } // add inputs to content pane content.getChildren().addAll(guiInputs); /* * nodes */ guiNodes = new GUINode[rows][columns]; for (int c = 0; c < columns; c++) { for (int r = 0; r < rows; r++) { // make the connection lines Line lines[] = new Line[GUI.resources.arity()]; for (int l = 0; l < lines.length; l++) { lines[l] = new Line(); lines[l].setMouseTransparent(true); lines[l].setVisible(false); connectionLines.add(lines[l]); } // make the GUI element guiNodes[r][c] = new GUINode(chromosome.getNode(r, c), lines); // add node to content pane content.getChildren().add(guiNodes[r][c]); } } /* * outputs */ guiOutputs = new GUIOutput[GUI.resources.outputs()]; for (int i = 0; i < guiOutputs.length; i++) { // make the connection line Line line = new Line(); line.setVisible(false); line.setMouseTransparent(true); connectionLines.add(line); // make the GUI element guiOutputs[i] = new GUIOutput(chromosome.getOutput(i), line); } // add outputs to content pane content.getChildren().addAll(guiOutputs); // add lines to the pane on top of genes content.getChildren().addAll(connectionLines); setPrefWidth(620); setContent(content); } protected boolean isTarget() { return target; } protected void setTarget(boolean newValue) { target = newValue; } public void updateGenes(Chromosome chr) { for (int r = 0; r < GUI.resources.rows(); r++) { for (int c = 0; c < GUI.resources.columns(); c++) { guiNodes[r][c].setNode(chr.getNode(r, c)); } } for (int i = 0; i < guiOutputs.length; i++) { guiOutputs[i].setOutput(chr.getOutput(i)); } } public static boolean isAllowed(GUIMutable source, GUIConnection target) { if (source instanceof GUINode) { // if the source is a node, all inputs and some nodes are valid if (target instanceof GUIInput) { return true; } else if (target instanceof GUINode) { // target and source are nodes, let's look at levels back Node t = ((GUINode) target).getNode(), s = ((GUINode) source).getNode(); if (s.getColumn() - t.getColumn() > 0 && s.getColumn() - t.getColumn() <= GUI.resources.levelsBack()) { return true; } } return false; } else if (source instanceof GUIOutput) { // if the source is an output, any node or input is valid if (target instanceof GUINode || target instanceof GUIInput) { return true; } else { // this should never happen... return false; } } // if the source was neither node nor output, something bad is happening throw new ClassCastException("Source was neither GUINode nor GUIOutput."); } }