package jcgp.gui.settings; import java.util.ArrayList; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Cursor; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.ScrollPane; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.scene.text.Font; import javafx.scene.text.FontSmoothingType; import javafx.scene.text.Text; import jcgp.JCGP; import jcgp.backend.function.FunctionSet; import jcgp.backend.modules.ea.EvolutionaryAlgorithm; import jcgp.backend.modules.fitness.FitnessFunction; import jcgp.backend.modules.mutator.Mutator; import jcgp.backend.parameters.IntegerParameter; import jcgp.backend.parameters.Parameter; import jcgp.gui.GUI; import jcgp.gui.settings.parameters.*; public class SettingsPane extends AnchorPane { private VBox mainContainer; private VBox bpPane, eaPane, mutatorPane, ffPane, nfPane; private Button runPause; private ArrayList parameters = new ArrayList(); private boolean dragging = false; public SettingsPane(JCGP cgp, GUI gui) { super(); setResizeListeners(); mainContainer = new VBox(8); mainContainer.setPadding(new Insets(5, GUI.RESIZE_MARGIN, 0, 2)); setMinWidth(GUI.SETTINGS_WIDTH); setPrefWidth(GUI.SETTINGS_WIDTH); initialiseBaseParameters(cgp, gui); initialiseEAParameters(cgp); initialiseMutatorParameters(cgp); initialiseFitnessFunctionParameters(cgp); initialiseNodeFunctionParameters(cgp); createControls(cgp, gui); ScrollPane scroll = new ScrollPane(); scroll.setFitToWidth(true); scroll.setContent(mainContainer); scroll.setStyle("-fx-background-color: #FFFFFF"); AnchorPane.setTopAnchor(scroll, 0.0); AnchorPane.setBottomAnchor(scroll, 0.0); AnchorPane.setRightAnchor(scroll, 0.0); AnchorPane.setLeftAnchor(scroll, GUI.RESIZE_MARGIN); getChildren().add(scroll); } private void initialiseBaseParameters(JCGP cgp, GUI gui) { bpPane = new VBox(2); Text header = new Text("Base Parameters"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); bpPane.getChildren().add(header); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("rows"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("columns"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("inputs"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("outputs"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("levelsBack"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("popSize"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("generations"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("runs"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentGen"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentRun"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("maxFitness"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("seed"), this)); parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("report"), this)); bpPane.getChildren().addAll(parameters); mainContainer.getChildren().add(bpPane); } private void initialiseEAParameters(final JCGP cgp) { eaPane = new VBox(2); Text header = new Text("Evolutionary Algorithm"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); final ComboBox eaCBox = new ComboBox(); eaCBox.getItems().addAll(cgp.getEvolutionaryAlgorithms()); eaCBox.getSelectionModel().select(cgp.getEvolutionaryAlgorithm()); eaCBox.prefWidthProperty().bind(mainContainer.widthProperty()); final VBox eaParameters = new VBox(); eaParameters.setSpacing(2); if (cgp.getEvolutionaryAlgorithm().getLocalParameters() != null) { refreshParameters(cgp.getEvolutionaryAlgorithm().getLocalParameters(), eaParameters); } eaCBox.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { cgp.setEvolutionaryAlgorithm(eaCBox.getSelectionModel().getSelectedIndex()); if (eaCBox.getSelectionModel().getSelectedItem().getLocalParameters() != null) { refreshParameters(eaCBox.getSelectionModel().getSelectedItem().getLocalParameters(), eaParameters); } } }); eaPane.getChildren().addAll(header, eaCBox, eaParameters); mainContainer.getChildren().add(eaPane); } private void initialiseMutatorParameters(final JCGP cgp) { mutatorPane = new VBox(2); Text header = new Text("Mutator"); header.setFontSmoothingType(FontSmoothingType.LCD); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); final ComboBox mutatorCBox = new ComboBox(); mutatorCBox.getItems().addAll(cgp.getMutators()); mutatorCBox.getSelectionModel().select(cgp.getMutator()); mutatorCBox.prefWidthProperty().bind(mainContainer.widthProperty()); final VBox mutatorParameters = new VBox(); mutatorParameters.setSpacing(2); if (cgp.getEvolutionaryAlgorithm().getLocalParameters() != null) { refreshParameters(cgp.getMutator().getLocalParameters(), mutatorParameters); } mutatorCBox.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { cgp.setEvolutionaryAlgorithm(mutatorCBox.getSelectionModel().getSelectedIndex()); if (mutatorCBox.getSelectionModel().getSelectedItem().getLocalParameters() != null) { refreshParameters(mutatorCBox.getSelectionModel().getSelectedItem().getLocalParameters(), mutatorParameters); } } }); mutatorPane.getChildren().addAll(header, mutatorCBox, mutatorParameters); mainContainer.getChildren().add(mutatorPane); } private void initialiseFitnessFunctionParameters(final JCGP cgp) { ffPane= new VBox(2); Text header = new Text("Fitness Function"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); final ComboBox ffCBox = new ComboBox(); ffCBox.getItems().addAll(cgp.getFitnessFunctions()); ffCBox.getSelectionModel().select(cgp.getFitnessFunction()); ffCBox.prefWidthProperty().bind(mainContainer.widthProperty()); final VBox ffParameters = new VBox(); ffParameters.setSpacing(2); if (cgp.getFitnessFunction().getLocalParameters() != null) { refreshParameters(cgp.getFitnessFunction().getLocalParameters(), ffParameters); } ffCBox.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { cgp.setEvolutionaryAlgorithm(ffCBox.getSelectionModel().getSelectedIndex()); if (ffCBox.getSelectionModel().getSelectedItem().getLocalParameters() != null) { refreshParameters(ffCBox.getSelectionModel().getSelectedItem().getLocalParameters(), ffParameters); } } }); ffPane.getChildren().addAll(header, ffCBox, ffParameters); mainContainer.getChildren().add(ffPane); } private void initialiseNodeFunctionParameters(JCGP cgp) { nfPane = new VBox(2); Text header = new Text("Node Functions"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); final ComboBox nfCBox = new ComboBox(); nfCBox.getItems().addAll(cgp.getResources().getFunctionSets()); nfCBox.getSelectionModel().select(cgp.getResources().getFunctionSet()); nfCBox.prefWidthProperty().bind(mainContainer.widthProperty()); final VBox nfParameters = new VBox(); nfParameters.setSpacing(2); refreshFunctions(cgp.getResources().getFunctionSet(), nfParameters); nfCBox.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { refreshFunctions(nfCBox.getSelectionModel().getSelectedItem(), nfParameters); } }); nfPane.getChildren().addAll(header, nfCBox, nfParameters); mainContainer.getChildren().add(nfPane); } private void createControls(final JCGP cgp, final GUI gui) { final VBox controls = new VBox(2); controls.setFillWidth(true); final HBox flowButtons = new HBox(2); runPause = new Button("Run"); runPause.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { gui.runPause(); } }); Button step = new Button("Step"); step.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { gui.step(); } }); Button reset = new Button("Reset"); reset.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { gui.reset(); } }); flowButtons.getChildren().addAll(runPause, step, reset); HBox.setHgrow(runPause, Priority.ALWAYS); runPause.setMaxWidth(Double.MAX_VALUE); HBox.setHgrow(step, Priority.ALWAYS); step.setMaxWidth(Double.MAX_VALUE); HBox.setHgrow(reset, Priority.ALWAYS); reset.setMaxWidth(Double.MAX_VALUE); controls.getChildren().add(flowButtons); mainContainer.getChildren().add(controls); } /** * @param cgp * @param vb */ private void refreshParameters(Parameter[] newParameters, VBox vb) { parameters.removeAll(vb.getChildren()); vb.getChildren().clear(); for (int i = 0; i < newParameters.length; i++) { GUIParameter gp = GUIParameter.create(newParameters[i], this); parameters.add(gp); vb.getChildren().add(gp); } revalidateParameters(); } private void refreshFunctions(final FunctionSet fs, VBox vb) { vb.getChildren().clear(); CheckBox cb; for (int i = 0; i < fs.getTotalFunctionCount(); i++) { cb = new CheckBox(fs.getFunction(i).getName()); cb.setId(String.valueOf(i)); cb.setSelected(fs.isEnabled(fs.getFunction(i))); final int index = i; cb.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { if (((CheckBox) event.getSource()).isSelected()) { fs.enableFunction(index); } else { fs.disableFunction(index); } } }); vb.getChildren().add(cb); } } private void setResizeListeners() { setOnMousePressed(new EventHandler() { @Override public void handle(MouseEvent event) { if(isInDraggableZone(event)) { dragging = true; } } }); setOnMouseDragged(new EventHandler() { @Override public void handle(MouseEvent event) { if(dragging) { double newWidth = getWidth() - event.getX(); if (newWidth >= getMinWidth()) { setPrefWidth(newWidth); } else { setPrefWidth(getMinWidth()); } } } }); setOnMouseMoved(new EventHandler() { @Override public void handle(MouseEvent event) { if(isInDraggableZone(event) || dragging) { setCursor(Cursor.H_RESIZE); } else { setCursor(Cursor.DEFAULT); } } }); setOnMouseReleased(new EventHandler() { @Override public void handle(MouseEvent event) { dragging = false; setCursor(Cursor.DEFAULT); } }); } private boolean isInDraggableZone(MouseEvent event) { return event.getX() < (GUI.RESIZE_MARGIN); } public void disableSettings(boolean value) { bpPane.setDisable(value); eaPane.setDisable(value); mutatorPane.setDisable(value); ffPane.setDisable(value); nfPane.setDisable(value); } /** * Writes the GUI parameter value back to the resources parameter, * if any changes were made. * * @return true if the experiment needs to be reset, false otherwise. */ public boolean isResetRequired() { for (GUIParameter parameter : parameters) { if (parameter.requiresReset()) { return true; } } return false; } public boolean areParametersValid() { for (GUIParameter parameter : parameters) { if (!parameter.isValid()) { return false; } } return true; } public void revalidateParameters() { for (GUIParameter parameter : parameters) { parameter.validate(); } } public void applyParameters() { for (GUIParameter parameter : parameters) { parameter.applyValue(); } } public Button getRunButton() { return runPause; } }