diff options
| author | Eduardo Pedroni <e.pedroni91@gmail.com> | 2015-03-09 17:03:48 -0300 | 
|---|---|---|
| committer | Eduardo Pedroni <e.pedroni91@gmail.com> | 2015-03-09 17:03:48 -0300 | 
| commit | d69fa8746728367646494fd8c2c18944f306c6a2 (patch) | |
| tree | f063f9efc6c93a5520991f509f3a481543b73a91 /src/jcgp/gui/population | |
| parent | 9062115b7d15cb05552632dc5486a5cd15a45289 (diff) | |
Added existing source code
Diffstat (limited to 'src/jcgp/gui/population')
| -rw-r--r-- | src/jcgp/gui/population/ChromosomePane.java | 140 | ||||
| -rw-r--r-- | src/jcgp/gui/population/FunctionSelector.java | 80 | ||||
| -rw-r--r-- | src/jcgp/gui/population/GUIConnection.java | 32 | ||||
| -rw-r--r-- | src/jcgp/gui/population/GUIGene.java | 187 | ||||
| -rw-r--r-- | src/jcgp/gui/population/GUIInput.java | 70 | ||||
| -rw-r--r-- | src/jcgp/gui/population/GUIMutable.java | 20 | ||||
| -rw-r--r-- | src/jcgp/gui/population/GUINode.java | 134 | ||||
| -rw-r--r-- | src/jcgp/gui/population/GUIOutput.java | 79 | ||||
| -rw-r--r-- | src/jcgp/gui/population/PopulationPane.java | 75 | 
9 files changed, 817 insertions, 0 deletions
| diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java new file mode 100644 index 0000000..a87a054 --- /dev/null +++ b/src/jcgp/gui/population/ChromosomePane.java @@ -0,0 +1,140 @@ +package jcgp.gui.population; + +import java.util.ArrayList; + +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.Pane; +import javafx.scene.shape.Line; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Node; +import jcgp.gui.GUI; + +/** + * 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 laid over the nodes, inputs and outputs. + *  + *  + * @author Eduardo Pedroni + * + */ +public class ChromosomePane extends ScrollPane { + +	private GUIInput[] guiInputs; +	private GUINode[][] guiNodes; +	private GUIOutput[] guiOutputs; + +	private Pane content; + +	private boolean target = false; + +	public ChromosomePane(Chromosome chromosome) { +		super(); + +		ArrayList<Line> connectionLines = new ArrayList<Line>(); + +		int rows = GUI.resources.rows(); +		int columns = GUI.resources.columns(); + +		content = new Pane(); +		content.setId("content pane for genes"); + +		/*  +		 * inputs +		 */ +		guiInputs = new GUIInput[GUI.resources.inputs()]; +		for (int i = 0; i < guiInputs.length; i++) { +			guiInputs[i] = new GUIInput(chromosome.getInput(i)); +		} +		// add inputs to content pane +		content.getChildren().addAll(guiInputs); + +		/* +		 * nodes +		 */ +		guiNodes = new GUINode[rows][columns]; +		for (int c = 0; c < columns; c++) { +			for (int r = 0; r < rows; r++) { +				// make the connection lines +				Line lines[] = new Line[GUI.resources.arity()]; +				for (int l = 0; l < lines.length; l++) { +					lines[l] = new Line(); +					lines[l].setMouseTransparent(true); +					lines[l].setVisible(false); +					connectionLines.add(lines[l]); +				} +				// 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]); +			} +		} + +		/*  +		 * outputs +		 */ +		guiOutputs = new GUIOutput[GUI.resources.outputs()]; +		for (int i = 0; i < guiOutputs.length; i++) { +			// make the connection line +			Line line = new Line(); +			line.setVisible(false); +			line.setMouseTransparent(true); +			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); +		setContent(content); +	} + +	protected boolean isTarget() { +		return target; +	} + +	protected void setTarget(boolean newValue) { +		target = newValue; +	} + +	public void updateGenes(Chromosome chr) { +		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)); +			} +		} +		for (int i = 0; i < guiOutputs.length; i++) { +			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 +			if (target instanceof GUIInput) { +				return true; +			} else if (target instanceof GUINode) { +				// target and source are nodes, let's look at levels back +				Node t = ((GUINode) target).getNode(), s = ((GUINode) source).getNode(); +				if (s.getColumn() - t.getColumn() > 0 && s.getColumn() - t.getColumn() <= GUI.resources.levelsBack()) { +					return true; +				} +			} +			return false; +		} else if (source instanceof GUIOutput) { +			// if the source is an output, any node or input is valid +			if (target instanceof GUINode || target instanceof GUIInput) { +				return true; +			} else { +				// this should never happen... +				return false; +			} +		} +		// if the source was neither node nor output, something bad is happening +		throw new ClassCastException("Source was neither GUINode nor GUIOutput."); +	} +} diff --git a/src/jcgp/gui/population/FunctionSelector.java b/src/jcgp/gui/population/FunctionSelector.java new file mode 100644 index 0000000..14614e5 --- /dev/null +++ b/src/jcgp/gui/population/FunctionSelector.java @@ -0,0 +1,80 @@ +package jcgp.gui.population; + +import javafx.event.EventHandler; +import javafx.scene.control.Label; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.VBox; +import jcgp.backend.function.FunctionSet; +import jcgp.gui.constants.Constants; + +/** + * A menu class, exposes all of the allowed functions + * when called by a node, so that the node function can be changed. + *  + *  + * @author Eduardo Pedroni + * + */ +public class FunctionSelector extends VBox { +	 +	private GUINode target; +		 +	public FunctionSelector(FunctionSet functionSet) { +		setFillWidth(true); +		setVisible(false); +		setStyle("-fx-border-color: #A0A0A0; -fx-border-width: 1 1 0 1"); +		 +		remakeFunctions(functionSet); +		 +		addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() { +			@Override +			public void handle(MouseEvent event) { +				dismiss(); +			} +		}); +	} +	 +	public void remakeFunctions(final FunctionSet fs) { +		getChildren().clear(); +		 +		for (int i = 0; i < fs.getAllowedFunctionCount(); i++) { +			final int index = i; +			Label l = new Label(fs.getAllowedFunction(i).toString()); +			l.setMaxWidth(Double.MAX_VALUE); +			l.setStyle("-fx-background-color: #FFFFFF; -fx-border-color: #A0A0A0; -fx-border-width: 0 0 1 0; -fx-padding: 2"); +			 +			l.addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() { +				@Override +				public void handle(MouseEvent event) { +					((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<MouseEvent>() { +				@Override +				public void handle(MouseEvent event) { +					((Label) event.getSource()).setStyle("-fx-background-color: #FFFFFF; -fx-border-color: #A0A0A0; -fx-border-width: 0 0 1 0; -fx-padding: 2"); +				} +			}); +			l.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { +				@Override +				public void handle(MouseEvent event) { +					//target.setFunction(fs.getAllowedFunction(index)); +					dismiss(); +				} +			}); +			 +			getChildren().add(l); +		} +	} +	 +	public void relocateAndShow(MouseEvent event, GUINode node) { +		relocate(event.getSceneX() - 5, event.getSceneY() - 5); +		target = node; +		setVisible(true); +	} +	 +	private void dismiss() { +		setVisible(false); +	} +	 +} diff --git a/src/jcgp/gui/population/GUIConnection.java b/src/jcgp/gui/population/GUIConnection.java new file mode 100644 index 0000000..dc7fcc8 --- /dev/null +++ b/src/jcgp/gui/population/GUIConnection.java @@ -0,0 +1,32 @@ +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); +	 +	/** +	 * Add or remove a lock, but also recursively propagate that change +	 * all the way back to the inputs. +	 *  +	 * @param value true to lock, false to unlock. +	 */ +	public void setLockRecursively(boolean value); +	 +} diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java new file mode 100644 index 0000000..5e6107f --- /dev/null +++ b/src/jcgp/gui/population/GUIGene.java @@ -0,0 +1,187 @@ +package jcgp.gui.population; + +import javafx.geometry.VPos; +import javafx.scene.Group; +import javafx.scene.paint.Paint; +import javafx.scene.shape.Circle; +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.scene.text.TextAlignment; +import jcgp.gui.constants.Constants; + +/** + * Defines the general behaviour of the visual representation of each chromosome gene. + * <br><br> + * In practice, this is subclass of {@code javafx.scene.Group} containing a {@code Circle} + * object and a {@code Text} object. Subclasses may add further elements to the group, for + * instance to display connection input and output sockets. + * <br><br> + * Genes also contain a locked property. When locked, some gene states behave slightly + * differently. This is used so genes remain highlighted even in the neutral state. The + * gene lock is in fact recursive; a gene can be locked multiple times and only unlocking + * it as many times will actually revert it back to its unlocked state. This allows multiple + * pathways to lock the same gene independently without affecting each other; the gene remains + * locked until no pathways are locking it. + *  + * @author Eduardo Pedroni + * + */ +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, +		 +		GOOD_TARGET, +		 +		NEUTRAL_TARGET, +		 +		BAD_TARGET +	} + +	private GUIGeneState currentState = GUIGeneState.NEUTRAL; + +	private Text text; +	private Circle mainCircle; +	 +	/** +	 * Recursive lock; lock == 0 means unlocked, lock > 0 means locked. +	 * Accessing using {@code setLock(...)}. +	 */ +	private int lock = 0; + +	/** +	 * 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); + +		mainCircle = new Circle(Constants.NODE_RADIUS, Constants.NEUTRAL_PAINT); +		mainCircle.setStroke(Paint.valueOf("black")); +		 +		getChildren().addAll(mainCircle, text); +	} + +	/** +	 * Sets the gene's text field. +	 *  +	 * @param newText the text string to be displayed. +	 */ +	public void setText(String newText) { +		text.setText(newText); +	} + +	/** +	 * @return the gene's current state. +	 */ +	public GUIGeneState getState() { +		return currentState; +	} + +	/** +	 * 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(isLocked() ? Constants.HARD_HIGHLIGHT_PAINT : Constants.NEUTRAL_PAINT); +			setLinesVisible(isLocked()); +			break; +		case HOVER: +			mainCircle.setFill(Constants.MEDIUM_HIGHLIGHT_PAINT); +			setLinesVisible(true); +			break; +		case EXTENDED_HOVER: +			mainCircle.setFill(Constants.SOFT_HIGHLIGHT_PAINT); +			setLinesVisible(isLocked()); +			break; +		case ACTIVE_HOVER: +			mainCircle.setFill(Constants.SOFT_HIGHLIGHT_PAINT); +			setLinesVisible(true); +			break; +		case GOOD_TARGET: +			mainCircle.setFill(Constants.GOOD_SELECTION_PAINT); +			break; +		case NEUTRAL_TARGET: +			mainCircle.setFill(Constants.NEUTRAL_SELECTION_PAINT); +			break; +		case BAD_TARGET: +			mainCircle.setFill(Constants.BAD_SELECTION_PAINT); +			break; +		} +		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); +	 +	/** +	 * @return true if the gene is locked, false otherwise. +	 */ +	public boolean isLocked() { +		return lock > 0; +	} +	 +	/** +	 * Locks or unlocks the gene once. Locked genes +	 * behave slightly differently in some states.  +	 * <br> +	 * Unlocking an already unlocked gene does nothing. +	 *  +	 * @param value true to lock, false to unlock; +	 */ +	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 new file mode 100644 index 0000000..3db7416 --- /dev/null +++ b/src/jcgp/gui/population/GUIInput.java @@ -0,0 +1,70 @@ +package jcgp.gui.population; + +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; +	 +	/** +	 * 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.setStroke(Paint.valueOf("black")); +		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; +	} + +	@Override +	public void setStateRecursively(GUIGeneState state) { +		setState(state); +	} + +	@Override +	protected void setLinesVisible(boolean value) {} + +	@Override +	public void setLockRecursively(boolean value) { +		setLock(value); +	} +} diff --git a/src/jcgp/gui/population/GUIMutable.java b/src/jcgp/gui/population/GUIMutable.java new file mode 100644 index 0000000..fa996e2 --- /dev/null +++ b/src/jcgp/gui/population/GUIMutable.java @@ -0,0 +1,20 @@ +package jcgp.gui.population; + +import javafx.scene.shape.Line; + +/** + * 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 { +	 +	public Line[] getLines(); +	 +	public GUIConnection[] getConnections(); +	 +} diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java new file mode 100644 index 0000000..1a32426 --- /dev/null +++ b/src/jcgp/gui/population/GUINode.java @@ -0,0 +1,134 @@ +package jcgp.gui.population; + +import javafx.scene.paint.Paint; +import javafx.scene.shape.Circle; +import javafx.scene.shape.Line; +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, associate with node +		this.node = node; +		this.lines = lines; +		node.setGUIObject(this); + +		// create the output socket +		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_PAINT); +			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().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; +	} + +	/** +	 * Associates this instance with a new node. +	 *  +	 * @param node the new node. +	 */ +	void setNode(Node node) { +		this.node = node; +	} +	 +	@Override +	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; +	} + +	@Override +	public void setStateRecursively(GUIGeneState state) { +		setState(state); +		for (int i = 0; i < GUI.resources.arity(); i++) { +			((GUIConnection) ((Gene) node.getConnection(i)).getGUIObject()).setStateRecursively(state); +		} +	} + +	@Override +	protected void setLinesVisible(boolean value) { +		for (int i = 0; i < lines.length; i++) { +			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); +		} +	} + +	@Override +	public GUIConnection[] getConnections() { +		GUIConnection[] connections = new GUIConnection[GUI.resources.arity()]; +		for (int c = 0; c < connections.length; c++) { +			connections[c] = (GUIConnection) ((Gene) node.getConnection(c)).getGUIObject(); +		} +		return connections; +	} +} diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java new file mode 100644 index 0000000..f023d00 --- /dev/null +++ b/src/jcgp/gui/population/GUIOutput.java @@ -0,0 +1,79 @@ +package jcgp.gui.population; + +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; +		output.setGUIObject(this); + +		// create input socket +		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()); +		getChildren().add(socket); + +		// relocate output, add handlers +		Position.place(this); +		OutputHandlers.addHandlers(this); +	} + +	/** +	 * @return the {@code Output} instance associated with this object. +	 */ +	public Output getOutput() { +		return output; +	} +	 +	/** +	 * Associates this instance with a new output. +	 *  +	 * @param output the new output. +	 */ +	void setOutput(Output output) { +		this.output = output; +	} + +	@Override +	public Line[] getLines() { +		return new Line[] {line}; +	} + +	@Override +	protected void setLinesVisible(boolean value) { +		line.setVisible(value); +	} + +	@Override +	public GUIConnection[] getConnections() { +		return new GUIConnection[] {(GUIConnection) output.getGUIObject()}; +	} +} diff --git a/src/jcgp/gui/population/PopulationPane.java b/src/jcgp/gui/population/PopulationPane.java new file mode 100644 index 0000000..51b5ba4 --- /dev/null +++ b/src/jcgp/gui/population/PopulationPane.java @@ -0,0 +1,75 @@ +package jcgp.gui.population; + +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import jcgp.JCGP; +import jcgp.backend.modules.problem.TestCaseProblem; +import jcgp.backend.modules.problem.TestCaseProblem.TestCase; +import jcgp.gui.GUI; + +public class PopulationPane extends TabPane { +	 +	private GUI gui; +	private TestCase<Object> currentTestCase; +	private boolean evaluating = false; +	 +	public PopulationPane(GUI gui) { +		super(); +		this.gui = gui; +		setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); +		remakeTabs(); +	} +	 +	public void remakeTabs() { +		getTabs().clear(); +		JCGP jcgp = gui.getExperiment(); +		 +		Tab tab; +		ChromosomePane cp; +		for (int i = 0; i < jcgp.getResources().populationSize(); i++) { +			cp = new ChromosomePane(jcgp.getPopulation().get(i)); +			tab = new Tab("Chr " + i); +			tab.setContent(cp); +			getTabs().add(tab); +		} +	} +		 +	public void updateGenes() { +		if (evaluating) { +			evaluateTestCase(currentTestCase); +		} +		for (int i = 0; i < getTabs().size(); i++) { +			((ChromosomePane) getTabs().get(i).getContent()).updateGenes(gui.getExperiment().getPopulation().get(i)); +		} +	} +	 +	public void evaluateTestCase(TestCase<Object> testCase) { +		if (gui.getExperiment().getProblem() instanceof TestCaseProblem && testCase != null) { +			currentTestCase = testCase; +			if (testCase.getInputs().length == gui.getExperiment().getResources().inputs()) { +				evaluating = true; +				for (int i = 0; i < getTabs().size(); i++) { +					//((ChromosomePane) getTabs().get(i).getContent()).setInputs(testCase.getInputs()); +				} +			} else { +				throw new IllegalArgumentException("Test case has " + testCase.getInputs().length +						+ " inputs and chromosome has " + gui.getExperiment().getResources().inputs()); +			} +		} +	} +	 +	public void hideValues() { +		evaluating = false; +		for (int i = 0; i < getTabs().size(); i++) { +			//((ChromosomePane) getTabs().get(i).getContent()).updateValues(); +		} +	} + +	public boolean isEvaluating() { +		return evaluating; +	} + +	public void setEvaluating(boolean value) { +		evaluating = value; +	} +} | 
