aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/jcgp/gui')
-rw-r--r--src/jcgp/gui/constants/Constants.java52
-rw-r--r--src/jcgp/gui/constants/Position.java79
-rw-r--r--src/jcgp/gui/population/ChromosomePane.java90
-rw-r--r--src/jcgp/gui/population/GUIConnection.java15
-rw-r--r--src/jcgp/gui/population/GUIGene.java63
-rw-r--r--src/jcgp/gui/population/GUIInput.java45
-rw-r--r--src/jcgp/gui/population/GUIMutable.java10
-rw-r--r--src/jcgp/gui/population/GUINode.java98
-rw-r--r--src/jcgp/gui/population/GUIOutput.java55
9 files changed, 338 insertions, 169 deletions
diff --git a/src/jcgp/gui/constants/Constants.java b/src/jcgp/gui/constants/Constants.java
index 350f8b1..d53b1ca 100644
--- a/src/jcgp/gui/constants/Constants.java
+++ b/src/jcgp/gui/constants/Constants.java
@@ -1,52 +1,62 @@
package jcgp.gui.constants;
+import javafx.scene.paint.Paint;
+
/**
* Holds the constants used in the GUI.
*
* @author Eduardo Pedroni
*
*/
-public abstract class Constants {
+public final class Constants {
+ /**
+ * Private constructor to prevent instantiation.
+ */
+ private Constants(){}
+
/* Colours */
/**
- * A string containing the hexadecimal colour used for representing neutrality.
+ * A {@code Paint} containing the colour used for representing neutrality.
*/
- public static final String NEUTRAL_COLOUR = "#FFFFFF";
+ public static final Paint NEUTRAL_COLOUR = Paint.valueOf("#FFFFFF");
/**
- * A string containing the hexadecimal colour used for representing a hard highlight.
+ * A {@code Paint} containing the colour used for representing a hard highlight.
* A "hard" select, for instance, happens when an output path is locked on the chromosome
* pane.
*/
- public static final String HARD_HIGHLIGHT_COLOUR = "#5496FF";
+ public static final Paint HARD_HIGHLIGHT_COLOUR = Paint.valueOf("#5496FF");
/**
- * A string containing the hexadecimal colour used for a medium highlight.
+ * A {@code Paint} containing the colour used for a medium highlight.
* One example of such a selection is the colour applied to a node
* when it is hovered over.
*/
- public static final String MEDIUM_HIGHLIGHT_COLOUR = "#75BAFF";
+ public static final Paint MEDIUM_HIGHLIGHT_COLOUR = Paint.valueOf("#75BAFF");
/**
- * A string containing the hexadecimal colour used for a soft highlight.
+ * A {@code Paint} containing the colour used for a soft highlight.
* When hovering over a node, its connections are soft-selected.
*/
- public static final String SOFT_HIGHLIGHT_COLOUR = "#C7DFFF";
+ public static final Paint SOFT_HIGHLIGHT_COLOUR = Paint.valueOf("#C7DFFF");
/**
- * A string containing the hexadecimal colour used for representing a good selection.
+ * A {@code Paint} containing the colour used for representing a good selection.
* Ideally a shade of green, used for instance when a manual connection is valid.
*/
- public static final String GOOD_SELECTION_COLOUR = "#38C25B";
+ public static final Paint GOOD_SELECTION_COLOUR = Paint.valueOf("#38C25B");
/**
- * A string containing the hexadecimal colour used for representing a neutral selection.
+ * A {@code Paint} containing the colour used for representing a neutral selection.
* Ideally a shade of yellow, used for instance when a manual connection is already the
* current connection.
*/
- public static final String NEUTRAL_SELECTION_COLOUR = "#FFEF73";
+ public static final Paint NEUTRAL_SELECTION_COLOUR = Paint.valueOf("#FFEF73");
/**
- * A string containing the hexadecimal colour used for representing a bad selection.
+ * A {@code Paint} containing the colour used for representing a bad selection.
* Ideally a shade of red, use for instance when a manual connection is not valid.
*/
- public static final String BAD_SELECTION_COLOUR = "#FF5C5C";
-
+ public static final Paint BAD_SELECTION_COLOUR = Paint.valueOf("#FF5C5C");
+ /**
+ * A {@code Paint} containing the colour used for the gene sockets.
+ */
+ public static final Paint SOCKET_COLOUR = Paint.valueOf("#FFFFFF");
/* Sizes and distances */
@@ -74,13 +84,15 @@ public abstract class Constants {
*/
public static final double SPACING = 15;
/**
- * The angle across which the node's sockets are evently distributed.
+ * The margin between the genes and the edge of the chromosome pane.
+ */
+ public static final double CHROMOSOME_PANE_MARGIN = 10;
+ /**
+ * The angle across which the node's sockets are evenly distributed.
*/
public static final double THETA = Math.PI / 1.4;
/**
- * The radius of the connection sockets, calculated as a function of
- * NODE_RADIUS.
- *
+ * The radius of the connection sockets, calculated as a function of NODE_RADIUS.
*/
public static final double SOCKET_RADIUS = Math.sqrt(NODE_RADIUS) / 1.8;
/**
diff --git a/src/jcgp/gui/constants/Position.java b/src/jcgp/gui/constants/Position.java
index a13d21e..144ba6d 100644
--- a/src/jcgp/gui/constants/Position.java
+++ b/src/jcgp/gui/constants/Position.java
@@ -1,5 +1,6 @@
package jcgp.gui.constants;
+import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import jcgp.gui.GUI;
import jcgp.gui.population.GUIGene;
@@ -7,34 +8,98 @@ import jcgp.gui.population.GUIInput;
import jcgp.gui.population.GUINode;
import jcgp.gui.population.GUIOutput;
+/**
+ * Abstracts the task of positioning GUI components.
+ * <br>
+ * Do not instantiate this class; instead, use the {@code public static} methods provided.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
public final class Position {
+ /**
+ * Private constructor to prevent instantiation.
+ */
+ private Position() {}
+
+ /**
+ * Sets the X and Y layouts of the specified input to the appropriate values, according to its index.
+ *
+ * @param input the {@code GUIInput} instance to relocate.
+ */
public static void place(GUIInput input) {
- input.relocate(0,
- input.getInput().getIndex() * (2 * Constants.NODE_RADIUS + Constants.SPACING));
+ // inputs are the first column, so we only worry about the margin and their index
+ input.relocate(Constants.CHROMOSOME_PANE_MARGIN,
+ input.getInput().getIndex() * (2 * Constants.NODE_RADIUS + Constants.SPACING) + Constants.CHROMOSOME_PANE_MARGIN);
}
+ /**
+ * Sets the X and Y layouts of the specified node to the appropriate values, according to its row and column values.
+ * This also connects the start of every line with its respective socket. Therefore, this method should be called at least
+ * once when the {@code GUINode} is instantiated.
+ *
+ * @param node the {@code GUINode} instance to relocate.
+ */
public static void place(GUINode node) {
- // TODO cut down method calls
- double xOffset = ((node.getNode().getColumn() + 1) * (2 * Constants.NODE_RADIUS + Constants.SPACING));
- double yOffset = node.getNode().getRow() * (2 * Constants.NODE_RADIUS + Constants.SPACING);
+ // calculate x and y offsets, in relation to the layout origin
+ double xOffset = (node.getNode().getColumn() + 1) * (2 * Constants.NODE_RADIUS + Constants.SPACING) + Constants.CHROMOSOME_PANE_MARGIN;
+ double yOffset = node.getNode().getRow() * (2 * Constants.NODE_RADIUS + Constants.SPACING) + Constants.CHROMOSOME_PANE_MARGIN;
+
+ // move node
node.relocate(xOffset, yOffset);
+ // use the offset and the socket positions to connect the lines
for (int i = 0; i < GUI.resources.arity(); i++) {
node.getLine(i).setStartX(node.getSocket(i).getCenterX() + xOffset + Constants.NODE_RADIUS + Constants.SOCKET_RADIUS);
node.getLine(i).setStartY(node.getSocket(i).getCenterY() + yOffset + Constants.NODE_RADIUS);
}
}
+ /**
+ * Sets the X and Y layouts of the specified output to the appropriate values, according to its index.
+ * This also connects the start of the output's single line to its single input socket.Therefore,
+ * this method should be called at least once when the {@code GUIOutput} is instantiated.
+ *
+ * @param output the {@code GUIOutput} instance to relocate.
+ */
public static void place(GUIOutput output) {
- output.relocate(((GUI.resources.columns() + 1) * (2 * Constants.NODE_RADIUS + Constants.SPACING)),
- output.getOutput().getIndex() * (2 * Constants.NODE_RADIUS + Constants.SPACING));
+ // the output's position is a function of the number of columns and its own index
+ output.relocate(((GUI.resources.columns() + 1) * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.CHROMOSOME_PANE_MARGIN,
+ output.getOutput().getIndex() * (2 * Constants.NODE_RADIUS + Constants.SPACING) + Constants.CHROMOSOME_PANE_MARGIN);
output.getLine().setStartX(output.getLayoutX() - Constants.NODE_RADIUS);
output.getLine().setStartY(output.getLayoutY());
}
+
+
+ /**
+ * Connects the end of a specified line to the specified gene.
+ *
+ * @param line the line to connect.
+ * @param target the target gene to connect to.
+ */
public static void connect(Line line, GUIGene target) {
+ // set line ends based on the layout position of the target
line.setEndX(target.getLayoutX() + Constants.NODE_RADIUS);
line.setEndY(target.getLayoutY());
}
+
+ /**
+ * Relocates the given socket to the appropriate position given the
+ * socket's index.
+ *
+ * @param index the socket index.
+ * @param socket the {@code Circle} instance to relocate.
+ */
+ public static void placeSocket(int index, Circle socket) {
+ // calculate the angle with respect to the x-axis
+ double angle = (((index + 1) / ((double) (GUI.resources.arity() + 1))) * Constants.THETA) - (Constants.THETA / 2);
+ // convert to cartesian form
+ double xPos = -Math.cos(angle) * Constants.NODE_RADIUS;
+ double yPos = Math.sin(angle) * Constants.NODE_RADIUS;
+ // set centre
+ socket.setCenterX(xPos);
+ socket.setCenterY(yPos);
+ }
}
diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java
index bf9db72..7826dcc 100644
--- a/src/jcgp/gui/population/ChromosomePane.java
+++ b/src/jcgp/gui/population/ChromosomePane.java
@@ -6,20 +6,13 @@ import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import jcgp.backend.population.Chromosome;
-import jcgp.backend.population.Gene;
-import jcgp.backend.population.Input;
import jcgp.backend.population.Node;
-import jcgp.backend.population.Output;
import jcgp.gui.GUI;
-import jcgp.gui.constants.Position;
-import jcgp.gui.handlers.InputHandlers;
-import jcgp.gui.handlers.NodeHandlers;
-import jcgp.gui.handlers.OutputHandlers;
/**
* 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 overlaid over the nodes, inputs and outputs.
+ * all of the connection lines laid over the nodes, inputs and outputs.
*
*
* @author Eduardo Pedroni
@@ -33,8 +26,6 @@ public class ChromosomePane extends ScrollPane {
private Pane content;
- private int rows, columns;
-
private boolean target = false;
public ChromosomePane(Chromosome chromosome) {
@@ -42,58 +33,39 @@ public class ChromosomePane extends ScrollPane {
ArrayList<Line> connectionLines = new ArrayList<Line>();
- rows = GUI.resources.rows();
- columns = GUI.resources.columns();
+ int rows = GUI.resources.rows();
+ int columns = GUI.resources.columns();
content = new Pane();
content.setId("content pane for genes");
- // generate the GUIGenes
/*
* inputs
*/
guiInputs = new GUIInput[GUI.resources.inputs()];
for (int i = 0; i < guiInputs.length; i++) {
- // get the backend input
- Input input = chromosome.getInput(i);
- // make the GUI elements
- guiInputs[i] = new GUIInput(input);
- // assign the GUI object to the associated backend element
- input.setGUIObject(guiInputs[i]);
- // position, handlers
- Position.place(guiInputs[i]);
- InputHandlers.addHandlers(guiInputs[i]);
+ guiInputs[i] = new GUIInput(chromosome.getInput(i));
}
+ // add inputs to content pane
content.getChildren().addAll(guiInputs);
/*
* nodes
*/
guiNodes = new GUINode[rows][columns];
- //double angle, xPos, yPos;
-
for (int c = 0; c < columns; c++) {
for (int r = 0; r < rows; r++) {
- // get the backend node
- Node node = chromosome.getNode(r, c);
// make the connection lines
Line lines[] = new Line[GUI.resources.arity()];
for (int l = 0; l < lines.length; l++) {
lines[l] = new Line();
-
- Position.connect(lines[l], (GUIGene) ((Gene) node.getConnection(l)).getGUIObject());
-
lines[l].setMouseTransparent(true);
lines[l].setVisible(false);
connectionLines.add(lines[l]);
}
- // make the GUI elements
- guiNodes[r][c] = new GUINode(node, lines);
- // assign the GUI object to the associated backend element
- node.setGUIObject(guiNodes[r][c]);
- // position, handlers
- Position.place(guiNodes[r][c]);
- NodeHandlers.addHandlers(guiNodes[r][c]);
+ // 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]);
}
}
@@ -103,45 +75,24 @@ public class ChromosomePane extends ScrollPane {
*/
guiOutputs = new GUIOutput[GUI.resources.outputs()];
for (int i = 0; i < guiOutputs.length; i++) {
- // get the backend output
- Output output = chromosome.getOutput(i);
- // make the GUI elements
+ // make the connection line
Line line = new Line();
- Position.connect(line, (GUIGene) ((Gene) output.getSource()).getGUIObject());
line.setVisible(false);
line.setMouseTransparent(true);
- guiOutputs[i] = new GUIOutput(output, line);
- // assign the GUI object to the associated backend element
- output.setGUIObject(guiOutputs[i]);
- // position, handlers
- Position.place(guiOutputs[i]);
- OutputHandlers.addHandlers(guiOutputs[i]);
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);
+ setPrefWidth(620);
setContent(content);
}
-
- /*
- * does this work lol
- */
- // 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;
}
@@ -151,8 +102,8 @@ public class ChromosomePane extends ScrollPane {
}
public void updateGenes(Chromosome chr) {
- for (int r = 0; r < rows; r++) {
- for (int c = 0; c < columns; c++) {
+ 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));
}
}
@@ -186,15 +137,4 @@ public class ChromosomePane extends ScrollPane {
// if the source was neither node nor output, something bad is happening
throw new ClassCastException("Source was neither GUINode nor GUIOutput.");
}
-
- // private 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();
- // }
- // }
}
diff --git a/src/jcgp/gui/population/GUIConnection.java b/src/jcgp/gui/population/GUIConnection.java
index 5fc857b..c17033a 100644
--- a/src/jcgp/gui/population/GUIConnection.java
+++ b/src/jcgp/gui/population/GUIConnection.java
@@ -2,8 +2,23 @@ package jcgp.gui.population;
import jcgp.gui.population.GUIGene.GUIGeneState;
+/**
+ * A loose equivalent to {@link jcgp.backend.population.Connection}.
+ * <br>
+ * This defines behaviour that all GUI representations of connections
+ * should be capable of.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
public interface GUIConnection {
+ /**
+ * Set the connection's state, but also recursively propagate that state
+ * all the way back to the inputs.
+ *
+ * @param state the state to set.
+ */
public void setStateRecursively(GUIGeneState state);
}
diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java
index 032d217..d6f9638 100644
--- a/src/jcgp/gui/population/GUIGene.java
+++ b/src/jcgp/gui/population/GUIGene.java
@@ -21,33 +21,55 @@ import jcgp.gui.constants.Constants;
*/
public abstract class GUIGene extends Group {
+ /**
+ * This {@code enum} type defines a finite list of all states
+ * a gene can take. Each state represents a particular steady
+ * situation, and has its own GUI appearance associated with it:
+ * a combination of connection line visibility, gene background colour
+ * and other visual characteristics.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
public enum GUIGeneState {
+ /**
+ * No user interaction at all.
+ */
NEUTRAL,
+ /**
+ * User is simply hovering over the node.
+ */
HOVER,
+ /**
+ * User is hovering over a node connected to this one.
+ */
EXTENDED_HOVER,
+ /**
+ * User is hovering over an output connected to this gene.
+ */
ACTIVE_HOVER
}
private GUIGeneState currentState = GUIGeneState.NEUTRAL;
- private Text text = new Text();
- private Circle mainCircle = new Circle(Constants.NODE_RADIUS, Paint.valueOf(Constants.NEUTRAL_COLOUR));
+ private Text text;
+ private Circle mainCircle;
/**
* Initialises the {@code Text} and {@code Circle} objects so that all genes are standardised.
*/
protected GUIGene() {
+ text = new Text();
text.setFont(Font.font("Arial", 12));
text.setTextOrigin(VPos.CENTER);
text.setTextAlignment(TextAlignment.CENTER);
text.setWrappingWidth(Constants.NODE_RADIUS * 2);
text.setX(-Constants.NODE_RADIUS);
- text.setVisible(true);
+ mainCircle = new Circle(Constants.NODE_RADIUS, Constants.NEUTRAL_COLOUR);
mainCircle.setStroke(Paint.valueOf("black"));
getChildren().addAll(mainCircle, text);
-
}
/**
@@ -59,26 +81,43 @@ public abstract class GUIGene extends Group {
text.setText(newText);
}
+ /**
+ * @return the gene's current state.
+ */
public GUIGeneState getState() {
return currentState;
}
- public void setState(GUIGeneState newState) {
+ /**
+ * Gene states are standardised: all gene subclasses behave the same way in each state.
+ * <br>
+ * This design choice was made for the sake of consistency. Rather than controlling the
+ * appearance of the genes with logic in the state transition method AND the mouse handlers,
+ * the states are now consistent across all types of gene. The mouse handlers implement
+ * whatever logic is necessary to determine the gene's new state given a certain user input,
+ * but the states themselves are the same for all genes.
+ * <br>
+ * The transition logic for each type of gene is defined in its respective handler class:
+ * {@code InputHandlers}, {@code NodeHandlers} and {@code OutputHandlers}.
+ *
+ * @param newState the gene's new state.
+ */
+ public final void setState(GUIGeneState newState) {
switch (newState) {
case NEUTRAL:
- mainCircle.setFill(Paint.valueOf(Constants.NEUTRAL_COLOUR));
+ mainCircle.setFill(Constants.NEUTRAL_COLOUR);
setLinesVisible(false);
break;
case HOVER:
- mainCircle.setFill(Paint.valueOf(Constants.MEDIUM_HIGHLIGHT_COLOUR));
+ mainCircle.setFill(Constants.MEDIUM_HIGHLIGHT_COLOUR);
setLinesVisible(true);
break;
case EXTENDED_HOVER:
- mainCircle.setFill(Paint.valueOf(Constants.SOFT_HIGHLIGHT_COLOUR));
+ mainCircle.setFill(Constants.SOFT_HIGHLIGHT_COLOUR);
setLinesVisible(false);
break;
case ACTIVE_HOVER:
- mainCircle.setFill(Paint.valueOf(Constants.SOFT_HIGHLIGHT_COLOUR));
+ mainCircle.setFill(Constants.SOFT_HIGHLIGHT_COLOUR);
setLinesVisible(true);
break;
@@ -88,5 +127,11 @@ public abstract class GUIGene extends Group {
currentState = newState;
}
+ /**
+ * For the sake of practicality, all {@code GUIGene} instances must implement this
+ * method. It sets the visibility of all of the gene's lines, if it has any.
+ *
+ * @param value the visibility value.
+ */
protected abstract void setLinesVisible(boolean value);
}
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index 68952f6..9b5f567 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -4,43 +4,68 @@ import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import jcgp.backend.population.Input;
import jcgp.gui.constants.Constants;
+import jcgp.gui.constants.Position;
+import jcgp.gui.handlers.InputHandlers;
/**
- *
+ * The GUI counterpart of {@link jcgp.backend.population.Input}. This is a
+ * subclass of {@code GUIGene} which represents a chromosome input.
*
* @author Eduardo Pedroni
- *
*/
public class GUIInput extends GUIGene implements GUIConnection {
private Input input;
/**
- * @param input
+ * Instantiate {@code GUIInput} given an {@code Input}.
+ *
+ * @param input the associated backend input.
*/
public GUIInput(final Input input) {
super();
-
+ // store the input, associate itself with it
this.input = input;
+ input.setGUIObject(this);
+ // inputs only have a single output socket
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);
+ outputSocket.setId(String.valueOf(0));
+ getChildren().add(outputSocket);
+
+ // relocate to the right position, add mouse handlers
+ Position.place(this);
+ InputHandlers.addHandlers(this);
}
+ /**
+ * @return the {@code Input} instance associated with this object.
+ */
public Input getInput() {
return input;
}
+
+ /**
+ * Associates this instance with a new input.
+ *
+ * @param input the new input.
+ */
+ void setInput(Input input) {
+ this.input = input;
+ }
+ /* (non-Javadoc)
+ * @see jcgp.gui.population.GUIConnection#setStateRecursively(jcgp.gui.population.GUIGene.GUIGeneState)
+ */
@Override
public void setStateRecursively(GUIGeneState state) {
setState(state);
}
+ /* (non-Javadoc)
+ * @see jcgp.gui.population.GUIGene#setLinesVisible(boolean)
+ */
@Override
- protected void setLinesVisible(boolean value) {
- // blank
- }
+ protected void setLinesVisible(boolean value) {}
}
diff --git a/src/jcgp/gui/population/GUIMutable.java b/src/jcgp/gui/population/GUIMutable.java
index e51b54e..61a8f48 100644
--- a/src/jcgp/gui/population/GUIMutable.java
+++ b/src/jcgp/gui/population/GUIMutable.java
@@ -1,6 +1,16 @@
package jcgp.gui.population;
+/**
+ * A loose equivalent to {@link jcgp.backend.population.Mutable}.
+ * <br>
+ * This defines behaviour that all GUI representations of mutables
+ * should be capable of.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
public interface GUIMutable {
+
}
diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java
index f8f2e20..230d167 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -1,6 +1,5 @@
package jcgp.gui.population;
-import javafx.scene.control.Label;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
@@ -8,63 +7,109 @@ import jcgp.backend.population.Gene;
import jcgp.backend.population.Node;
import jcgp.gui.GUI;
import jcgp.gui.constants.Constants;
+import jcgp.gui.constants.Position;
+import jcgp.gui.handlers.NodeHandlers;
+/**
+ * The GUI counterpart of {@link jcgp.backend.population.Node}. This is a
+ * subclass of {@code GUIGene} which represents a chromosome node.
+ *
+ * @author Eduardo Pedroni
+ */
public class GUINode extends GUIGene implements GUIMutable, GUIConnection {
private Node node;
private Line[] lines;
private Circle[] sockets;
+ /**
+ * Instantiate {@code GUINode} given a {@code Node} and the lines needed
+ * to show its connections.
+ *
+ * @param node the associated backend node.
+ * @param lines the lines used to display connections.
+ */
public GUINode(Node node, Line[] lines) {
super();
- // store references
+ // store references, associate with node
this.node = node;
this.lines = lines;
-
- 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);
+ node.setGUIObject(this);
- Circle output = new Circle(Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Paint.valueOf("white"));
+ // create the output socket
+ Circle output = new Circle(Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Constants.SOCKET_COLOUR);
output.setStroke(Paint.valueOf("black"));
+ // create input sockets
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] = new Circle(Constants.SOCKET_RADIUS, Constants.SOCKET_COLOUR);
sockets[l].setStroke(Paint.valueOf("black"));
+ sockets[l].setId(String.valueOf(l));
+ // relocate them
+ Position.placeSocket(l, sockets[l]);
+ Position.connect(lines[l], (GUIGene) ((Gene) node.getConnection(l)).getGUIObject());
}
+ // add elements
getChildren().addAll(sockets);
- getChildren().addAll(output, connectionNumber);
+ getChildren().add(output);
+
+ // relocate node, add handlers
+ Position.place(this);
+ NodeHandlers.addHandlers(this);
}
+ /**
+ * @return the {@code Node} instance associated with this object.
+ */
public Node getNode() {
return node;
}
- void setNode(Node node2) {
- // TODO Auto-generated method stub
-
+ /**
+ * Associates this instance with a new node.
+ *
+ * @param node the new node.
+ */
+ void setNode(Node node) {
+ this.node = node;
}
+ /**
+ * Returns one of this object's connection lines. Lines are
+ * indexed in the same order as sockets and the connections
+ * they represent.
+ *
+ * @param index the line to return.
+ * @return the indexed line object.
+ */
public Line getLine(int index) {
return lines[index];
}
+ /**
+ * @return the entire {@code Line} array.
+ */
public Line[] getLines() {
return lines;
}
+ /**
+ * Returns one of this object's connection sockets. They are
+ * indexed in the same order as lines and the connections
+ * they represent.
+ *
+ * @param index the socket to return.
+ * @return the indexed socket object.
+ */
public Circle getSocket(int index) {
return sockets[index];
}
+ /**
+ * @return the entire {@code Socket} array.
+ */
public Circle[] getSockets() {
return sockets;
}
@@ -83,21 +128,4 @@ public class GUINode extends GUIGene implements GUIMutable, GUIConnection {
lines[i].setVisible(value);
}
}
-
-// @Override
-// public void updateLines() {
-// 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) + Constants.SOCKET_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);
-// }
-// }
-// }
-
}
diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java
index a07fd90..b281833 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -1,42 +1,71 @@
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.Gene;
import jcgp.backend.population.Output;
import jcgp.gui.constants.Constants;
+import jcgp.gui.constants.Position;
+import jcgp.gui.handlers.OutputHandlers;
+/**
+ * The GUI counterpart of {@link jcgp.backend.population.Output}. This is a
+ * subclass of {@code GUIGene} which represents a chromosome output.
+ *
+ * @author Eduardo Pedroni
+ */
public class GUIOutput extends GUIGene implements GUIMutable {
private Output output;
private Line line;
+ /**
+ * Instantiate {@code GUIOutput} given an {@code Output} and the line needed
+ * to show its connection.
+ *
+ * @param output the associated backend output.
+ * @param line the line used to display connection.
+ */
public GUIOutput(final Output output, Line line) {
super();
+ // store references, associate with backend object
this.output = output;
this.line = line;
-
- Circle socket = new Circle(-Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Paint.valueOf("white"));
- socket.setId(String.valueOf(0));
+ output.setGUIObject(this);
+
+ // create input socket
+ Circle socket = new Circle(-Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Constants.SOCKET_COLOUR);
socket.setStroke(Paint.valueOf("black"));
+ socket.setId(String.valueOf(0));
+ Position.connect(line, (GUIGene) ((Gene) output.getSource()).getGUIObject());
+ getChildren().add(socket);
- 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);
+ // relocate output, add handlers
+ Position.place(this);
+ OutputHandlers.addHandlers(this);
}
- void setOutput(Output output2) {
-
+ /**
+ * Associates this instance with a new output.
+ *
+ * @param output the new output.
+ */
+ void setOutput(Output output) {
+ this.output = output;
}
-
+
+ /**
+ * @return the {@code Output} instance associated with this object.
+ */
public Output getOutput() {
return output;
}
+
+ /**
+ * @return this output's single connection line.
+ */
public Line getLine() {
return line;
}