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.java106
-rw-r--r--src/jcgp/gui/population/GUIConnection.java7
-rw-r--r--src/jcgp/gui/population/GUIGene.java44
-rw-r--r--src/jcgp/gui/population/GUIInput.java18
-rw-r--r--src/jcgp/gui/population/GUIMutable.java9
-rw-r--r--src/jcgp/gui/population/GUINode.java67
-rw-r--r--src/jcgp/gui/population/GUIOutput.java23
-rw-r--r--src/jcgp/gui/population/PopulationPane.java2
8 files changed, 228 insertions, 48 deletions
diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java
index f09d452..ede01e0 100644
--- a/src/jcgp/gui/population/ChromosomePane.java
+++ b/src/jcgp/gui/population/ChromosomePane.java
@@ -1,7 +1,10 @@
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;
@@ -26,16 +29,20 @@ public class ChromosomePane extends ScrollPane {
private GUIInput[] guiInputs;
private GUIOutput[] guiOutputs;
+ private ArrayList<Line> connectionLines;
+
private Pane content;
private int rows, columns;
private boolean target = false;
- public ChromosomePane(Chromosome chromosome, GUI gui, PopulationPane parent) {
+ public ChromosomePane(Chromosome chromosome) {
super();
- final Resources resources = gui.getExperiment().getResources();
+ final Resources resources = GUI.resources;
+
+ connectionLines = new ArrayList<Line>();
rows = resources.rows();
columns = resources.columns();
@@ -44,7 +51,9 @@ public class ChromosomePane extends ScrollPane {
content.setId("content pane for genes");
// generate the GUIGenes
- // inputs
+ /*
+ * inputs
+ */
guiInputs = new GUIInput[resources.inputs()];
for (int i = 0; i < guiInputs.length; i++) {
// make the GUI elements
@@ -54,43 +63,91 @@ public class ChromosomePane extends ScrollPane {
GUIHandlers.addHandlers(guiInputs[i]);
}
content.getChildren().addAll(guiInputs);
- // nodes
+
+ /*
+ * nodes
+ */
guiNodes = new GUINode[rows][columns];
+ double angle, xPos, yPos;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
+ // make the connection lines
+ Line lines[] = new Line[resources.arity()];
+ for (int l = 0; l < lines.length; l++) {
+ angle = ((((double) (l + 1)) / ((double) (lines.length + 1))) * Constants.THETA) - (Constants.THETA / 2);
+ xPos = (-Math.cos(angle) * Constants.NODE_RADIUS) + (((c + 1) * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.NODE_RADIUS);
+ yPos = (Math.sin(angle) * Constants.NODE_RADIUS) + ((r * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.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(chromosome.getNode(r, c));
+ guiNodes[r][c] = new GUINode(chromosome.getNode(r, c), lines) {
+ @Override
+ public GUIConnection getGUIConnection(Connection connection) {
+ if (connection instanceof Input) {
+ return guiInputs[((Input) connection).getIndex()];
+ } else if (connection instanceof Node) {
+ return guiNodes[((Node) connection).getRow()][((Node) connection).getColumn()];
+ } else {
+ // something bad happened!
+ throw new ClassCastException();
+ }
+ }
+ };
guiNodes[r][c].relocate(((chromosome.getNode(r, c).getColumn() + 1) * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.NODE_RADIUS,
(chromosome.getNode(r, c).getRow() * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.NODE_RADIUS);
GUIHandlers.addHandlers(guiNodes[r][c]);
}
content.getChildren().addAll(guiNodes[r]);
}
- // outputs
+
+ /*
+ * outputs
+ */
guiOutputs = new GUIOutput[resources.outputs()];
for (int i = 0; i < guiOutputs.length; i++) {
// make the GUI elements
- guiOutputs[i] = new GUIOutput(chromosome.getOutput(i));
+ guiOutputs[i] = new GUIOutput(chromosome.getOutput(i)) {
+
+ @Override
+ public GUIConnection getGUIConnection(Connection connection) {
+ if (connection instanceof Input) {
+ return guiInputs[((Input) connection).getIndex()];
+ } else if (connection instanceof Node) {
+ return guiNodes[((Node) connection).getRow()][((Node) connection).getColumn()];
+ } else {
+ // something bad happened!
+ throw new ClassCastException();
+ }
+ }
+
+ };
guiOutputs[i].relocate(((resources.columns() + 1) * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.NODE_RADIUS,
(chromosome.getOutput(i).getIndex() * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.NODE_RADIUS);
GUIHandlers.addHandlers(guiOutputs[i]);
}
content.getChildren().addAll(guiOutputs);
+ // add lines to the pane as on top of genes
+ content.getChildren().addAll(connectionLines);
+
setPrefWidth(620);
setContent(content);
}
- protected 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();
- }
- }
+// protected 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();
+// }
+// }
protected boolean isTarget() {
return target;
@@ -111,7 +168,7 @@ public class ChromosomePane extends ScrollPane {
}
}
- public static boolean isAllowed(GUIGene source, GUIGene target) {
+ 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) {
@@ -119,23 +176,18 @@ public class ChromosomePane extends ScrollPane {
} 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() <= 1 /* TODO this should be levels back */) {
+ if (s.getColumn() - t.getColumn() > 0 && s.getColumn() - t.getColumn() <= GUI.resources.levelsBack()) {
return true;
}
- return false;
- } else if (target instanceof GUIOutput) {
- return false;
- } else {
- throw new ClassCastException("Target was neither GUINode nor GUIInput nor GUIOutput.");
}
+ 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 if (target instanceof GUIOutput) {
- return false;
} else {
- throw new ClassCastException("Target was neither GUINode nor GUIInput nor GUIOutput.");
+ // this should never happen...
+ return false;
}
}
// if the source was neither node nor output, something bad is happening
diff --git a/src/jcgp/gui/population/GUIConnection.java b/src/jcgp/gui/population/GUIConnection.java
new file mode 100644
index 0000000..76d4a41
--- /dev/null
+++ b/src/jcgp/gui/population/GUIConnection.java
@@ -0,0 +1,7 @@
+package jcgp.gui.population;
+
+public abstract class GUIConnection extends GUIGene {
+
+ abstract void activeHover(boolean value);
+
+}
diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java
index eb7070c..6e61875 100644
--- a/src/jcgp/gui/population/GUIGene.java
+++ b/src/jcgp/gui/population/GUIGene.java
@@ -21,9 +21,17 @@ import jcgp.gui.constants.Constants;
*/
public abstract class GUIGene extends Group {
+ public enum GUIGeneState {
+ NEUTRAL,
+ HOVER,
+ EXTENDED_HOVER
+ }
+
+ private GUIGeneState currentState = GUIGeneState.NEUTRAL;
+
private Text text = new Text();
- protected final Circle mainCircle = new Circle(Constants.NODE_RADIUS, Paint.valueOf(Constants.NEUTRAL_COLOUR));
-
+ private Circle mainCircle = new Circle(Constants.NODE_RADIUS, Paint.valueOf(Constants.NEUTRAL_COLOUR));
+
/**
* Initialises the {@code Text} and {@code Circle} objects so that all genes are standardised.
*/
@@ -34,12 +42,12 @@ public abstract class GUIGene extends Group {
text.setWrappingWidth(Constants.NODE_RADIUS * 2);
text.setX(-Constants.NODE_RADIUS);
text.setVisible(true);
-
+
mainCircle.setStroke(Paint.valueOf("black"));
-
+
getChildren().addAll(mainCircle, text);
}
-
+
/**
* Sets the gene's text field.
*
@@ -48,8 +56,30 @@ public abstract class GUIGene extends Group {
public void setText(String newText) {
text.setText(newText);
}
-
+
+ public GUIGeneState getState() {
+ return currentState;
+ }
+
+ void setState(GUIGeneState newState) {
+ switch (newState) {
+ case NEUTRAL:
+ mainCircle.setFill(Paint.valueOf(Constants.NEUTRAL_COLOUR));
+ break;
+ case HOVER:
+ mainCircle.setFill(Paint.valueOf(Constants.MEDIUM_HIGHLIGHT_COLOUR));
+ break;
+ case EXTENDED_HOVER:
+ mainCircle.setFill(Paint.valueOf(Constants.SOFT_HIGHLIGHT_COLOUR));
+ break;
+
+ default:
+ break;
+ }
+ currentState = newState;
+ }
+
public abstract void mouseEnter();
public abstract void mouseExit();
-
+
}
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index d29851e..0fdf841 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -1,6 +1,7 @@
package jcgp.gui.population;
import javafx.scene.paint.Paint;
+import javafx.scene.shape.Circle;
import jcgp.backend.population.Input;
import jcgp.gui.constants.Constants;
@@ -10,23 +11,34 @@ import jcgp.gui.constants.Constants;
* @author Eduardo Pedroni
*
*/
-public class GUIInput extends GUIGene {
+public class GUIInput extends GUIConnection {
/**
* @param input
*/
public GUIInput(final Input input) {
super();
+
+ Circle outputSocket = new Circle(Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Paint.valueOf("white"));
+ outputSocket.setId(String.valueOf(0));
+ outputSocket.setStroke(Paint.valueOf("black"));
+
+ getChildren().addAll(outputSocket);
}
@Override
public void mouseEnter() {
- mainCircle.setFill(Paint.valueOf(Constants.SOFT_HIGHLIGHT_COLOUR));
+ setState(GUIGeneState.HOVER);
}
@Override
public void mouseExit() {
- mainCircle.setFill(Paint.valueOf(Constants.NEUTRAL_COLOUR));
+ setState(GUIGeneState.NEUTRAL);
+ }
+
+ @Override
+ public void activeHover(boolean value) {
+ setState(value ? GUIGeneState.EXTENDED_HOVER : GUIGeneState.NEUTRAL);
}
}
diff --git a/src/jcgp/gui/population/GUIMutable.java b/src/jcgp/gui/population/GUIMutable.java
new file mode 100644
index 0000000..0a28ed6
--- /dev/null
+++ b/src/jcgp/gui/population/GUIMutable.java
@@ -0,0 +1,9 @@
+package jcgp.gui.population;
+
+import jcgp.backend.population.Connection;
+
+public interface GUIMutable {
+
+ GUIConnection getGUIConnection(Connection connection);
+
+}
diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java
index 7b59162..6b6bafc 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -1,19 +1,60 @@
package jcgp.gui.population;
+import javafx.scene.control.Label;
import javafx.scene.paint.Paint;
+import javafx.scene.shape.Circle;
+import javafx.scene.shape.Line;
+import jcgp.backend.population.Input;
import jcgp.backend.population.Node;
+import jcgp.gui.GUI;
import jcgp.gui.constants.Constants;
-public class GUINode extends GUIGene {
+public abstract class GUINode extends GUIConnection implements GUIMutable {
private Node node;
+ private Line[] connectionLines;
-
- public GUINode(final Node node) {
+ public GUINode(Node node, Line[] connectionLines) {
super();
-
// store references
this.node = node;
+ this.connectionLines = connectionLines;
+
+ Label connectionNumber = new Label();
+ connectionNumber.setStyle("-fx-background-color:rgb(255, 255, 255); -fx-border-color:rgba(0, 0, 0, 0.5);");
+ connectionNumber.setVisible(false);
+
+ Circle output = new Circle(Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Paint.valueOf("white"));
+ output.setStroke(Paint.valueOf("black"));
+
+ Circle[] sockets = new Circle[GUI.resources.arity()];
+ double angle, xPos, yPos;
+ for (int l = 0; l < sockets.length; l++) {
+ angle = (((l + 1) / ((double) (GUI.resources.arity() + 1))) * Constants.THETA) - (Constants.THETA / 2);
+ xPos = -Math.cos(angle) * Constants.NODE_RADIUS;
+ yPos = Math.sin(angle) * Constants.NODE_RADIUS;
+
+ sockets[l] = new Circle(xPos, yPos, Constants.SOCKET_RADIUS, Paint.valueOf("white"));
+ sockets[l].setId(String.valueOf(l));
+ sockets[l].setStroke(Paint.valueOf("black"));
+ }
+
+ getChildren().addAll(sockets);
+ getChildren().addAll(output, connectionNumber);
+
+ for (int l = 0; l < connectionLines.length; l++) {
+ if (node.getConnection(l) instanceof Node) {
+ int row = ((Node) node.getConnection(l)).getRow(),
+ column = ((Node) node.getConnection(l)).getColumn();
+ connectionLines[l].setEndX(((column + 1) * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + 2 * Constants.NODE_RADIUS);
+ connectionLines[l].setEndY((row * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.NODE_RADIUS);
+ } else if (node.getConnection(l) instanceof Input) {
+ int inputIndex = ((Input) node.getConnection(l)).getIndex();
+ connectionLines[l].setEndX(2 * Constants.NODE_RADIUS);
+ connectionLines[l].setEndY(inputIndex * (2 * Constants.NODE_RADIUS + Constants.SPACING) + Constants.NODE_RADIUS);
+ }
+ }
+
}
public Node getNode() {
@@ -27,12 +68,26 @@ public class GUINode extends GUIGene {
@Override
public void mouseEnter() {
- mainCircle.setFill(Paint.valueOf(Constants.SOFT_HIGHLIGHT_COLOUR));
+ setState(GUIGeneState.HOVER);
+ for (int i = 0; i < GUI.resources.arity(); i++) {
+ getGUIConnection(node.getConnection(i)).setState(GUIGeneState.EXTENDED_HOVER);
+ }
}
@Override
public void mouseExit() {
- mainCircle.setFill(Paint.valueOf(Constants.NEUTRAL_COLOUR));
+ setState(GUIGeneState.NEUTRAL);
+ for (int i = 0; i < GUI.resources.arity(); i++) {
+ getGUIConnection(node.getConnection(i)).setState(GUIGeneState.NEUTRAL);
+ }
+ }
+
+ @Override
+ public void activeHover(boolean value) {
+ setState(value ? GUIGeneState.EXTENDED_HOVER : GUIGeneState.NEUTRAL);
+ for (int i = 0; i < GUI.resources.arity(); i++) {
+ getGUIConnection(node.getConnection(i)).activeHover(value);
+ }
}
}
diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java
index ccc96c3..8ae9485 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -1,17 +1,29 @@
package jcgp.gui.population;
+import javafx.scene.control.Label;
import javafx.scene.paint.Paint;
+import javafx.scene.shape.Circle;
import jcgp.backend.population.Output;
import jcgp.gui.constants.Constants;
-public class GUIOutput extends GUIGene {
+public abstract class GUIOutput extends GUIGene implements GUIMutable {
private Output output;
public GUIOutput(final Output output) {
super();
-
this.output = output;
+
+ Circle socket = new Circle(-Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Paint.valueOf("white"));
+ socket.setId(String.valueOf(0));
+ socket.setStroke(Paint.valueOf("black"));
+
+ Label connectionLabel = new Label("S");
+ connectionLabel.setStyle("-fx-background-color:rgb(255, 255, 255); -fx-border-color:rgba(0, 0, 0, 0.5);");
+ connectionLabel.relocate(socket.getCenterX() + 5, socket.getCenterY() - 10);
+ connectionLabel.setVisible(false);
+
+ getChildren().addAll(socket, connectionLabel);
}
void setOutput(Output output2) {
@@ -21,11 +33,14 @@ public class GUIOutput extends GUIGene {
@Override
public void mouseEnter() {
- mainCircle.setFill(Paint.valueOf(Constants.SOFT_HIGHLIGHT_COLOUR));
+ setState(GUIGeneState.HOVER);
+ getGUIConnection(output.getSource()).activeHover(true);
}
@Override
public void mouseExit() {
- mainCircle.setFill(Paint.valueOf(Constants.NEUTRAL_COLOUR));
+ setState(GUIGeneState.NEUTRAL);
+ getGUIConnection(output.getSource()).activeHover(false);
}
+
}
diff --git a/src/jcgp/gui/population/PopulationPane.java b/src/jcgp/gui/population/PopulationPane.java
index 31f6c33..51b5ba4 100644
--- a/src/jcgp/gui/population/PopulationPane.java
+++ b/src/jcgp/gui/population/PopulationPane.java
@@ -27,7 +27,7 @@ public class PopulationPane extends TabPane {
Tab tab;
ChromosomePane cp;
for (int i = 0; i < jcgp.getResources().populationSize(); i++) {
- cp = new ChromosomePane(jcgp.getPopulation().get(i), gui, this);
+ cp = new ChromosomePane(jcgp.getPopulation().get(i));
tab = new Tab("Chr " + i);
tab.setContent(cp);
getTabs().add(tab);