package jcgp.gui.settings; import java.io.File; import java.util.ArrayList; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.ScrollPane; 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.Text; import javafx.stage.FileChooser; import javafx.stage.FileChooser.ExtensionFilter; import jcgp.JCGP; import jcgp.backend.function.FunctionSet; import jcgp.backend.modules.es.EvolutionaryStrategy; import jcgp.backend.modules.mutator.Mutator; import jcgp.backend.modules.problem.Problem; import jcgp.backend.modules.problem.TestCaseProblem; import jcgp.backend.parameters.Parameter; import jcgp.gui.GUI; import jcgp.gui.settings.parameters.GUIParameter; import jcgp.gui.settings.testcase.TestCaseTable; public class SettingsPane extends AnchorPane { private VBox mainContainer; private VBox baseParameterPane, eaPane, mutatorPane, problemPane; private VBox nodeFunctions; private Button runPause = new Button("Run"), step = new Button("Step"), reset = new Button("Reset"); private Button loadParameters = new Button("Load parameters"), loadChromosome = new Button("Load chromosome"), saveChromosome = new Button("Save chromosome"); private ArrayList> parameters = new ArrayList>(); private TestCaseTable testCaseTable; private GUI gui; private int currentArity; public SettingsPane(GUI gui) { super(); this.gui = gui; final JCGP jcgp = gui.getExperiment(); mainContainer = new VBox(8); mainContainer.setPadding(new Insets(5, GUI.RESIZE_MARGIN, 0, 2)); setMinWidth(GUI.SETTINGS_MIN_WIDTH); setPrefWidth(GUI.SETTINGS_MIN_WIDTH); initialiseBaseParameters(jcgp); initialiseEAParameters(jcgp); initialiseMutatorParameters(jcgp); initialiseProblemTypeParameters(jcgp, gui); createControls(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 jcgp) { baseParameterPane = new VBox(2); Text header = new Text("Base Parameters"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); baseParameterPane.getChildren().add(header); parameters.add(GUIParameter.create(jcgp.getResources().getRowsParameter(), this)); parameters.add(GUIParameter.create(jcgp.getResources().getColumnsParameter(), this)); parameters.add(GUIParameter.create(jcgp.getResources().getInputsParameter(), this)); parameters.add(GUIParameter.create(jcgp.getResources().getOutputsParameter(), this)); parameters.add(GUIParameter.create(jcgp.getResources().getLevelsBackParameter(), this)); GUIParameter gp = GUIParameter.create(jcgp.getResources().getPopulationSizeParameter(), this); gp.setPadding(new Insets(0, 0, 10, 0)); parameters.add(gp); parameters.add(GUIParameter.create(jcgp.getResources().getCurrentGenerationParameter(), this)); parameters.add(GUIParameter.create(jcgp.getResources().getGenerationsParameter(), this)); parameters.add(GUIParameter.create(jcgp.getResources().getCurrentRunParameter(), this)); gp = GUIParameter.create(jcgp.getResources().getRunsParameter(), this); gp.setPadding(new Insets(0, 0, 10, 0)); parameters.add(gp); parameters.add(GUIParameter.create(jcgp.getResources().getSeedParameter(), this)); parameters.add(GUIParameter.create(jcgp.getResources().getReportIntervalParameter(), this)); baseParameterPane.getChildren().addAll(parameters); mainContainer.getChildren().add(baseParameterPane); } private void initialiseEAParameters(final JCGP jcgp) { eaPane = new VBox(2); Text header = new Text("Evolutionary Strategy"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); final ComboBox eaCBox = new ComboBox(); eaCBox.getItems().addAll(jcgp.getEvolutionaryStrategies()); eaCBox.getSelectionModel().select(jcgp.getEvolutionaryStrategy()); eaCBox.prefWidthProperty().bind(mainContainer.widthProperty()); final VBox eaParameters = new VBox(2); refreshParameters(jcgp.getEvolutionaryStrategy().getLocalParameters(), eaParameters); eaCBox.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { jcgp.setEvolutionaryStrategy(eaCBox.getSelectionModel().getSelectedIndex()); refreshParameters(eaCBox.getSelectionModel().getSelectedItem().getLocalParameters(), eaParameters); } }); eaPane.getChildren().addAll(header, eaCBox, eaParameters); mainContainer.getChildren().add(eaPane); } private void initialiseMutatorParameters(final JCGP jcgp) { mutatorPane = new VBox(2); Text header = new Text("Mutator"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); final ComboBox mutatorCBox = new ComboBox(); mutatorCBox.getItems().addAll(jcgp.getMutators()); mutatorCBox.getSelectionModel().select(jcgp.getMutator()); mutatorCBox.prefWidthProperty().bind(mainContainer.widthProperty()); final VBox mutatorParameters = new VBox(2); refreshParameters(jcgp.getMutator().getLocalParameters(), mutatorParameters); mutatorCBox.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { jcgp.setMutator(mutatorCBox.getSelectionModel().getSelectedIndex()); refreshParameters(mutatorCBox.getSelectionModel().getSelectedItem().getLocalParameters(), mutatorParameters); } }); mutatorPane.getChildren().addAll(header, mutatorCBox, mutatorParameters); mainContainer.getChildren().add(mutatorPane); } private void initialiseProblemTypeParameters(final JCGP jcgp, final GUI gui) { updateArity(); problemPane= new VBox(2); Text header = new Text("Problem Type"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); final ComboBox problemCBox = new ComboBox(); problemCBox.getItems().addAll(jcgp.getProblems()); problemCBox.getSelectionModel().select(jcgp.getProblem()); problemCBox.prefWidthProperty().bind(mainContainer.widthProperty()); final VBox problemParameters = new VBox(2); problemParameters.setPadding(new Insets(0, 0, 4, 0)); refreshParameters(jcgp.getProblem().getLocalParameters(), problemParameters); final HBox testCaseControlContainer = new HBox(2); final Button showTestCaseButton = makeTestCaseButton(); final Button loadProblemDataButton = makeLoadTestCaseButton(); HBox.setHgrow(showTestCaseButton, Priority.ALWAYS); showTestCaseButton.setMaxWidth(Double.MAX_VALUE); HBox.setHgrow(loadProblemDataButton, Priority.ALWAYS); loadProblemDataButton.setMaxWidth(Double.MAX_VALUE); if (jcgp.getProblem() instanceof TestCaseProblem) { testCaseControlContainer.getChildren().addAll(showTestCaseButton, loadProblemDataButton); remakeTestCaseTable(); } else { testCaseControlContainer.getChildren().add(loadProblemDataButton); } nodeFunctions = new VBox(2); nodeFunctions.setPadding(new Insets(0, 0, 4, 0)); refreshFunctions(); problemCBox.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { jcgp.setProblem(problemCBox.getSelectionModel().getSelectedIndex()); updateArity(); refreshParameters(jcgp.getProblem().getLocalParameters(), problemParameters); if (testCaseTable != null) { testCaseTable.close(); } gui.setEvaluating(false); refreshFunctions(); testCaseControlContainer.getChildren().clear(); if (jcgp.getProblem() instanceof TestCaseProblem) { testCaseControlContainer.getChildren().addAll(showTestCaseButton, loadProblemDataButton); remakeTestCaseTable(); } else { testCaseControlContainer.getChildren().add(loadProblemDataButton); } gui.reset(); } }); problemPane.getChildren().addAll(header, problemCBox, problemParameters, nodeFunctions, testCaseControlContainer); mainContainer.getChildren().add(problemPane); } private Button makeLoadTestCaseButton() { Button b = new Button("Load data"); b.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { FileChooser fc = new FileChooser(); fc.setTitle("Open problem file..."); fc.getExtensionFilters().add(new ExtensionFilter("CGP " + gui.getExperiment().getProblem() + " files", "*" + ((TestCaseProblem) gui.getExperiment().getProblem()).getFileExtension())); fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*")); File chrFile = fc.showOpenDialog(gui.getStage()); if (chrFile != null) { gui.getExperiment().loadProblemData(chrFile); remakeTestCaseTable(); gui.reDraw(); } } }); return b; } private Button makeTestCaseButton() { Button b = new Button("Show data1"); b.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { testCaseTable.show(); } }); return b; } private void createControls(final GUI gui) { Text header = new Text("Experiment controls"); header.setFont(Font.font("Arial", 14)); header.setUnderline(true); final VBox controls = new VBox(2); controls.setFillWidth(true); final HBox flowButtons = new HBox(2); runPause.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { gui.runPause(); } }); step.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { gui.step(); } }); reset.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { gui.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); flowButtons.getChildren().addAll(runPause, step, reset); flowButtons.setPadding(new Insets(0, 0, 10, 0)); loadParameters.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { FileChooser fc = new FileChooser(); fc.setTitle("Open .par file..."); fc.getExtensionFilters().add(new ExtensionFilter("CGP parameter files", "*.par")); fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*")); File parFile = fc.showOpenDialog(gui.getStage()); if (parFile != null) { gui.getExperiment().loadParameters(parFile); gui.reDraw(); refreshFunctions(); } gui.flushConsole(); } }); loadChromosome.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { FileChooser fc = new FileChooser(); fc.setTitle("Load .chr file..."); fc.getExtensionFilters().add(new ExtensionFilter("CGP chromosome files", "*.chr")); fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*")); File chrFile = fc.showOpenDialog(gui.getStage()); if (chrFile != null) { gui.getExperiment().loadChromosome(chrFile, 0); gui.reDraw(); } gui.flushConsole(); } }); saveChromosome.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { FileChooser fc = new FileChooser(); fc.setTitle("Save .chr file..."); fc.getExtensionFilters().add(new ExtensionFilter("CGP chromosome files", "*.chr")); fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*")); File chrFile = fc.showSaveDialog(gui.getStage()); if (chrFile != null) { gui.getExperiment().saveChromosome(chrFile, 0); } gui.flushConsole(); } }); HBox.setHgrow(loadParameters, Priority.ALWAYS); loadParameters.setMaxWidth(Double.MAX_VALUE); HBox.setHgrow(loadChromosome, Priority.ALWAYS); loadChromosome.setMaxWidth(Double.MAX_VALUE); HBox.setHgrow(saveChromosome, Priority.ALWAYS); saveChromosome.setMaxWidth(Double.MAX_VALUE); controls.getChildren().addAll(header, flowButtons, loadParameters, loadChromosome, saveChromosome); mainContainer.getChildren().add(controls); } /** * @param cgp * @param vb */ private void refreshParameters(ArrayList> newParameters, VBox vb) { parameters.removeAll(vb.getChildren()); vb.getChildren().clear(); if (newParameters != null) { for (int i = 0; i < newParameters.size(); i++) { GUIParameter gp = GUIParameter.create(newParameters.get(i), this); parameters.add(gp); vb.getChildren().add(gp); } } revalidateParameters(); } /** * This method handles a problem type change by updating the list of allowed * node functions. */ private void refreshFunctions() { nodeFunctions.getChildren().clear(); CheckBox cb; final FunctionSet fs = gui.getExperiment().getResources().getFunctionSet(); for (int i = 0; i < fs.getTotalFunctionCount(); i++) { cb = new CheckBox(fs.getFunction(i).toString()); 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); } gui.updateFunctionSelector(); revalidateParameters(); } }); nodeFunctions.getChildren().add(cb); gui.updateFunctionSelector(); } } public boolean isExperimentRunning() { return gui.isWorking(); } /** * * @return true if the experiment needs to be reset, false if otherwise. */ public boolean isResetRequired() { for (GUIParameter parameter : parameters) { if (parameter.requiresReset()) { return true; } } if (arityChanged()) { return true; } return false; } /** * @return true if no parameters have their status set to ParameterStatus.INVALID. */ public boolean areParametersValid() { for (GUIParameter parameter : parameters) { if (!parameter.isValid()) { return false; } } return true; } /** * Calls validate() on every parameter. This is called whenever a parameter changes, * so that other parameters update their status in case they were dependent on the * changed parameter. */ public void revalidateParameters() { boolean disableControls = false; for (GUIParameter parameter : parameters) { parameter.validate(); if (parameter.requiresReset()) { disableControls = true; } } if (arityChanged()) { disableControls = true; } runPause.setDisable(disableControls); step.setDisable(disableControls); } /** * Calls applyValue() on every parameter. This is called when a reset occurs, so that * the new value will be used as a reference instead of the old reference value. */ public void applyParameters() { for (GUIParameter parameter : parameters) { parameter.applyValue(); } updateArity(); } /** * Updates all of the controls to their appropriate state based on the status of the * experiment, in order to prevent inappropriate operations if the experiment is * running or finished. * * @param running true if the experiment is running * @param finished true if the experiment is finished */ public void updateControls(boolean running, boolean finished) { baseParameterPane.setDisable(running); eaPane.setDisable(running); mutatorPane.setDisable(running); problemPane.setDisable(running); runPause.setText(running ? "Pause" : "Run"); runPause.setDisable(finished); step.setDisable(running || finished); reset.setDisable(running); loadParameters.setDisable(running); loadChromosome.setDisable(running); saveChromosome.setDisable(running); testCaseTable.getTable().setDisable(running); } private void remakeTestCaseTable() { boolean wasShowing = false; if (testCaseTable != null) { wasShowing = testCaseTable.isShowing(); testCaseTable.close(); } testCaseTable = new TestCaseTable((TestCaseProblem) gui.getExperiment().getProblem(), gui); if (wasShowing) { testCaseTable.show(); } } public TestCaseTable getTestCaseTable() { return testCaseTable; } private void updateArity() { currentArity = gui.getExperiment().getProblem().getFunctionSet().getMaxArity(); } private boolean arityChanged() { return currentArity != gui.getExperiment().getProblem().getFunctionSet().getMaxArity(); } }