From 9d24ea7759c58e7b1fd4b8c37acc7d16cb7e55fa Mon Sep 17 00:00:00 2001
From: Eduardo Pedroni <e.pedroni91@gmail.com>
Date: Tue, 18 Nov 2014 19:26:18 +0000
Subject: Refactored handlers, separated into input, node and output files.
 Genes are less functional now, ChromosomePane will deal with hand-wired
 connections.

---
 src/jcgp/backend/population/Gene.java       |  20 +++
 src/jcgp/backend/population/Input.java      |   2 +-
 src/jcgp/backend/population/Node.java       |   2 +-
 src/jcgp/backend/population/Output.java     |   2 +-
 src/jcgp/gui/constants/Position.java        |  38 ++++++
 src/jcgp/gui/handlers/GUIHandlers.java      |  27 ----
 src/jcgp/gui/handlers/InputHandlers.java    |  31 +++++
 src/jcgp/gui/handlers/NodeHandlers.java     |  54 ++++++++
 src/jcgp/gui/handlers/OutputHandlers.java   |  39 ++++++
 src/jcgp/gui/population/ChromosomePane.java | 185 +++++++++++++++-------------
 src/jcgp/gui/population/GUIConnection.java  |   6 +-
 src/jcgp/gui/population/GUIGene.java        |  21 ++--
 src/jcgp/gui/population/GUIInput.java       |  24 ++--
 src/jcgp/gui/population/GUIMutable.java     |   3 -
 src/jcgp/gui/population/GUINode.java        |  78 +++++++-----
 src/jcgp/gui/population/GUIOutput.java      |  26 ++--
 16 files changed, 370 insertions(+), 188 deletions(-)
 create mode 100644 src/jcgp/backend/population/Gene.java
 create mode 100644 src/jcgp/gui/constants/Position.java
 delete mode 100644 src/jcgp/gui/handlers/GUIHandlers.java
 create mode 100644 src/jcgp/gui/handlers/InputHandlers.java
 create mode 100644 src/jcgp/gui/handlers/NodeHandlers.java
 create mode 100644 src/jcgp/gui/handlers/OutputHandlers.java

(limited to 'src/jcgp')

diff --git a/src/jcgp/backend/population/Gene.java b/src/jcgp/backend/population/Gene.java
new file mode 100644
index 0000000..47c8dfd
--- /dev/null
+++ b/src/jcgp/backend/population/Gene.java
@@ -0,0 +1,20 @@
+package jcgp.backend.population;
+
+/**
+ * TODO comment
+ * 
+ * @author Eduardo Pedroni
+ *
+ */
+public abstract class Gene {
+
+	private Object guiObject;
+	
+	public void setGUIObject(Object guiObject) {
+		this.guiObject = guiObject;
+	}
+	
+	public Object getGUIObject() {
+		return guiObject;
+	}
+}
diff --git a/src/jcgp/backend/population/Input.java b/src/jcgp/backend/population/Input.java
index 97fe82b..7d2590b 100644
--- a/src/jcgp/backend/population/Input.java
+++ b/src/jcgp/backend/population/Input.java
@@ -9,7 +9,7 @@ package jcgp.backend.population;
  * @author Eduardo Pedroni
  *
  */
-public class Input implements Connection {
+public class Input extends Gene implements Connection {
 	
 	private Object value;
 	private int index;
diff --git a/src/jcgp/backend/population/Node.java b/src/jcgp/backend/population/Node.java
index 6696694..a9131d1 100644
--- a/src/jcgp/backend/population/Node.java
+++ b/src/jcgp/backend/population/Node.java
@@ -25,7 +25,7 @@ import jcgp.backend.resources.Resources;
  * @author Eduardo Pedroni
  *
  */
-public class Node implements Mutable, Connection {
+public class Node extends Gene implements Mutable, Connection {
 
 	private Function function;
 	private Connection[] connections;
diff --git a/src/jcgp/backend/population/Output.java b/src/jcgp/backend/population/Output.java
index a346d4a..c87f97c 100644
--- a/src/jcgp/backend/population/Output.java
+++ b/src/jcgp/backend/population/Output.java
@@ -16,7 +16,7 @@ import java.util.ArrayList;
  * @author Eduardo Pedroni
  *
  */
-public class Output implements Mutable {
+public class Output extends Gene implements Mutable {
 	
 	private Connection source;
 	private Chromosome chromosome;
diff --git a/src/jcgp/gui/constants/Position.java b/src/jcgp/gui/constants/Position.java
new file mode 100644
index 0000000..0ea1299
--- /dev/null
+++ b/src/jcgp/gui/constants/Position.java
@@ -0,0 +1,38 @@
+package jcgp.gui.constants;
+
+import javafx.scene.shape.Line;
+import jcgp.gui.GUI;
+import jcgp.gui.population.GUIGene;
+import jcgp.gui.population.GUIInput;
+import jcgp.gui.population.GUINode;
+import jcgp.gui.population.GUIOutput;
+
+public final class Position {
+	
+	public static void place(GUIInput input) {
+		input.relocate(0,
+				input.getInput().getIndex() * (2 * Constants.NODE_RADIUS + Constants.SPACING));
+	}
+	
+	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);
+		node.relocate(xOffset, yOffset);
+		
+		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);
+		}
+	}
+	
+	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));
+	}
+	
+	public static void connect(Line line, GUIGene target) {
+		line.setEndX(target.getLayoutX() + Constants.NODE_RADIUS);
+		line.setEndY(target.getLayoutY());
+	}
+}
diff --git a/src/jcgp/gui/handlers/GUIHandlers.java b/src/jcgp/gui/handlers/GUIHandlers.java
deleted file mode 100644
index ca2a324..0000000
--- a/src/jcgp/gui/handlers/GUIHandlers.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package jcgp.gui.handlers;
-
-import javafx.event.EventHandler;
-import javafx.scene.input.MouseEvent;
-import jcgp.gui.population.GUIGene;
-
-public class GUIHandlers {
-
-	private static final EventHandler<MouseEvent> mouseEnteredHandler = new EventHandler<MouseEvent>() {
-		@Override
-		public void handle(MouseEvent event) {
-			((GUIGene) event.getSource()).mouseEnter();
-		}
-	};
-	
-	private static final EventHandler<MouseEvent> mouseExitedHandler = new EventHandler<MouseEvent>() {
-		@Override
-		public void handle(MouseEvent event) {
-			((GUIGene) event.getSource()).mouseExit();
-		}
-	};
-	
-	public static void addHandlers(GUIGene gene) {
-		gene.addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEnteredHandler);
-		gene.addEventHandler(MouseEvent.MOUSE_EXITED, mouseExitedHandler);
-	}
-}
diff --git a/src/jcgp/gui/handlers/InputHandlers.java b/src/jcgp/gui/handlers/InputHandlers.java
new file mode 100644
index 0000000..d0a8812
--- /dev/null
+++ b/src/jcgp/gui/handlers/InputHandlers.java
@@ -0,0 +1,31 @@
+package jcgp.gui.handlers;
+
+import javafx.event.EventHandler;
+import javafx.scene.input.MouseEvent;
+import jcgp.gui.population.GUIGene.GUIGeneState;
+import jcgp.gui.population.GUIInput;
+
+public final class InputHandlers {
+
+	private static EventHandler<MouseEvent> mouseEnteredHandler = new EventHandler<MouseEvent>() {
+		@Override
+		public void handle(MouseEvent event) {
+			//((GUIGene) event.getSource()).mouseEnter();
+			((GUIInput) event.getSource()).setState(GUIGeneState.HOVER);
+		}
+	};
+	
+	private static EventHandler<MouseEvent> mouseExitedHandler = new EventHandler<MouseEvent>() {
+		@Override
+		public void handle(MouseEvent event) {
+			//((GUIGene) event.getSource()).mouseExit();
+			((GUIInput) event.getSource()).setState(GUIGeneState.NEUTRAL);
+		}
+	};
+	
+	public static void addHandlers(GUIInput input) {
+		input.addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEnteredHandler);
+		input.addEventHandler(MouseEvent.MOUSE_EXITED, mouseExitedHandler);
+	}
+	
+}
diff --git a/src/jcgp/gui/handlers/NodeHandlers.java b/src/jcgp/gui/handlers/NodeHandlers.java
new file mode 100644
index 0000000..9d1f6a8
--- /dev/null
+++ b/src/jcgp/gui/handlers/NodeHandlers.java
@@ -0,0 +1,54 @@
+package jcgp.gui.handlers;
+
+import javafx.event.EventHandler;
+import javafx.scene.input.MouseEvent;
+import jcgp.backend.population.Gene;
+import jcgp.gui.GUI;
+import jcgp.gui.population.GUIGene;
+import jcgp.gui.population.GUIGene.GUIGeneState;
+import jcgp.gui.population.GUINode;
+
+public final class NodeHandlers {
+
+	private static EventHandler<MouseEvent> mouseEnteredHandler = new EventHandler<MouseEvent>() {
+		@Override
+		public void handle(MouseEvent event) {
+			// acquire the source, we can safely cast it to GUINode
+			GUINode source = (GUINode) event.getSource();
+
+			source.setState(GUIGeneState.HOVER);
+
+			/*
+			 * What have I done? Have I gone too far?
+			 * Have I unleashed an evil beyond control?
+			 * Will the gods of type casting ever forgive me?
+			 */
+			for (int i = 0; i < GUI.resources.arity(); i++) {
+				((GUIGene) ((Gene) source.getNode().getConnection(i)).getGUIObject()).setState(GUIGeneState.EXTENDED_HOVER);
+			}
+		}
+	};
+
+	private static EventHandler<MouseEvent> mouseExitedHandler = new EventHandler<MouseEvent>() {
+		@Override
+		public void handle(MouseEvent event) {
+			// acquire the source, we can safely cast it to GUINode
+			GUINode source = (GUINode) event.getSource();
+
+			source.setState(GUIGeneState.NEUTRAL);
+
+			/*
+			 * Is this the end? Is there any hope for salvation?
+			 * Am I damned beyond redemption?
+			 */
+			for (int i = 0; i < GUI.resources.arity(); i++) {
+				((GUIGene) ((Gene) source.getNode().getConnection(i)).getGUIObject()).setState(GUIGeneState.NEUTRAL);
+			}
+		}
+	};
+
+	public static void addHandlers(GUINode node) {
+		node.addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEnteredHandler);
+		node.addEventHandler(MouseEvent.MOUSE_EXITED, mouseExitedHandler);
+	}
+}
diff --git a/src/jcgp/gui/handlers/OutputHandlers.java b/src/jcgp/gui/handlers/OutputHandlers.java
new file mode 100644
index 0000000..31d6380
--- /dev/null
+++ b/src/jcgp/gui/handlers/OutputHandlers.java
@@ -0,0 +1,39 @@
+package jcgp.gui.handlers;
+
+import javafx.event.EventHandler;
+import javafx.scene.input.MouseEvent;
+import jcgp.backend.population.Gene;
+import jcgp.gui.population.GUIConnection;
+import jcgp.gui.population.GUIGene.GUIGeneState;
+import jcgp.gui.population.GUIOutput;
+
+public final class OutputHandlers {
+
+	private static EventHandler<MouseEvent> mouseEnteredHandler = new EventHandler<MouseEvent>() {
+		@Override
+		public void handle(MouseEvent event) {
+			// acquire the source, we can safely cast it to GUIOutput
+			GUIOutput source = (GUIOutput) event.getSource();
+
+			source.setState(GUIGeneState.HOVER);
+			((GUIConnection) ((Gene) source.getOutput().getSource()).getGUIObject()).setStateRecursively(GUIGeneState.ACTIVE_HOVER);
+		}
+	};
+
+	private static EventHandler<MouseEvent> mouseExitedHandler = new EventHandler<MouseEvent>() {
+		@Override
+		public void handle(MouseEvent event) {
+			// acquire the source, we can safely cast it to GUIOutput
+			GUIOutput source = (GUIOutput) event.getSource();
+
+			source.setState(GUIGeneState.NEUTRAL);
+			((GUIConnection) ((Gene) source.getOutput().getSource()).getGUIObject()).setStateRecursively(GUIGeneState.NEUTRAL);
+		}
+	};
+
+	public static void addHandlers(GUIOutput output) {
+		output.addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEnteredHandler);
+		output.addEventHandler(MouseEvent.MOUSE_EXITED, mouseExitedHandler);
+	}
+
+}
diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java
index ede01e0..6a5b33f 100644
--- a/src/jcgp/gui/population/ChromosomePane.java
+++ b/src/jcgp/gui/population/ChromosomePane.java
@@ -6,13 +6,15 @@ 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.Gene;
 import jcgp.backend.population.Input;
 import jcgp.backend.population.Node;
-import jcgp.backend.resources.Resources;
+import jcgp.backend.population.Output;
 import jcgp.gui.GUI;
-import jcgp.gui.constants.Constants;
-import jcgp.gui.handlers.GUIHandlers;
+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
@@ -28,135 +30,129 @@ public class ChromosomePane extends ScrollPane {
 	private GUINode[][] guiNodes;
 	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) {
 		super();
-		
-		final Resources resources = GUI.resources;
-		
-		connectionLines = new ArrayList<Line>();
-		
-		rows = resources.rows();
-		columns = resources.columns();
-		
+
+		ArrayList<Line> connectionLines = new ArrayList<Line>();
+
+		rows = GUI.resources.rows();
+		columns = GUI.resources.columns();
+
 		content = new Pane();
 		content.setId("content pane for genes");
-		
+
 		// generate the GUIGenes
 		/* 
 		 * inputs
 		 */
-		guiInputs = new GUIInput[resources.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(chromosome.getInput(i));
-			guiInputs[i].relocate(Constants.NODE_RADIUS,
-					(chromosome.getInput(i).getIndex() * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.NODE_RADIUS);
-			GUIHandlers.addHandlers(guiInputs[i]);
+			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]);
 		}
 		content.getChildren().addAll(guiInputs);
-		
-		/* 
+
+		/*
 		 * nodes
 		 */
 		guiNodes = new GUINode[rows][columns];
-		double angle, xPos, yPos;
-		for (int r = 0; r < rows; r++) {
-			for (int c = 0; c < columns; c++) {
+		//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[resources.arity()];
+				Line lines[] = new Line[GUI.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();
+					
+//					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) + Constants.SOCKET_RADIUS;
+//					yPos = (Math.sin(angle) * Constants.NODE_RADIUS) + ((r * (2 * Constants.NODE_RADIUS + Constants.SPACING)) + Constants.NODE_RADIUS);
+//					lines[l].setStartX(xPos);
+//					lines[l].setStartX(yPos);
+					
+					Position.connect(lines[l], (GUIGene) ((Gene) node.getConnection(l)).getGUIObject());
 					
-					lines[l] = new Line(xPos, yPos, xPos, yPos);
 					lines[l].setMouseTransparent(true);
-					//lines[l].setVisible(false);
+					lines[l].setVisible(false);
 					connectionLines.add(lines[l]);
 				}
 				// make the GUI elements
-				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]);
+				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]);
+				content.getChildren().add(guiNodes[r][c]);
 			}
-			content.getChildren().addAll(guiNodes[r]);
 		}
-		
+
 		/* 
 		 * outputs
 		 */
-		guiOutputs = new GUIOutput[resources.outputs()];
+		guiOutputs = new GUIOutput[GUI.resources.outputs()];
 		for (int i = 0; i < guiOutputs.length; i++) {
+			Line line = new Line();
+			// get the backend output
+			Output output = chromosome.getOutput(i);
 			// make the GUI elements
-			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]);
+			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);
 		}
 		content.getChildren().addAll(guiOutputs);
 
-		// add lines to the pane as on top of genes
+		// add lines to the pane 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();
-//		}	
-//	}
-	
+
+
+	/*
+	 * 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;
 	}
-	
+
 	protected void setTarget(boolean newValue) {
 		target = newValue;
 	}
-	
+
 	public void updateGenes(Chromosome chr) {
 		for (int r = 0; r < rows; r++) {
 			for (int c = 0; c < columns; c++) {
@@ -167,7 +163,7 @@ public class ChromosomePane extends ScrollPane {
 			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
@@ -193,4 +189,15 @@ 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 76d4a41..5fc857b 100644
--- a/src/jcgp/gui/population/GUIConnection.java
+++ b/src/jcgp/gui/population/GUIConnection.java
@@ -1,7 +1,9 @@
 package jcgp.gui.population;
 
-public abstract class GUIConnection extends GUIGene {
+import jcgp.gui.population.GUIGene.GUIGeneState;
 
-	abstract void activeHover(boolean value);
+public interface GUIConnection {
+
+	public void setStateRecursively(GUIGeneState state);
 	
 }
diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java
index 6e61875..032d217 100644
--- a/src/jcgp/gui/population/GUIGene.java
+++ b/src/jcgp/gui/population/GUIGene.java
@@ -24,7 +24,8 @@ public abstract class GUIGene extends Group {
 	public enum GUIGeneState {
 		NEUTRAL,
 		HOVER,
-		EXTENDED_HOVER
+		EXTENDED_HOVER,
+		ACTIVE_HOVER
 	}
 
 	private GUIGeneState currentState = GUIGeneState.NEUTRAL;
@@ -44,8 +45,9 @@ public abstract class GUIGene extends Group {
 		text.setVisible(true);
 
 		mainCircle.setStroke(Paint.valueOf("black"));
-
+		
 		getChildren().addAll(mainCircle, text);
+		
 	}
 
 	/**
@@ -61,16 +63,23 @@ public abstract class GUIGene extends Group {
 		return currentState;
 	}
 
-	void setState(GUIGeneState newState) {
+	public void setState(GUIGeneState newState) {
 		switch (newState) {
 		case NEUTRAL:
 			mainCircle.setFill(Paint.valueOf(Constants.NEUTRAL_COLOUR));
+			setLinesVisible(false);
 			break;
 		case HOVER:
 			mainCircle.setFill(Paint.valueOf(Constants.MEDIUM_HIGHLIGHT_COLOUR));
+			setLinesVisible(true);
 			break;
 		case EXTENDED_HOVER:
 			mainCircle.setFill(Paint.valueOf(Constants.SOFT_HIGHLIGHT_COLOUR));
+			setLinesVisible(false);
+			break;
+		case ACTIVE_HOVER:
+			mainCircle.setFill(Paint.valueOf(Constants.SOFT_HIGHLIGHT_COLOUR));
+			setLinesVisible(true);
 			break;
 			
 		default:
@@ -78,8 +87,6 @@ public abstract class GUIGene extends Group {
 		}
 		currentState = newState;
 	}
-
-	public abstract void mouseEnter();
-	public abstract void mouseExit();
-
+	
+	protected abstract void setLinesVisible(boolean value);
 }
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index 0fdf841..68952f6 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -11,14 +11,18 @@ import jcgp.gui.constants.Constants;
  * @author Eduardo Pedroni
  *
  */
-public class GUIInput extends GUIConnection {
+public class GUIInput extends GUIGene implements GUIConnection {
 
+	private Input input;
+	
 	/**
 	 * @param input
 	 */
 	public GUIInput(final Input input) {
 		super();
 		
+		this.input = input;
+		
 		Circle outputSocket = new Circle(Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Paint.valueOf("white"));
 		outputSocket.setId(String.valueOf(0));
 		outputSocket.setStroke(Paint.valueOf("black"));
@@ -26,19 +30,17 @@ public class GUIInput extends GUIConnection {
 		getChildren().addAll(outputSocket);
 	}
 
-	@Override
-	public void mouseEnter() {
-		setState(GUIGeneState.HOVER);
+	public Input getInput() {
+		return input;
 	}
 
 	@Override
-	public void mouseExit() {
-		setState(GUIGeneState.NEUTRAL);
+	public void setStateRecursively(GUIGeneState state) {
+		setState(state);
 	}
-	
+
 	@Override
-	public void activeHover(boolean value) {
-		setState(value ? GUIGeneState.EXTENDED_HOVER : GUIGeneState.NEUTRAL);
-	}
-	
+	protected void setLinesVisible(boolean value) {
+		// blank
+	}	
 }
diff --git a/src/jcgp/gui/population/GUIMutable.java b/src/jcgp/gui/population/GUIMutable.java
index 0a28ed6..e51b54e 100644
--- a/src/jcgp/gui/population/GUIMutable.java
+++ b/src/jcgp/gui/population/GUIMutable.java
@@ -1,9 +1,6 @@
 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 6b6bafc..f8f2e20 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -4,21 +4,22 @@ 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.Gene;
 import jcgp.backend.population.Node;
 import jcgp.gui.GUI;
 import jcgp.gui.constants.Constants;
 
-public abstract class GUINode extends GUIConnection implements GUIMutable {
+public class GUINode extends GUIGene implements GUIMutable, GUIConnection {
 
 	private Node node;
-	private Line[] connectionLines;
+	private Line[] lines;
+	private Circle[] sockets;
 	
-	public GUINode(Node node, Line[] connectionLines) {
+	public GUINode(Node node, Line[] lines) {
 		super();
 		// store references
 		this.node = node;
-		this.connectionLines = connectionLines;
+		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);");
@@ -27,7 +28,7 @@ public abstract class GUINode extends GUIConnection implements GUIMutable {
 		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()];
+		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);
@@ -41,20 +42,6 @@ public abstract class GUINode extends GUIConnection implements GUIMutable {
 		
 		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() {
@@ -65,29 +52,52 @@ public abstract class GUINode extends GUIConnection implements GUIMutable {
 		// TODO Auto-generated method stub
 		
 	}
-
-	@Override
-	public void mouseEnter() {
-		setState(GUIGeneState.HOVER);
-		for (int i = 0; i < GUI.resources.arity(); i++) {
-			getGUIConnection(node.getConnection(i)).setState(GUIGeneState.EXTENDED_HOVER);
-		}
+	
+	public Line getLine(int index) {
+		return lines[index];
+	}
+	
+	public Line[] getLines() {
+		return lines;
+	}
+	
+	public Circle getSocket(int index) {
+		return sockets[index];
+	}
+	
+	public Circle[] getSockets() {
+		return sockets;
 	}
 
 	@Override
-	public void mouseExit() {
-		setState(GUIGeneState.NEUTRAL);
+	public void setStateRecursively(GUIGeneState state) {
+		setState(state);
 		for (int i = 0; i < GUI.resources.arity(); i++) {
-			getGUIConnection(node.getConnection(i)).setState(GUIGeneState.NEUTRAL);
+			((GUIConnection) ((Gene) node.getConnection(i)).getGUIObject()).setStateRecursively(state);
 		}
 	}
 
 	@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);
+	protected void setLinesVisible(boolean value) {
+		for (int i = 0; i < lines.length; i++) {
+			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 8ae9485..ebc23d0 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -3,16 +3,19 @@ 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.Output;
 import jcgp.gui.constants.Constants;
 
-public abstract class GUIOutput extends GUIGene implements GUIMutable {
+public class GUIOutput extends GUIGene implements GUIMutable {
 
 	private Output output;
+	private Line line;
 
-	public GUIOutput(final Output output) {
+	public GUIOutput(final Output output, Line line) {
 		super();
 		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));
@@ -27,20 +30,19 @@ public abstract class GUIOutput extends GUIGene implements GUIMutable {
 	}
 
 	void setOutput(Output output2) {
-		// TODO Auto-generated method stub
 		
 	}
-
-	@Override
-	public void mouseEnter() {
-		setState(GUIGeneState.HOVER);
-		getGUIConnection(output.getSource()).activeHover(true);
+	
+	public Output getOutput() {
+		return output;
+	}
+	
+	public Line getLine() {
+		return line;
 	}
 
 	@Override
-	public void mouseExit() {
-		setState(GUIGeneState.NEUTRAL);
-		getGUIConnection(output.getSource()).activeHover(false);
+	protected void setLinesVisible(boolean value) {
+		line.setVisible(true);
 	}
-	
 }
-- 
cgit v1.2.3