From 3f17c598a374e46200f3b2a73ef4f1f82f734a2e Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Mon, 24 Nov 2014 10:59:53 +0000 Subject: Visualisation features complete, seems to be quite stable. Behaves slightly differently to before, but the source is cleaner and more maintainable. Now moving on to connection manipulation. --- src/jcgp/gui/constants/Constants.java | 82 ++++++++++++++++++++------- src/jcgp/gui/handlers/InputHandlers.java | 8 ++- src/jcgp/gui/handlers/NodeHandlers.java | 10 ---- src/jcgp/gui/handlers/OutputHandlers.java | 34 +++++++++-- src/jcgp/gui/population/ChromosomePane.java | 2 +- src/jcgp/gui/population/FunctionSelector.java | 2 +- src/jcgp/gui/population/GUIConnection.java | 2 + src/jcgp/gui/population/GUIGene.java | 33 +++++++---- src/jcgp/gui/population/GUIInput.java | 5 ++ src/jcgp/gui/population/GUINode.java | 12 +++- src/jcgp/gui/population/GUIOutput.java | 2 +- 11 files changed, 141 insertions(+), 51 deletions(-) diff --git a/src/jcgp/gui/constants/Constants.java b/src/jcgp/gui/constants/Constants.java index d53b1ca..509d982 100644 --- a/src/jcgp/gui/constants/Constants.java +++ b/src/jcgp/gui/constants/Constants.java @@ -15,51 +15,93 @@ public final class Constants { */ private Constants(){} - /* Colours */ + /*--------------------------------------------------------------------------------------------------- + * Colour Strings + *-------------------------------------------------------------------------------------------------*/ + /** + * A {@code String} containing the colour used for representing neutrality. + */ + public static final String NEUTRAL_COLOUR = "#FFFFFF"; + /** + * A {@code String} containing the hexadecimal 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"; + /** + * A {@code String} containing the hexadecimal 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"; + /** + * A {@code String} containing the hexadecimal colour used for a soft highlight. + * When hovering over a node, its connections are soft-selected. + */ + public static final String SOFT_HIGHLIGHT_COLOUR = "#C7DFFF"; + /** + * A {@code String} containing the hexadecimal 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"; + /** + * A {@code String} containing the hexadecimal 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"; + /** + * A {@code String} containing the hexadecimal 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"; + /** + * A {@code String} containing the hexadecimal colour used for the gene sockets. + */ + public static final String SOCKET_COLOUR = "#FFFFFF"; + + /*--------------------------------------------------------------------------------------------------- + * Colour Paints + *-------------------------------------------------------------------------------------------------*/ /** * A {@code Paint} containing the colour used for representing neutrality. */ - public static final Paint NEUTRAL_COLOUR = Paint.valueOf("#FFFFFF"); + public static final Paint NEUTRAL_PAINT = Paint.valueOf(NEUTRAL_COLOUR); /** * 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. + * A "hard" select, for instance, happens when an output path is locked on the chromosome pane. */ - public static final Paint HARD_HIGHLIGHT_COLOUR = Paint.valueOf("#5496FF"); + public static final Paint HARD_HIGHLIGHT_PAINT = Paint.valueOf(HARD_HIGHLIGHT_COLOUR); /** * 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. + * One example of such a selection is the colour applied to a node when it is hovered over. */ - public static final Paint MEDIUM_HIGHLIGHT_COLOUR = Paint.valueOf("#75BAFF"); + public static final Paint MEDIUM_HIGHLIGHT_PAINT = Paint.valueOf(MEDIUM_HIGHLIGHT_COLOUR); /** * A {@code Paint} containing the colour used for a soft highlight. * When hovering over a node, its connections are soft-selected. */ - public static final Paint SOFT_HIGHLIGHT_COLOUR = Paint.valueOf("#C7DFFF"); + public static final Paint SOFT_HIGHLIGHT_PAINT = Paint.valueOf(SOFT_HIGHLIGHT_COLOUR); /** * 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 Paint GOOD_SELECTION_COLOUR = Paint.valueOf("#38C25B"); + public static final Paint GOOD_SELECTION_PAINT = Paint.valueOf(GOOD_SELECTION_COLOUR); /** * 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. + * Ideally a shade of yellow, used for instance when a manual connection is already the current connection. */ - public static final Paint NEUTRAL_SELECTION_COLOUR = Paint.valueOf("#FFEF73"); + public static final Paint NEUTRAL_SELECTION_PAINT = Paint.valueOf(NEUTRAL_SELECTION_COLOUR); /** * 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 Paint BAD_SELECTION_COLOUR = Paint.valueOf("#FF5C5C"); + public static final Paint BAD_SELECTION_PAINT = Paint.valueOf(BAD_SELECTION_COLOUR); /** * A {@code Paint} containing the colour used for the gene sockets. */ - public static final Paint SOCKET_COLOUR = Paint.valueOf("#FFFFFF"); - + public static final Paint SOCKET_PAINT = Paint.valueOf(SOCKET_COLOUR); - /* Sizes and distances */ + /*--------------------------------------------------------------------------------------------------- + * Sizes and distances + *-------------------------------------------------------------------------------------------------*/ /** * The width or height of the area that can be clicked on * to drag-resize a pane. @@ -100,10 +142,10 @@ public final class Constants { */ public static final double NODE_TEXT = NODE_RADIUS / 2.5; - - /* CSS Styles + /*--------------------------------------------------------------------------------------------------- + * CSS Styles * TODO extract to stylesheet? - */ + *-------------------------------------------------------------------------------------------------*/ /** * The basic style of text boxes used in parameters. */ diff --git a/src/jcgp/gui/handlers/InputHandlers.java b/src/jcgp/gui/handlers/InputHandlers.java index d0a8812..6be4e7e 100644 --- a/src/jcgp/gui/handlers/InputHandlers.java +++ b/src/jcgp/gui/handlers/InputHandlers.java @@ -5,12 +5,17 @@ import javafx.scene.input.MouseEvent; import jcgp.gui.population.GUIGene.GUIGeneState; import jcgp.gui.population.GUIInput; +/** + * + * + * @author Eduardo Pedroni + * + */ public final class InputHandlers { private static EventHandler mouseEnteredHandler = new EventHandler() { @Override public void handle(MouseEvent event) { - //((GUIGene) event.getSource()).mouseEnter(); ((GUIInput) event.getSource()).setState(GUIGeneState.HOVER); } }; @@ -18,7 +23,6 @@ public final class InputHandlers { private static EventHandler mouseExitedHandler = new EventHandler() { @Override public void handle(MouseEvent event) { - //((GUIGene) event.getSource()).mouseExit(); ((GUIInput) event.getSource()).setState(GUIGeneState.NEUTRAL); } }; diff --git a/src/jcgp/gui/handlers/NodeHandlers.java b/src/jcgp/gui/handlers/NodeHandlers.java index 9d1f6a8..8c9c465 100644 --- a/src/jcgp/gui/handlers/NodeHandlers.java +++ b/src/jcgp/gui/handlers/NodeHandlers.java @@ -15,14 +15,8 @@ public final class NodeHandlers { 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); } @@ -37,10 +31,6 @@ public final class NodeHandlers { 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); } diff --git a/src/jcgp/gui/handlers/OutputHandlers.java b/src/jcgp/gui/handlers/OutputHandlers.java index 31d6380..7399e50 100644 --- a/src/jcgp/gui/handlers/OutputHandlers.java +++ b/src/jcgp/gui/handlers/OutputHandlers.java @@ -15,8 +15,10 @@ public final class OutputHandlers { // 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); + //if (!source.isLocked()) { + source.setState(GUIGeneState.HOVER); + ((GUIConnection) ((Gene) source.getOutput().getSource()).getGUIObject()).setStateRecursively(GUIGeneState.ACTIVE_HOVER); + //} } }; @@ -26,14 +28,38 @@ public final class OutputHandlers { // 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); + //if (!source.isLocked()) { + source.setState(GUIGeneState.NEUTRAL); + ((GUIConnection) ((Gene) source.getOutput().getSource()).getGUIObject()).setStateRecursively(GUIGeneState.NEUTRAL); + //} + + } + }; + + private static EventHandler mouseClickHandler = new EventHandler() { + @Override + public void handle(MouseEvent event) { + // acquire the source, we can safely cast it to GUIOutput + GUIOutput source = (GUIOutput) event.getSource(); + + if (source.isLocked()) { + source.setLock(false); + ((GUIConnection) ((Gene) source.getOutput().getSource()).getGUIObject()).setLockRecursively(false); + } else { + source.setLock(true); + ((GUIConnection) ((Gene) source.getOutput().getSource()).getGUIObject()).setLockRecursively(true); + } + +// source.setState(GUIGeneState.HOVER); +// ((GUIConnection) ((Gene) source.getOutput().getSource()).getGUIObject()).setStateRecursively(GUIGeneState.ACTIVE_HOVER); + } }; public static void addHandlers(GUIOutput output) { output.addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEnteredHandler); output.addEventHandler(MouseEvent.MOUSE_EXITED, mouseExitedHandler); + output.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseClickHandler); } } diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java index 7826dcc..a87a054 100644 --- a/src/jcgp/gui/population/ChromosomePane.java +++ b/src/jcgp/gui/population/ChromosomePane.java @@ -20,8 +20,8 @@ import jcgp.gui.GUI; */ public class ChromosomePane extends ScrollPane { - private GUINode[][] guiNodes; private GUIInput[] guiInputs; + private GUINode[][] guiNodes; private GUIOutput[] guiOutputs; private Pane content; diff --git a/src/jcgp/gui/population/FunctionSelector.java b/src/jcgp/gui/population/FunctionSelector.java index d96617c..14614e5 100644 --- a/src/jcgp/gui/population/FunctionSelector.java +++ b/src/jcgp/gui/population/FunctionSelector.java @@ -46,7 +46,7 @@ public class FunctionSelector extends VBox { l.addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler() { @Override public void handle(MouseEvent event) { - ((Label) event.getSource()).setStyle("-fx-background-color: " + Constants.SOFT_HIGHLIGHT_COLOUR + "; -fx-border-color: #B0B0B0; -fx-border-width: 0 0 1 0; -fx-padding: 2"); + ((Label) event.getSource()).setStyle("-fx-background-color: " + Constants.SOFT_HIGHLIGHT_PAINT + "; -fx-border-color: #B0B0B0; -fx-border-width: 0 0 1 0; -fx-padding: 2"); } }); l.addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler() { diff --git a/src/jcgp/gui/population/GUIConnection.java b/src/jcgp/gui/population/GUIConnection.java index c17033a..3a0ad67 100644 --- a/src/jcgp/gui/population/GUIConnection.java +++ b/src/jcgp/gui/population/GUIConnection.java @@ -21,4 +21,6 @@ public interface GUIConnection { */ public void setStateRecursively(GUIGeneState state); + public void setLockRecursively(boolean value); + } diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java index d6f9638..02b87e7 100644 --- a/src/jcgp/gui/population/GUIGene.java +++ b/src/jcgp/gui/population/GUIGene.java @@ -54,6 +54,8 @@ public abstract class GUIGene extends Group { private Text text; private Circle mainCircle; + + private int lock = 0; /** * Initialises the {@code Text} and {@code Circle} objects so that all genes are standardised. @@ -66,7 +68,7 @@ public abstract class GUIGene extends Group { text.setWrappingWidth(Constants.NODE_RADIUS * 2); text.setX(-Constants.NODE_RADIUS); - mainCircle = new Circle(Constants.NODE_RADIUS, Constants.NEUTRAL_COLOUR); + mainCircle = new Circle(Constants.NODE_RADIUS, Constants.NEUTRAL_PAINT); mainCircle.setStroke(Paint.valueOf("black")); getChildren().addAll(mainCircle, text); @@ -105,24 +107,21 @@ public abstract class GUIGene extends Group { public final void setState(GUIGeneState newState) { switch (newState) { case NEUTRAL: - mainCircle.setFill(Constants.NEUTRAL_COLOUR); - setLinesVisible(false); + mainCircle.setFill(isLocked() ? Constants.HARD_HIGHLIGHT_PAINT : Constants.NEUTRAL_PAINT); + setLinesVisible(isLocked() ? true : false); break; case HOVER: - mainCircle.setFill(Constants.MEDIUM_HIGHLIGHT_COLOUR); + mainCircle.setFill(Constants.MEDIUM_HIGHLIGHT_PAINT); setLinesVisible(true); break; case EXTENDED_HOVER: - mainCircle.setFill(Constants.SOFT_HIGHLIGHT_COLOUR); - setLinesVisible(false); + mainCircle.setFill(Constants.SOFT_HIGHLIGHT_PAINT); + setLinesVisible(isLocked() ? true : false); break; case ACTIVE_HOVER: - mainCircle.setFill(Constants.SOFT_HIGHLIGHT_COLOUR); + mainCircle.setFill(Constants.SOFT_HIGHLIGHT_PAINT); setLinesVisible(true); break; - - default: - break; } currentState = newState; } @@ -134,4 +133,18 @@ public abstract class GUIGene extends Group { * @param value the visibility value. */ protected abstract void setLinesVisible(boolean value); + + public boolean isLocked() { + return lock > 0; + } + + public void setLock(boolean value) { + if (value) { + lock++; + } else if (lock > 0) { + lock--; + } else { + lock = 0; + } + } } diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java index 9b5f567..d899585 100644 --- a/src/jcgp/gui/population/GUIInput.java +++ b/src/jcgp/gui/population/GUIInput.java @@ -68,4 +68,9 @@ public class GUIInput extends GUIGene implements GUIConnection { */ @Override protected void setLinesVisible(boolean value) {} + + @Override + public void setLockRecursively(boolean value) { + setLock(value); + } } diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java index 230d167..ee98f22 100644 --- a/src/jcgp/gui/population/GUINode.java +++ b/src/jcgp/gui/population/GUINode.java @@ -37,13 +37,13 @@ public class GUINode extends GUIGene implements GUIMutable, GUIConnection { node.setGUIObject(this); // create the output socket - Circle output = new Circle(Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Constants.SOCKET_COLOUR); + Circle output = new Circle(Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Constants.SOCKET_PAINT); output.setStroke(Paint.valueOf("black")); // create input sockets sockets = new Circle[GUI.resources.arity()]; for (int l = 0; l < sockets.length; l++) { - sockets[l] = new Circle(Constants.SOCKET_RADIUS, Constants.SOCKET_COLOUR); + sockets[l] = new Circle(Constants.SOCKET_RADIUS, Constants.SOCKET_PAINT); sockets[l].setStroke(Paint.valueOf("black")); sockets[l].setId(String.valueOf(l)); // relocate them @@ -128,4 +128,12 @@ public class GUINode extends GUIGene implements GUIMutable, GUIConnection { lines[i].setVisible(value); } } + + @Override + public void setLockRecursively(boolean value) { + setLock(value); + for (int i = 0; i < GUI.resources.arity(); i++) { + ((GUIConnection) ((Gene) node.getConnection(i)).getGUIObject()).setLockRecursively(value); + } + } } diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java index b281833..9ffef1d 100644 --- a/src/jcgp/gui/population/GUIOutput.java +++ b/src/jcgp/gui/population/GUIOutput.java @@ -35,7 +35,7 @@ public class GUIOutput extends GUIGene implements GUIMutable { output.setGUIObject(this); // create input socket - Circle socket = new Circle(-Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Constants.SOCKET_COLOUR); + Circle socket = new Circle(-Constants.NODE_RADIUS, 0, Constants.SOCKET_RADIUS, Constants.SOCKET_PAINT); socket.setStroke(Paint.valueOf("black")); socket.setId(String.valueOf(0)); Position.connect(line, (GUIGene) ((Gene) output.getSource()).getGUIObject()); -- cgit v1.2.3