aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/gui
diff options
context:
space:
mode:
authorEduardo Pedroni <ep625@york.ac.uk>2014-03-24 17:16:51 +0000
committerEduardo Pedroni <ep625@york.ac.uk>2014-03-24 17:16:51 +0000
commitbc4fafb9d3c60993253f7e78c10338c901de653a (patch)
treeb62e6cacc72c0c8ff645744fdaf2ca007f1fc891 /src/jcgp/gui
parenta09124d93c3e31d4e25ffe6c2f0a7663c02c35ed (diff)
Node grid all done and apparently stable.
Diffstat (limited to 'src/jcgp/gui')
-rw-r--r--src/jcgp/gui/SettingsPane.java6
-rw-r--r--src/jcgp/gui/population/ChromosomePane.java62
-rw-r--r--src/jcgp/gui/population/GUIGene.java18
-rw-r--r--src/jcgp/gui/population/GUIInput.java116
-rw-r--r--src/jcgp/gui/population/GUINode.java230
-rw-r--r--src/jcgp/gui/population/GUIOutput.java107
6 files changed, 361 insertions, 178 deletions
diff --git a/src/jcgp/gui/SettingsPane.java b/src/jcgp/gui/SettingsPane.java
index 06c35ec..f7e7767 100644
--- a/src/jcgp/gui/SettingsPane.java
+++ b/src/jcgp/gui/SettingsPane.java
@@ -6,21 +6,21 @@ import java.util.Map.Entry;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
-import jcgp.CGP;
+import jcgp.JCGP;
import jcgp.gui.settings.GUIIntegerParameter;
import jcgp.parameters.IntegerParameter;
import jcgp.parameters.Parameter;
public class SettingsPane extends VBox {
- public SettingsPane(CGP cgp) {
+ public SettingsPane(JCGP cgp) {
super();
setPrefSize(180, 500);
Text parameters = new Text("Parameters");
getChildren().add(parameters);
- Iterator<Entry<String, Parameter>> it = cgp.getResources().getEntries().iterator();
+ Iterator<Entry<String, Parameter>> it = cgp.getResources().iterator();
while (it.hasNext()) {
Parameter p = (Parameter) ((Map.Entry<String, Parameter>) it.next()).getValue();
if (p instanceof IntegerParameter) {
diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java
index 546314e..0c7b3d2 100644
--- a/src/jcgp/gui/population/ChromosomePane.java
+++ b/src/jcgp/gui/population/ChromosomePane.java
@@ -5,8 +5,11 @@ import java.util.ArrayList;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
-import jcgp.CGP.Resources;
+import jcgp.GUI;
import jcgp.population.Chromosome;
+import jcgp.population.Connection;
+import jcgp.population.Input;
+import jcgp.population.Node;
public class ChromosomePane extends ScrollPane {
@@ -19,7 +22,9 @@ public class ChromosomePane extends ScrollPane {
private ArrayList<Line> connectionLines;
- public ChromosomePane(Chromosome chromosome, Resources resources) {
+ private boolean target = false;
+
+ public ChromosomePane(Chromosome chromosome) {
super();
connectionLines = new ArrayList<Line>();
@@ -28,19 +33,19 @@ public class ChromosomePane extends ScrollPane {
// generate the GUIGenes
// inputs
- guiInputs = new GUIInput[(int) resources.get("inputs")];
+ guiInputs = new GUIInput[(int) GUI.resources.get("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[(int) resources.get("rows")][(int) resources.get("columns")];
+ guiNodes = new GUINode[(int) GUI.resources.get("rows")][(int) GUI.resources.get("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[(int) resources.get("arity")];
+ Line lines[] = new Line[(int) GUI.resources.get("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);
@@ -52,15 +57,15 @@ public class ChromosomePane extends ScrollPane {
connectionLines.add(lines[l]);
}
// make the GUI elements
- guiNodes[r][c] = new GUINode(this, chromosome.getNode(r, c), resources, lines);
+ guiNodes[r][c] = new GUINode(this, chromosome.getNode(r, c), lines);
}
content.getChildren().addAll(guiNodes[r]);
}
// outputs
- guiOutputs = new GUIOutput[(int) resources.get("outputs")];
+ guiOutputs = new GUIOutput[(int) GUI.resources.get("outputs")];
for (int i = 0; i < guiOutputs.length; i++) {
- xPos = (((int) resources.get("columns") + 1) * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING));
+ xPos = (((int) GUI.resources.get("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);
@@ -68,7 +73,7 @@ public class ChromosomePane extends ScrollPane {
line.setVisible(false);
connectionLines.add(line);
// make the GUI elements
- guiOutputs[i] = new GUIOutput(this, chromosome.getOutput(i), resources, line);
+ guiOutputs[i] = new GUIOutput(this, chromosome.getOutput(i), line);
content.getChildren().addAll(guiOutputs[i]);
}
@@ -78,20 +83,41 @@ public class ChromosomePane extends ScrollPane {
}
- public GUINode getGuiNode(int row, int column) {
- return guiNodes[row][column];
- }
-
- public GUIInput getGuiInput(int index) {
- return guiInputs[index];
- }
+// public GUINode getGuiNode(int row, int column) {
+// return guiNodes[row][column];
+// }
+//
+// public GUIInput getGuiInput(int index) {
+// return guiInputs[index];
+// }
+//
+// public GUIOutput getGuiOutput(int index) {
+// return guiOutputs[index];
+// }
- public GUIOutput getGuiOutput(int index) {
- return guiOutputs[index];
+ 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 Pane getContentPane() {
return content;
}
+
+
+ public boolean isTarget() {
+ return target;
+ }
+
+ public void setTarget(boolean newValue) {
+ target = newValue;
+ }
}
diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java
index 830192c..1be662e 100644
--- a/src/jcgp/gui/population/GUIGene.java
+++ b/src/jcgp/gui/population/GUIGene.java
@@ -4,6 +4,7 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Group;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
+import jcgp.population.Connection;
import jcgp.population.Gene;
enum GUIGeneState {
@@ -11,6 +12,7 @@ enum GUIGeneState {
HOVER,
INDIRECT_HOVER,
ACTIVE_HOVER,
+ LOCKED_HOVER,
SOURCE,
TARGET,
NO_CHANGE_TARGET,
@@ -52,13 +54,29 @@ public abstract class GUIGene extends Group {
return locked > 0;
}
+ public int getLocks() {
+ return locked;
+ }
+
public abstract void setLocked(boolean value);
+ public abstract void addLocks(int value);
+
+ public abstract void removeLocks(int value);
+
+ public abstract void updateLines();
+
public abstract Gene getGene();
+
+ public abstract void setChangingConnection(Connection newConnection);
+
+ public abstract Connection getChangingConnection();
public abstract void setConnections(GUIGeneState newState);
public abstract void resetState();
+ public abstract void setConnectionLine(GUIGene gene);
+
}
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index bf872dc..ac1a775 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -12,8 +12,8 @@ import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import jcgp.GUI;
+import jcgp.population.Connection;
import jcgp.population.Input;
-import jcgp.population.Node;
import jcgp.population.Output;
public class GUIInput extends GUIGene {
@@ -54,13 +54,13 @@ public class GUIInput extends GUIGene {
public void handle(MouseDragEvent event) {
// the drag has entered this node, react appropriately
// this happens even if we are the source of the drag
+ ((GUIGene) event.getGestureSource()).setConnectionLine((GUIGene) event.getSource());
+
if (event.getGestureSource() instanceof GUINode) {
- Node source = ((GUINode) event.getGestureSource()).getGene();
- for (int i = 0; i < (int) GUI.resources.get("arity"); i++) {
- if (input == source.getConnection(i)) {
- stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
- return;
- }
+ Connection source = ((GUINode) event.getGestureSource()).getChangingConnection();
+ if (input == source) {
+ stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
+ return;
}
} else if (event.getGestureSource() instanceof GUIOutput) {
Output source = ((GUIOutput) event.getGestureSource()).getGene();
@@ -77,28 +77,45 @@ public class GUIInput extends GUIGene {
public void handle(MouseDragEvent event) {
// the drag has exited this node, react appropriately
// this happens even if we are the source of the drag
- if (stateProperty.get() == GUIGeneState.NO_CHANGE_TARGET) {
- stateProperty.set(GUIGeneState.INDIRECT_HOVER);
- } else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ parent.setTarget(false);
+ if (event.isPrimaryButtonDown()) {
+ if (stateProperty.get() == GUIGeneState.NO_CHANGE_TARGET) {
+ stateProperty.set(GUIGeneState.INDIRECT_HOVER);
+ } else {
+ stateProperty.set(GUIGeneState.NEUTRAL);
+ ((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.INDIRECT_HOVER);
+ }
}
}
});
-
+
addEventFilter(MouseDragEvent.MOUSE_DRAG_RELEASED, new EventHandler<MouseDragEvent>() {
@Override
public void handle(MouseDragEvent event) {
+ GUIGene source = ((GUIGene) event.getGestureSource());
// set states to reflect the new situation
- ((GUIGene) event.getGestureSource()).setState(GUIGeneState.NEUTRAL);
- ((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.NEUTRAL);
- stateProperty.set(GUIGeneState.HOVER);
+ if (source.isLocked()) {
+ source.setState(GUIGeneState.HOVER);
+ source.setConnections(GUIGeneState.HOVER);
+ } else {
+ source.setState(GUIGeneState.NEUTRAL);
+ source.setConnections(GUIGeneState.NEUTRAL);
+ }
+
// the user released the drag gesture on this node, react appropriately
- if (event.getGestureSource() instanceof GUINode) {
- ((GUINode) event.getGestureSource()).setChangingConnection(input);
- } else if (event.getGestureSource() instanceof GUIOutput) {
- ((GUIOutput) event.getGestureSource()).getGene().setConnection(0, input);
- }
+ if (source.isLocked()) {
+ // remove locks from the old connection, add the to the new
+ // note that the old connection may still have locks after this
+ parent.getGuiGene(source.getChangingConnection()).removeLocks(source.getLocks());
+ source.setChangingConnection(input);
+ addLocks(source.getLocks());
+ } else {
+ source.setChangingConnection(input);
+ }
+
+ source.updateLines();
+ stateProperty.set(GUIGeneState.HOVER);
}
});
@@ -107,7 +124,7 @@ public class GUIInput extends GUIGene {
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.INDIRECT_HOVER);
+ stateProperty.set(GUIGeneState.HOVER);
}
}
});
@@ -116,7 +133,7 @@ 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.INDIRECT_HOVER) {
+ if (stateProperty.get() == GUIGeneState.HOVER) {
stateProperty.set(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
@@ -129,27 +146,40 @@ public class GUIInput extends GUIGene {
switch (newValue) {
case ACTIVE_HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
+ 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.HARD_HIGHLIGHT_COLOUR));
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
break;
case INDIRECT_HOVER:
mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
break;
case NEUTRAL:
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
+ 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.HARD_HIGHLIGHT_COLOUR));
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
break;
case TARGET:
+ parent.setTarget(true);
mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
break;
default:
@@ -179,11 +209,43 @@ public class GUIInput extends GUIGene {
@Override
public void resetState() {
stateProperty.set(GUIGeneState.NEUTRAL);
-
}
@Override
public void setLocked(boolean value) {
locked += value ? 1 : -1;
+ stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ }
+
+ @Override
+ public void setChangingConnection(Connection newConnection) {
+ // do nothing
+ }
+
+ @Override
+ public Connection getChangingConnection() {
+ return null;
+ }
+
+ @Override
+ public void addLocks(int value) {
+ locked += value;
+ stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ }
+
+ @Override
+ public void updateLines() {
+ // nothing
+ }
+
+ @Override
+ public void removeLocks(int value) {
+ locked -= value;
+ stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
+ }
+
+ @Override
+ public void setConnectionLine(GUIGene gene) {
+ // nothing
}
}
diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java
index c5ab43a..dd20006 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -13,7 +13,6 @@ import javafx.scene.shape.Line;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
-import jcgp.CGP.Resources;
import jcgp.GUI;
import jcgp.function.Function;
import jcgp.population.Connection;
@@ -22,7 +21,7 @@ import jcgp.population.Node;
import jcgp.population.Output;
public class GUINode extends GUIGene {
-
+
private Circle[] sockets;
private Circle output;
@@ -31,23 +30,23 @@ public class GUINode extends GUIGene {
private Label connectionNumber;
private Node node;
-
- private int connectionIndex;
-
- public GUINode(ChromosomePane parentRef, final Node node, Resources resources, Line[] connectionLines) {
+
+ private int connectionIndex = 0;
+
+ public GUINode(ChromosomePane parentRef, final Node node, Line[] connectionLines) {
// store references
this.parent = parentRef;
this.node = node;
this.lines = connectionLines;
-
+
// move the GUIGene to the right position
relocate(((node.getColumn() + 1) * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS,
(node.getRow() * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS);
// set the line ends correctly
updateLines();
-
+
connectionNumber = new Label();
connectionNumber.setStyle("-fx-background-color:rgb(255, 255, 255); -fx-border-color:rgba(0, 0, 0, 0.5); ");
connectionNumber.setVisible(false);
@@ -73,20 +72,20 @@ public class GUINode extends GUIGene {
text.setX(-NODE_RADIUS);
text.setVisible(true);
- sockets = new Circle[(int) resources.get("arity")];
+ sockets = new Circle[(int) GUI.resources.get("arity")];
double angle, xPos, yPos;
for (int l = 0; l < sockets.length; l++) {
- angle = ((((double) (l + 1)) / ((double) ((int) resources.get("arity") + 1))) * THETA) - (THETA / 2);
+ angle = ((((double) (l + 1)) / ((double) ((int) GUI.resources.get("arity") + 1))) * THETA) - (THETA / 2);
xPos = -Math.cos(angle) * NODE_RADIUS;
yPos = Math.sin(angle) * NODE_RADIUS;
sockets[l] = new Circle(xPos, yPos, GUIGene.SOCKET_RADIUS, Paint.valueOf("white"));
sockets[l].setId(String.valueOf(l));
sockets[l].setStroke(Paint.valueOf("black"));
-
+
final Circle s = sockets[l];
final int index = l;
-
+
/*
* Mouse event handlers on sockets
*
@@ -98,7 +97,7 @@ public class GUINode extends GUIGene {
startFullDrag();
}
});
-
+
s.addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
@@ -108,7 +107,7 @@ public class GUINode extends GUIGene {
connectionNumber.setVisible(true);
}
});
-
+
s.addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
@@ -116,24 +115,26 @@ public class GUINode extends GUIGene {
connectionNumber.setVisible(false);
}
});
-
+
s.addEventFilter(MouseDragEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// mouse was pressed on the socket
stateProperty.set(GUIGeneState.SOURCE);
connectionIndex = index;
- }
+ }
});
-
+
s.addEventFilter(MouseDragEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
- lines[connectionIndex].setEndX(event.getX() + ((Circle) event.getSource()).getParent().getLayoutX());
- lines[connectionIndex].setEndY(event.getY() + ((Circle) event.getSource()).getParent().getLayoutY());
+ if (!parent.isTarget()) {
+ lines[connectionIndex].setEndX(event.getX() + ((Circle) event.getSource()).getParent().getLayoutX());
+ lines[connectionIndex].setEndY(event.getY() + ((Circle) event.getSource()).getParent().getLayoutY());
+ }
}
});
-
+
s.addEventFilter(MouseDragEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
@@ -142,10 +143,10 @@ public class GUINode extends GUIGene {
updateLine(index);
stateProperty.set(GUIGeneState.HOVER);
}
- }
+ }
});
}
-
+
/*
* Mouse event handlers on whole gene
*/
@@ -155,13 +156,12 @@ public class GUINode extends GUIGene {
// the drag has entered this node, react appropriately
// this happens even if we are the source of the drag
if (isAllowed((GUIGene) event.getGestureSource(), (GUIGene) event.getSource())) {
+ ((GUIGene) event.getGestureSource()).setConnectionLine((GUIGene) event.getSource());
if (event.getGestureSource() instanceof GUINode) {
- Node source = ((GUINode) event.getGestureSource()).getGene();
- for (int i = 0; i < lines.length; i++) {
- if (node == source.getConnection(i)) {
- stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
- return;
- }
+ Connection source = ((GUINode) event.getGestureSource()).getChangingConnection();
+ if (node == source) {
+ stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
+ return;
}
} else if (event.getGestureSource() instanceof GUIOutput) {
Output source = ((GUIOutput) event.getGestureSource()).getGene();
@@ -181,6 +181,7 @@ public class GUINode extends GUIGene {
public void handle(MouseDragEvent event) {
// the drag has exited this node, react appropriately
// this happens even if we are the source of the drag
+ parent.setTarget(false);
if (event.isPrimaryButtonDown()) {
if (event.getGestureSource() == event.getSource()) {
stateProperty.set(GUIGeneState.SOURCE);
@@ -189,58 +190,74 @@ public class GUINode extends GUIGene {
stateProperty.set(GUIGeneState.INDIRECT_HOVER);
} else {
stateProperty.set(GUIGeneState.NEUTRAL);
+ ((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.INDIRECT_HOVER);
}
}
}
}
});
-
+
addEventFilter(MouseDragEvent.MOUSE_DRAG_RELEASED, new EventHandler<MouseDragEvent>() {
@Override
public void handle(MouseDragEvent event) {
+ GUIGene source = ((GUIGene) event.getGestureSource());
// set states to reflect the new situation
- ((GUIGene) event.getGestureSource()).setState(GUIGeneState.NEUTRAL);
- ((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.NEUTRAL);
- stateProperty.set(GUIGeneState.HOVER);
+ if (source.isLocked()) {
+ source.setState(GUIGeneState.HOVER);
+ source.setConnections(GUIGeneState.HOVER);
+ } else {
+ source.setState(GUIGeneState.NEUTRAL);
+ source.setConnections(GUIGeneState.NEUTRAL);
+ }
+
// the user released the drag gesture on this node, react appropriately
if (isAllowed((GUIGene) event.getGestureSource(), (GUIGene) event.getSource())) {
- if (event.getGestureSource() instanceof GUINode) {
- ((GUINode) event.getGestureSource()).setChangingConnection(node);
- } else if (event.getGestureSource() instanceof GUIOutput) {
- ((GUIOutput) event.getGestureSource()).getGene().setConnection(0, node);
+ if (source.isLocked()) {
+ // remove locks from the old connection, add the to the new
+ // note that the old connection may still have locks after this
+ parent.getGuiGene(source.getChangingConnection()).removeLocks(source.getLocks());
+ source.setChangingConnection(node);
+ addLocks(source.getLocks());
+ } else {
+ if (source instanceof GUIOutput) {
+ source.resetState();
+ }
+ source.setChangingConnection(node);
}
+
}
- if (event.getGestureSource() instanceof GUINode) {
- ((GUINode) event.getGestureSource()).updateLines();
- } else if (event.getGestureSource() instanceof GUIOutput) {
- ((GUIOutput) event.getGestureSource()).updateLine();
- }
-
+ source.updateLines();
+ stateProperty.set(GUIGeneState.HOVER);
}
});
-
-
+
+
addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
@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);
+ } else if (locked > 0) {
+ setConnections(GUIGeneState.LOCKED_HOVER);
}
}
});
-
+
addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
@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) {
- if (isLocked()) {
-
+ if (stateProperty.get() == GUIGeneState.HOVER && locked <= 0) {
+ stateProperty.set(GUIGeneState.NEUTRAL);
+ setConnections(GUIGeneState.NEUTRAL);
+ } else if (locked > 0) {
+ if (stateProperty.get() == GUIGeneState.SOURCE || stateProperty.get() == GUIGeneState.FORBIDDEN_TARGET) {
+ setConnections(GUIGeneState.INDIRECT_HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
- setConnections(GUIGeneState.NEUTRAL);
+ setConnections(GUIGeneState.HOVER);
}
+
}
}
});
@@ -248,54 +265,67 @@ public class GUINode extends GUIGene {
getChildren().addAll(mainCircle, text);
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:
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- showLines(true);
+ 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.HARD_HIGHLIGHT_COLOUR));
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
showLines(true);
- if (!isLocked()) {
+ if ((oldValue != GUIGeneState.LOCKED_HOVER || oldValue != GUIGeneState.SOURCE) && 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:
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
- showLines(false);
- if (oldValue == GUIGeneState.ACTIVE_HOVER) {
- setConnections(GUIGeneState.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;
-
}
}
});
-
+
for (int c = 0; c < lines.length; c++) {
final int i = c;
node.connections().get(c).addListener(new ChangeListener<Connection>() {
@@ -306,10 +336,15 @@ public class GUINode extends GUIGene {
}
});
}
-
+
}
-
-
+
+ @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
@@ -368,7 +403,7 @@ public class GUINode extends GUIGene {
updateLine(c);
}
}
-
+
/**
* Toggle visibility of all connection lines.
*
@@ -389,22 +424,11 @@ public class GUINode extends GUIGene {
@Override
public void setConnections(GUIGeneState newState) {
for (int i = 0; i < lines.length; i++) {
- if (node.getConnection(i) instanceof Node) {
- if (!parent.getGuiNode(((Node) node.getConnection(i)).getRow(), ((Node) node.getConnection(i)).getColumn()).isLocked()) {
- parent.getGuiNode(((Node) node.getConnection(i)).getRow(), ((Node) node.getConnection(i)).getColumn()).setState(newState);
- }
- } else if (node.getConnection(i) instanceof Input) {
- if (!parent.getGuiInput(((Input) node.getConnection(i)).getIndex()).isLocked()) {
- parent.getGuiInput(((Input) node.getConnection(i)).getIndex()).setState(newState);
- }
- }
+ parent.getGuiGene(node.getConnection(i)).setState(newState);
}
}
-
- /**
- * This method sets the connection currently being changed to the
- * specified value.
- */
+
+ @Override
public void setChangingConnection(Connection newConnection) {
node.setConnection(connectionIndex, newConnection);
}
@@ -412,22 +436,48 @@ public class GUINode extends GUIGene {
@Override
public void resetState() {
- stateProperty.set(GUIGeneState.NEUTRAL);
- setConnections(GUIGeneState.NEUTRAL);
- }
+ if (locked > 0) {
+ stateProperty.set(GUIGeneState.HOVER);
+ } else {
+ stateProperty.set(GUIGeneState.NEUTRAL);
+ setConnections(GUIGeneState.NEUTRAL);
+ }
+ }
@Override
public void setLocked(boolean value) {
locked += value ? 1 : -1;
stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
-
+
for (int i = 0; i < lines.length; i++) {
- if (node.getConnection(i) instanceof Node) {
- parent.getGuiNode(((Node) node.getConnection(i)).getRow(), ((Node) node.getConnection(i)).getColumn()).setLocked(value);
- } else if (node.getConnection(i) instanceof Input) {
- parent.getGuiInput(((Input) node.getConnection(i)).getIndex()).setLocked(value);
- }
+ parent.getGuiGene(node.getConnection(i)).setLocked(value);
+ }
+ }
+
+ @Override
+ public void addLocks(int value) {
+ locked += value;
+ stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+
+ for (int i = 0; i < lines.length; i++) {
+ parent.getGuiGene(node.getConnection(i)).addLocks(value);
+ }
+ }
+
+ @Override
+ public void removeLocks(int value) {
+ locked -= value;
+ stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
+
+ for (int i = 0; i < lines.length; i++) {
+ parent.getGuiGene(node.getConnection(i)).removeLocks(value);
}
}
+
+ @Override
+ public void setConnectionLine(GUIGene gene) {
+ lines[connectionIndex].setEndX(gene.getLayoutX() + NODE_RADIUS);
+ lines[connectionIndex].setEndY(gene.getLayoutY());
+ }
}
diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java
index 415d0fd..87d420e 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -14,7 +14,6 @@ import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import jcgp.GUI;
-import jcgp.CGP.Resources;
import jcgp.population.Connection;
import jcgp.population.Input;
import jcgp.population.Node;
@@ -30,17 +29,17 @@ public class GUIOutput extends GUIGene {
private Output output;
- public GUIOutput(ChromosomePane parentRef, final Output output, Resources resources, Line line) {
+ public GUIOutput(ChromosomePane parentRef, final Output output, Line line) {
this.parent = parentRef;
this.output = output;
this.sourceLine = line;
- relocate((((int) resources.get("columns") + 1) * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS,
+ relocate((((int) GUI.resources.get("columns") + 1) * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS,
(output.getIndex() * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS);
-
+
// set the line ends correctly
- updateLine();
+ updateLines();
mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white"));
mainCircle.setStroke(Paint.valueOf("black"));
@@ -56,7 +55,7 @@ public class GUIOutput extends GUIGene {
socket = new Circle(-NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
socket.setId(String.valueOf(0));
socket.setStroke(Paint.valueOf("black"));
-
+
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);
@@ -111,13 +110,13 @@ public class GUIOutput extends GUIGene {
public void handle(MouseEvent event) {
if (event.isDragDetect()) {
// mouse was released before dragging out of the socket
- updateLine();
+ updateLines();
stateProperty.set(GUIGeneState.HOVER);
}
}
});
-
+
/*
* Mouse event handlers on whole gene
*/
@@ -138,28 +137,33 @@ public class GUIOutput extends GUIGene {
if (event.getGestureSource() == event.getSource()) {
stateProperty.set(GUIGeneState.SOURCE);
} else {
- if (stateProperty.get() == GUIGeneState.NO_CHANGE_TARGET) {
- stateProperty.set(GUIGeneState.INDIRECT_HOVER);
- } else {
- stateProperty.set(GUIGeneState.NEUTRAL);
- }
+ stateProperty.set(isLocked() ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
}
}
}
});
-
+
addEventFilter(MouseDragEvent.MOUSE_DRAG_RELEASED, new EventHandler<MouseDragEvent>() {
@Override
public void handle(MouseDragEvent event) {
// making a connection to an output is illegal
// set states to reflect the new situation
- ((GUIGene) event.getGestureSource()).setState(GUIGeneState.NEUTRAL);
- ((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.NEUTRAL);
+ GUIGene source = ((GUIGene) event.getGestureSource());
+
+ if (source.isLocked()) {
+ source.setState(GUIGeneState.HOVER);
+ source.setConnections(GUIGeneState.HOVER);
+ } else {
+ source.setState(GUIGeneState.NEUTRAL);
+ source.setConnections(GUIGeneState.NEUTRAL);
+ }
+
+ source.updateLines();
stateProperty.set(GUIGeneState.HOVER);
}
});
-
-
+
+
addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
@@ -169,7 +173,7 @@ public class GUIOutput extends GUIGene {
}
}
});
-
+
addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
@@ -188,11 +192,11 @@ public class GUIOutput extends GUIGene {
stateProperty.set(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
-
+
}
}
});
-
+
getChildren().addAll(mainCircle, text, socket, connectionLabel);
@@ -208,9 +212,11 @@ public class GUIOutput extends GUIGene {
mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
break;
case HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR));
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
sourceLine.setVisible(true);
- setConnections(GUIGeneState.ACTIVE_HOVER);
+ if (!isLocked()) {
+ setConnections(GUIGeneState.ACTIVE_HOVER);
+ }
break;
case INDIRECT_HOVER:
mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
@@ -224,28 +230,31 @@ public class GUIOutput extends GUIGene {
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;
-
+
}
}
});
-
+
output.sourceProperty().addListener(new ChangeListener<Connection>() {
@Override
public void changed(ObservableValue<? extends Connection> observable,
Connection oldValue, Connection newValue) {
- updateLine();
+ updateLines();
}
});
}
- public void updateLine() {
+ @Override
+ public void updateLines() {
if (output.getSource() instanceof Node) {
int row = ((Node) output.getSource()).getRow(),
column = ((Node) output.getSource()).getColumn();
@@ -265,11 +274,7 @@ public class GUIOutput extends GUIGene {
@Override
public void setConnections(GUIGeneState newState) {
- if (output.getSource() instanceof Node) {
- parent.getGuiNode(((Node) output.getSource()).getRow(), ((Node) output.getSource()).getColumn()).setState(newState);
- } else if (output.getSource() instanceof Input) {
- parent.getGuiInput(((Input) output.getSource()).getIndex()).setState(newState);
- }
+ parent.getGuiGene(output.getSource()).setState(newState);
}
@Override
@@ -280,15 +285,37 @@ public class GUIOutput extends GUIGene {
@Override
public void setLocked(boolean value) {
- //stateProperty.set(GUIGeneState.HOVER);
locked += value ? 1 : -1;
setConnections(value ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
-
- if (output.getSource() instanceof Node) {
- parent.getGuiNode(((Node) output.getSource()).getRow(), ((Node) output.getSource()).getColumn()).setLocked(value);
- } else if (output.getSource() instanceof Input) {
- parent.getGuiInput(((Input) output.getSource()).getIndex()).setLocked(value);
- }
-
+
+ parent.getGuiGene(output.getSource()).setLocked(value);
+
+ }
+
+ @Override
+ public void setChangingConnection(Connection newConnection) {
+ output.setConnection(0, newConnection);
}
+
+ @Override
+ public Connection getChangingConnection() {
+ return output.getSource();
+ }
+
+ @Override
+ public void addLocks(int value) {
+ locked += value;
+ }
+
+ @Override
+ public void removeLocks(int value) {
+ locked -= value;
+ }
+
+ @Override
+ public void setConnectionLine(GUIGene gene) {
+ sourceLine.setEndX(gene.getLayoutX() + NODE_RADIUS);
+ sourceLine.setEndY(gene.getLayoutY());
+ }
+
}