aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/gui/population
diff options
context:
space:
mode:
Diffstat (limited to 'src/jcgp/gui/population')
-rw-r--r--src/jcgp/gui/population/ChromosomePane.java133
-rw-r--r--src/jcgp/gui/population/FunctionSelector.java73
-rw-r--r--src/jcgp/gui/population/GUIGene.java40
-rw-r--r--src/jcgp/gui/population/GUIInput.java145
-rw-r--r--src/jcgp/gui/population/GUINode.java207
-rw-r--r--src/jcgp/gui/population/GUIOutput.java142
-rw-r--r--src/jcgp/gui/population/PopulationPane.java49
7 files changed, 503 insertions, 286 deletions
diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java
new file mode 100644
index 0000000..cba58d2
--- /dev/null
+++ b/src/jcgp/gui/population/ChromosomePane.java
@@ -0,0 +1,133 @@
+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.Connection;
+import jcgp.backend.population.Input;
+import jcgp.backend.population.Node;
+import jcgp.backend.resources.Resources;
+
+
+public class ChromosomePane extends ScrollPane {
+
+ private GUINode[][] guiNodes;
+ private GUIInput[] guiInputs;
+ private GUIOutput[] guiOutputs;
+
+ private Pane content;
+
+ private ArrayList<Line> connectionLines;
+
+ private ArrayList<GUIOutput> relock = new ArrayList<GUIOutput>();
+
+ private boolean target = false;
+
+ public ChromosomePane(Chromosome chromosome, Resources resources) {
+ super();
+ connectionLines = new ArrayList<Line>();
+
+ content = new Pane();
+ content.setId("content pane for genes");
+
+ // generate the GUIGenes
+ // inputs
+ guiInputs = new GUIInput[resources.getInt("inputs")];
+ for (int i = 0; i < guiInputs.length; i++) {
+ // make the GUI elements
+ guiInputs[i] = new GUIInput(this, chromosome.getInput(i));
+ content.getChildren().addAll(guiInputs[i]);
+ }
+ // nodes
+ guiNodes = new GUINode[resources.getInt("rows")][resources.getInt("columns")];
+ double angle, xPos, yPos;
+ for (int r = 0; r < guiNodes.length; r++) {
+ for (int c = 0; c < guiNodes[r].length; c++) {
+ // make the connection lines
+ Line lines[] = new Line[resources.getInt("arity")];
+ for (int l = 0; l < lines.length; l++) {
+ angle = ((((double) (l + 1)) / ((double) (lines.length + 1))) * GUIGene.THETA) - (GUIGene.THETA / 2);
+ xPos = (-Math.cos(angle) * GUIGene.NODE_RADIUS) + (((c + 1) * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING)) + GUIGene.NODE_RADIUS);
+ yPos = (Math.sin(angle) * GUIGene.NODE_RADIUS) + ((r * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING)) + GUIGene.NODE_RADIUS);
+
+ lines[l] = new Line(xPos, yPos, xPos, yPos);
+ lines[l].setMouseTransparent(true);
+ lines[l].setVisible(false);
+ connectionLines.add(lines[l]);
+ }
+ // make the GUI elements
+ guiNodes[r][c] = new GUINode(this, chromosome.getNode(r, c), lines);
+ }
+ content.getChildren().addAll(guiNodes[r]);
+ }
+
+ // outputs
+ guiOutputs = new GUIOutput[resources.getInt("outputs")];
+ for (int i = 0; i < guiOutputs.length; i++) {
+ xPos = ((resources.getInt("columns") + 1) * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING));
+ yPos = (chromosome.getOutput(i).getIndex() * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING)) + GUIGene.NODE_RADIUS;
+ // make the line
+ Line line = new Line(xPos, yPos, xPos, yPos);
+ line.setMouseTransparent(true);
+ line.setVisible(false);
+ connectionLines.add(line);
+ // make the GUI elements
+ guiOutputs[i] = new GUIOutput(this, chromosome.getOutput(i), line);
+ content.getChildren().addAll(guiOutputs[i]);
+ }
+
+ content.getChildren().addAll(connectionLines);
+ setPrefWidth(620);
+ setContent(content);
+ }
+
+ public GUIGene getGuiGene(Connection gene) {
+ if (gene instanceof Input) {
+ return guiInputs[((Input) gene).getIndex()];
+ } else if (gene instanceof Node) {
+ return guiNodes[((Node) gene).getRow()][((Node) gene).getColumn()];
+ } else {
+ // something bad happened!
+ throw new ClassCastException();
+ }
+ }
+
+ public boolean isTarget() {
+ return target;
+ }
+
+ public void setTarget(boolean newValue) {
+ target = newValue;
+ }
+
+ public void updateGenes() {
+ for (int r = 0; r < guiNodes.length; r++) {
+ for (int c = 0; c < guiNodes[r].length; c++) {
+ guiNodes[r][c].updateLines();
+ guiNodes[r][c].updateFunction();
+ }
+ }
+ for (int i = 0; i < guiOutputs.length; i++) {
+ guiOutputs[i].updateLines();
+ }
+ }
+
+ public void unlockOutputs() {
+ relock.clear();
+ for (int i = 0; i < guiOutputs.length; i++) {
+ if (guiOutputs[i].isLocked()) {
+ guiOutputs[i].unlock();
+ relock.add(guiOutputs[i]);
+ }
+ }
+ }
+
+ public void relockOutputs() {
+ for (int i = 0; i < relock.size(); i++) {
+ relock.get(i).lock();
+ }
+ }
+}
diff --git a/src/jcgp/gui/population/FunctionSelector.java b/src/jcgp/gui/population/FunctionSelector.java
new file mode 100644
index 0000000..0a9606f
--- /dev/null
+++ b/src/jcgp/gui/population/FunctionSelector.java
@@ -0,0 +1,73 @@
+package jcgp.gui.population;
+
+import javafx.event.EventHandler;
+import javafx.scene.control.Label;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.VBox;
+import jcgp.backend.function.FunctionSet;
+import jcgp.gui.GUI;
+
+public class FunctionSelector extends VBox {
+
+ private GUINode target;
+
+ public FunctionSelector(FunctionSet functionSet) {
+ setFillWidth(true);
+ setVisible(false);
+ setStyle("-fx-border-color: #A0A0A0; -fx-border-width: 1 1 0 1");
+
+ remakeFunctions(functionSet);
+
+ addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dismiss();
+ }
+ });
+ }
+
+ public void remakeFunctions(final FunctionSet fs) {
+ getChildren().clear();
+
+ for (int i = 0; i < fs.getAllowedFunctionCount(); i++) {
+ final int index = i;
+ Label l = new Label(fs.getAllowedFunction(i).getName());
+ l.setMaxWidth(Double.MAX_VALUE);
+ l.setStyle("-fx-background-color: #FFFFFF; -fx-border-color: #A0A0A0; -fx-border-width: 0 0 1 0; -fx-padding: 2");
+
+ l.addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ ((Label) event.getSource()).setStyle("-fx-background-color: " + GUI.SOFT_HIGHLIGHT_COLOUR + "; -fx-border-color: #B0B0B0; -fx-border-width: 0 0 1 0; -fx-padding: 2");
+ }
+ });
+ l.addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ ((Label) event.getSource()).setStyle("-fx-background-color: #FFFFFF; -fx-border-color: #A0A0A0; -fx-border-width: 0 0 1 0; -fx-padding: 2");
+ }
+ });
+ l.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ target.getGene().setFunction(fs.getAllowedFunction(index));
+ target.updateFunction();
+ dismiss();
+ }
+ });
+
+ getChildren().add(l);
+ }
+ }
+
+ public void relocateAndShow(MouseEvent event, GUINode node) {
+ relocate(event.getSceneX() - 5, event.getSceneY() - 5);
+ target = node;
+ setVisible(true);
+ }
+
+ private void dismiss() {
+ setVisible(false);
+ }
+
+}
diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java
index 26be2a5..6e9d098 100644
--- a/src/jcgp/gui/population/GUIGene.java
+++ b/src/jcgp/gui/population/GUIGene.java
@@ -1,12 +1,14 @@
package jcgp.gui.population;
-import javafx.beans.property.SimpleObjectProperty;
+import javafx.geometry.VPos;
import javafx.scene.Group;
+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.backend.population.Connection;
import jcgp.backend.population.Gene;
-import jcgp.gui.ChromosomePane;
enum GUIGeneState {
NEUTRAL,
@@ -30,27 +32,34 @@ public abstract class GUIGene extends Group {
public static final double NODE_TEXT = NODE_RADIUS / 2.5;
- protected Text text;
- protected Circle mainCircle;
+ protected Text text = new Text();
+ protected Circle mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white"));
- protected SimpleObjectProperty<GUIGeneState> stateProperty = new SimpleObjectProperty<GUIGeneState>(GUIGeneState.NEUTRAL);
+ private GUIGeneState state = GUIGeneState.NEUTRAL;
protected ChromosomePane parent;
protected int locked = 0;
-
- public SimpleObjectProperty<GUIGeneState> stateProperty() {
- return stateProperty;
+
+ public GUIGene() {
+ 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);
+
+ mainCircle.setStroke(Paint.valueOf("black"));
}
public void setState(GUIGeneState newState) {
- stateProperty.set(newState);
- }
-
- public void showText(boolean value) {
- text.setVisible(value);
+ state = newState;
}
+ public GUIGeneState getState() {
+ return state;
+ }
+
public boolean isLocked() {
return locked > 0;
}
@@ -63,6 +72,11 @@ public abstract class GUIGene extends Group {
public abstract void addLocks(int value);
+ /**
+ * test
+ *
+ * @param value
+ */
public abstract void removeLocks(int value);
public abstract void updateLines();
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index f47186c..b4eccaa 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -1,20 +1,13 @@
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.backend.population.Connection;
import jcgp.backend.population.Input;
import jcgp.backend.population.Output;
-import jcgp.gui.ChromosomePane;
import jcgp.gui.GUI;
public class GUIInput extends GUIGene {
@@ -22,23 +15,16 @@ 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);
- 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);
+ text.setText("I: " + input.getIndex());
+
Circle outputSocket = new Circle(NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
outputSocket.setId(String.valueOf(0));
@@ -59,7 +45,7 @@ public class GUIInput extends GUIGene {
if (event.getGestureSource() instanceof GUINode) {
Connection source = ((GUINode) event.getGestureSource()).getChangingConnection();
if (input == source) {
- stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
+ setState(GUIGeneState.NO_CHANGE_TARGET);
return;
}
} else if (event.getGestureSource() instanceof GUIOutput) {
@@ -68,7 +54,7 @@ public class GUIInput extends GUIGene {
((GUIGene) event.getSource()).setState(GUIGeneState.NO_CHANGE_TARGET);
}
}
- stateProperty.set(GUIGeneState.TARGET);
+ setState(GUIGeneState.TARGET);
}
});
@@ -79,10 +65,10 @@ public class GUIInput extends GUIGene {
// this happens even if we are the source of the drag
parent.setTarget(false);
if (event.isPrimaryButtonDown()) {
- if (stateProperty.get() == GUIGeneState.NO_CHANGE_TARGET) {
- stateProperty.set(GUIGeneState.INDIRECT_HOVER);
+ if (getState() == GUIGeneState.NO_CHANGE_TARGET) {
+ setState(GUIGeneState.INDIRECT_HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.INDIRECT_HOVER);
}
}
@@ -115,7 +101,7 @@ public class GUIInput extends GUIGene {
}
source.updateLines();
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
}
});
@@ -123,8 +109,8 @@ public class GUIInput extends GUIGene {
@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);
+ if (getState() == GUIGeneState.NEUTRAL) {
+ setState(GUIGeneState.HOVER);
}
}
});
@@ -133,62 +119,61 @@ public class GUIInput extends GUIGene {
@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) {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ if (getState() == GUIGeneState.HOVER) {
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
}
});
+ }
+
+ @Override
+ public void setState(GUIGeneState newState) {
+ super.setState(newState);
- stateProperty.addListener(new ChangeListener<GUIGeneState>() {
- @Override
- public void changed(ObservableValue<? extends GUIGeneState> observable, GUIGeneState oldValue, GUIGeneState newValue) {
-
- switch (newValue) {
- case ACTIVE_HOVER:
- if (locked > 0) {
- stateProperty().set(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) {
- stateProperty.set(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;
-
- }
+ 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
@@ -208,13 +193,13 @@ public class GUIInput extends GUIGene {
@Override
public void resetState() {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
}
@Override
void setLocked(boolean value) {
locked += value ? 1 : -1;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
}
@Override
@@ -230,7 +215,7 @@ public class GUIInput extends GUIGene {
@Override
public void addLocks(int value) {
locked += value;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
}
@Override
@@ -241,7 +226,7 @@ public class GUIInput extends GUIGene {
@Override
public void removeLocks(int value) {
locked -= value;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
}
@Override
diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java
index 450647f..98ba738 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -1,22 +1,15 @@
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.control.Label;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
-import javafx.scene.text.Font;
-import javafx.scene.text.Text;
-import javafx.scene.text.TextAlignment;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Input;
import jcgp.backend.population.Node;
-import jcgp.gui.ChromosomePane;
import jcgp.gui.GUI;
public class GUINode extends GUIGene {
@@ -26,7 +19,8 @@ public class GUINode extends GUIGene {
private int connectionIndex = 0;
public GUINode(ChromosomePane parentRef, final Node node, Line[] connectionLines) {
-
+ super();
+
// store references
this.parent = parentRef;
this.node = node;
@@ -46,21 +40,12 @@ public class GUINode extends GUIGene {
Circle output = new Circle(NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
output.setStroke(Paint.valueOf("black"));
- mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white"));
- mainCircle.setStroke(Paint.valueOf("black"));
-
- text = new Text(node.getFunction().getName());
- text.setFont(Font.font("Arial", NODE_TEXT));
- text.setTextOrigin(VPos.CENTER);
- text.setTextAlignment(TextAlignment.CENTER);
- text.setWrappingWidth(NODE_RADIUS * 2);
- text.setX(-NODE_RADIUS);
- text.setVisible(true);
+ text.setText(node.getFunction().getName());
Circle[] sockets = new Circle[GUI.resources.getInt("arity")];
double angle, xPos, yPos;
for (int l = 0; l < sockets.length; l++) {
- angle = ((((double) (l + 1)) / ((GUI.resources.getDouble("arity") + 1))) * THETA) - (THETA / 2);
+ angle = (((l + 1) / ((GUI.resources.getDouble("arity") + 1))) * THETA) - (THETA / 2);
xPos = -Math.cos(angle) * NODE_RADIUS;
yPos = Math.sin(angle) * NODE_RADIUS;
@@ -75,7 +60,7 @@ public class GUINode extends GUIGene {
* Mouse event handlers on sockets
*
*/
- s.addEventFilter(MouseDragEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
+ s.addEventFilter(MouseEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// the mouse has been dragged out of the socket, this means a full drag is in progress
@@ -101,16 +86,16 @@ public class GUINode extends GUIGene {
}
});
- s.addEventFilter(MouseDragEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
+ s.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// mouse was pressed on the socket
- stateProperty.set(GUIGeneState.SOURCE);
+ setState(GUIGeneState.SOURCE);
connectionIndex = index;
}
});
- s.addEventFilter(MouseDragEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
+ s.addEventFilter(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (!parent.isTarget()) {
@@ -120,14 +105,14 @@ public class GUINode extends GUIGene {
}
});
- s.addEventFilter(MouseDragEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
+ s.addEventFilter(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.isStillSincePress()) {
// mouse was released before dragging out of the socket
updateLine(index);
- stateProperty.set(GUIGeneState.HOVER);
- } else if (stateProperty.get() == GUIGeneState.SOURCE) {
+ setState(GUIGeneState.HOVER);
+ } else if (getState() == GUIGeneState.SOURCE) {
// no connection has been made, fallback
resetState();
updateLines();
@@ -139,6 +124,14 @@ public class GUINode extends GUIGene {
/*
* Mouse event handlers on whole gene
*/
+
+ addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ GUI.functionSelector.relocateAndShow(event, (GUINode) event.getSource());
+ }
+ });
+
addEventFilter(MouseDragEvent.MOUSE_DRAG_ENTERED, new EventHandler<MouseDragEvent>() {
@Override
public void handle(MouseDragEvent event) {
@@ -149,12 +142,12 @@ public class GUINode extends GUIGene {
Connection source = ((GUIGene) event.getGestureSource()).getChangingConnection();
if (node == source) {
- stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
+ setState(GUIGeneState.NO_CHANGE_TARGET);
} else {
- stateProperty.set(GUIGeneState.TARGET);
+ setState(GUIGeneState.TARGET);
}
} else {
- stateProperty.set(GUIGeneState.FORBIDDEN_TARGET);
+ setState(GUIGeneState.FORBIDDEN_TARGET);
}
}
});
@@ -167,12 +160,12 @@ public class GUINode extends GUIGene {
parent.setTarget(false);
if (event.isPrimaryButtonDown()) {
if (event.getGestureSource() == event.getSource()) {
- stateProperty.set(GUIGeneState.SOURCE);
+ setState(GUIGeneState.SOURCE);
} else {
- if (stateProperty.get() == GUIGeneState.NO_CHANGE_TARGET) {
- stateProperty.set(GUIGeneState.INDIRECT_HOVER);
+ if (getState() == GUIGeneState.NO_CHANGE_TARGET) {
+ setState(GUIGeneState.INDIRECT_HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.INDIRECT_HOVER);
}
}
@@ -210,7 +203,7 @@ public class GUINode extends GUIGene {
}
source.updateLines();
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
}
});
@@ -219,8 +212,8 @@ public class GUINode extends GUIGene {
@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);
+ if (getState() == GUIGeneState.NEUTRAL) {
+ setState(GUIGeneState.HOVER);
} else if (locked > 0) {
setConnections(GUIGeneState.LOCKED_HOVER);
}
@@ -231,11 +224,11 @@ public class GUINode extends GUIGene {
@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 && locked <= 0) {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ if (getState() == GUIGeneState.HOVER && locked <= 0) {
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
} else if (locked > 0) {
- if (stateProperty.get() == GUIGeneState.SOURCE || stateProperty.get() == GUIGeneState.FORBIDDEN_TARGET) {
+ if (getState() == GUIGeneState.SOURCE || getState() == GUIGeneState.FORBIDDEN_TARGET) {
setConnections(GUIGeneState.INDIRECT_HOVER);
} else {
setConnections(GUIGeneState.HOVER);
@@ -249,85 +242,72 @@ public class GUINode extends GUIGene {
getChildren().addAll(sockets);
getChildren().addAll(output, connectionNumber);
- stateProperty.addListener(new ChangeListener<GUIGeneState>() {
- @Override
- public void changed(ObservableValue<? extends GUIGeneState> observable, GUIGeneState oldValue, GUIGeneState newValue) {
+ }
- switch (newValue) {
- case ACTIVE_HOVER:
- 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.MEDIUM_HIGHLIGHT_COLOUR));
- showLines(true);
- if (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:
- 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;
+ @Override
+ public void setState(GUIGeneState newState) {
+ switch (newState) {
+ case ACTIVE_HOVER:
+ if (locked > 0) {
+ setState(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.MEDIUM_HIGHLIGHT_COLOUR));
+ showLines(true);
+ if (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:
+ if (locked > 0) {
+ setState(GUIGeneState.HOVER);
+ } else {
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
+ showLines(false);
+ if (getState() == GUIGeneState.ACTIVE_HOVER) {
+ setConnections(GUIGeneState.NEUTRAL);
}
}
- });
-
-// for (int c = 0; c < lines.length; c++) {
-// final int i = c;
-// node.connections().get(c).addListener(new ChangeListener<Connection>() {
-// @Override
-// public void changed(ObservableValue<? extends Connection> observable,
-// Connection oldValue, Connection newValue) {
-// updateLine(i);
-// }
-// });
-// }
+ 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;
+ }
+ super.setState(newState);
}
-
+
@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
@@ -381,6 +361,7 @@ public class GUINode extends GUIGene {
/**
* Updates the end of all lines to match the associated connections.
*/
+ @Override
public void updateLines() {
for (int c = 0; c < lines.length; c++) {
updateLine(c);
@@ -420,9 +401,9 @@ public class GUINode extends GUIGene {
@Override
public void resetState() {
if (locked > 0) {
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
@@ -431,7 +412,7 @@ public class GUINode extends GUIGene {
@Override
void setLocked(boolean value) {
locked += value ? 1 : -1;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
for (int i = 0; i < lines.length; i++) {
parent.getGuiGene(node.getConnection(i)).setLocked(value);
@@ -441,7 +422,7 @@ public class GUINode extends GUIGene {
@Override
public void addLocks(int value) {
locked += value;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
for (int i = 0; i < lines.length; i++) {
parent.getGuiGene(node.getConnection(i)).addLocks(value);
@@ -451,7 +432,7 @@ public class GUINode extends GUIGene {
@Override
public void removeLocks(int value) {
locked -= value;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
for (int i = 0; i < lines.length; i++) {
parent.getGuiGene(node.getConnection(i)).removeLocks(value);
diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java
index 9c5dfa5..4a12385 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -1,23 +1,16 @@
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.control.Label;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
-import javafx.scene.text.Font;
-import javafx.scene.text.Text;
-import javafx.scene.text.TextAlignment;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Input;
import jcgp.backend.population.Node;
import jcgp.backend.population.Output;
-import jcgp.gui.ChromosomePane;
import jcgp.gui.GUI;
public class GUIOutput extends GUIGene {
@@ -27,7 +20,8 @@ public class GUIOutput extends GUIGene {
private Output output;
public GUIOutput(ChromosomePane parentRef, final Output output, Line line) {
-
+ super();
+
this.parent = parentRef;
this.output = output;
this.sourceLine = line;
@@ -38,16 +32,7 @@ public class GUIOutput extends GUIGene {
// set the line ends correctly
updateLines();
- mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white"));
- mainCircle.setStroke(Paint.valueOf("black"));
-
- text = new Text("O: " + output.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);
+ text.setText("O: " + output.getIndex());
Circle socket = new Circle(-NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
socket.setId(String.valueOf(0));
@@ -62,7 +47,7 @@ public class GUIOutput extends GUIGene {
* Mouse event handlers on sockets
*
*/
- socket.addEventFilter(MouseDragEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
+ socket.addEventFilter(MouseEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// the mouse has been dragged out of the socket, this means a full drag is in progress
@@ -86,15 +71,15 @@ public class GUIOutput extends GUIGene {
}
});
- socket.addEventFilter(MouseDragEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
+ socket.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// mouse was pressed on the socket
- stateProperty.set(GUIGeneState.SOURCE);
+ setState(GUIGeneState.SOURCE);
}
});
- socket.addEventFilter(MouseDragEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
+ socket.addEventFilter(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (!parent.isTarget()) {
@@ -105,14 +90,14 @@ public class GUIOutput extends GUIGene {
}
});
- socket.addEventFilter(MouseDragEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
+ socket.addEventFilter(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.isStillSincePress()) {
// mouse was released before dragging out of the socket
updateLines();
- stateProperty.set(GUIGeneState.HOVER);
- } else if (stateProperty.get() == GUIGeneState.SOURCE) {
+ setState(GUIGeneState.HOVER);
+ } else if (getState() == GUIGeneState.SOURCE) {
// no connection has been made, fallback
resetState();
updateLines();
@@ -129,7 +114,7 @@ public class GUIOutput extends GUIGene {
@Override
public void handle(MouseDragEvent event) {
// the drag has entered this node, react appropriately
- stateProperty.set(GUIGeneState.FORBIDDEN_TARGET);
+ setState(GUIGeneState.FORBIDDEN_TARGET);
}
});
@@ -140,9 +125,9 @@ public class GUIOutput extends GUIGene {
// this happens even if we are the source of the drag
if (event.isPrimaryButtonDown()) {
if (event.getGestureSource() == event.getSource()) {
- stateProperty.set(GUIGeneState.SOURCE);
+ setState(GUIGeneState.SOURCE);
} else {
- stateProperty.set(isLocked() ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
+ setState(isLocked() ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
}
}
}
@@ -164,7 +149,7 @@ public class GUIOutput extends GUIGene {
}
source.updateLines();
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
}
});
@@ -173,8 +158,8 @@ public class GUIOutput extends GUIGene {
@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);
+ if (getState() == GUIGeneState.NEUTRAL) {
+ setState(GUIGeneState.HOVER);
}
}
});
@@ -190,8 +175,8 @@ public class GUIOutput extends GUIGene {
@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 && !isLocked()) {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ if (getState() == GUIGeneState.HOVER && !isLocked()) {
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
}
@@ -199,52 +184,49 @@ public class GUIOutput extends GUIGene {
getChildren().addAll(mainCircle, text, socket, connectionLabel);
+
+ }
- stateProperty.addListener(new ChangeListener<GUIGeneState>() {
- @Override
- public void changed(ObservableValue<? extends GUIGeneState> observable, GUIGeneState oldValue, GUIGeneState newValue) {
-
-
- switch (newValue) {
- case ACTIVE_HOVER:
- break;
- case FORBIDDEN_TARGET:
- mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
- break;
- case HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
- sourceLine.setVisible(true);
- if (!isLocked()) {
- setConnections(GUIGeneState.ACTIVE_HOVER);
- }
- break;
- case INDIRECT_HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- break;
- case NEUTRAL:
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
- sourceLine.setVisible(false);
- break;
- case NO_CHANGE_TARGET:
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR));
- break;
- case SOURCE:
- mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR));
- setConnections(GUIGeneState.NEUTRAL);
- setConnections(GUIGeneState.INDIRECT_HOVER);
- break;
- case TARGET:
- mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
- break;
- default:
- break;
-
- }
+ @Override
+ public void setState(GUIGeneState newState) {
+ super.setState(newState);
+
+ switch (newState) {
+ case ACTIVE_HOVER:
+ break;
+ case FORBIDDEN_TARGET:
+ mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
+ break;
+ case HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
+ sourceLine.setVisible(true);
+ if (!isLocked()) {
+ setConnections(GUIGeneState.ACTIVE_HOVER);
}
- });
-
+ break;
+ case INDIRECT_HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
+ break;
+ case NEUTRAL:
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
+ sourceLine.setVisible(false);
+ break;
+ case NO_CHANGE_TARGET:
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR));
+ break;
+ case SOURCE:
+ mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR));
+ setConnections(GUIGeneState.NEUTRAL);
+ setConnections(GUIGeneState.INDIRECT_HOVER);
+ break;
+ case TARGET:
+ mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
+ break;
+ default:
+ break;
+ }
}
-
+
@Override
public void updateLines() {
if (output.getSource() instanceof Node) {
@@ -272,10 +254,10 @@ public class GUIOutput extends GUIGene {
@Override
public void resetState() {
if (locked > 0) {
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
setConnections(GUIGeneState.HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
}
@@ -318,14 +300,14 @@ public class GUIOutput extends GUIGene {
public void unlock() {
if (isLocked()) {
setLocked(false);
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
}
public void lock() {
if (!isLocked()) {
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
setLocked(true);
}
}
diff --git a/src/jcgp/gui/population/PopulationPane.java b/src/jcgp/gui/population/PopulationPane.java
new file mode 100644
index 0000000..3a83a86
--- /dev/null
+++ b/src/jcgp/gui/population/PopulationPane.java
@@ -0,0 +1,49 @@
+package jcgp.gui.population;
+
+import javafx.scene.control.Tab;
+import javafx.scene.control.TabPane;
+import jcgp.JCGP;
+import jcgp.backend.population.Population;
+import jcgp.backend.resources.Resources;
+
+public class PopulationPane extends TabPane {
+
+ public PopulationPane(JCGP jcgp) {
+ super();
+
+ setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
+
+ remakeTabs(jcgp.getPopulation(), jcgp.getResources());
+ }
+
+ public void remakeTabs(Population population, Resources resources) {
+ getTabs().clear();
+
+ Tab tab;
+ ChromosomePane cp;
+ for (int i = 0; i < resources.getInt("popSize"); i++) {
+ cp = new ChromosomePane(population.getChromosome(i), resources);
+ tab = new Tab("Chr " + i);
+ tab.setContent(cp);
+ getTabs().add(tab);
+ }
+ }
+
+ public void updateGenes() {
+ for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ ((ChromosomePane) getTabs().get(i).getContent()).updateGenes();
+ }
+ }
+
+ public void unlockOutputs() {
+ for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ ((ChromosomePane) getTabs().get(i).getContent()).unlockOutputs();
+ }
+ }
+
+ public void relockOutputs() {
+ for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ ((ChromosomePane) getTabs().get(i).getContent()).relockOutputs();
+ }
+ }
+}