diff options
author | Eduardo Pedroni <e.pedroni91@gmail.com> | 2015-03-09 16:40:17 -0300 |
---|---|---|
committer | Eduardo Pedroni <e.pedroni91@gmail.com> | 2015-03-09 16:40:17 -0300 |
commit | ff5248437491f1829c0168b271e85cb358516577 (patch) | |
tree | 1c41e92769d8186b2d6e05efe8bdb6d205b01156 /src/jcgp/gui/settings | |
parent | db2bc6e935ff1632d78ea8a03606b396944ef21e (diff) |
Diffstat (limited to 'src/jcgp/gui/settings')
-rw-r--r-- | src/jcgp/gui/settings/SettingsPane.java | 595 | ||||
-rw-r--r-- | src/jcgp/gui/settings/parameters/GUIBooleanParameter.java | 82 | ||||
-rw-r--r-- | src/jcgp/gui/settings/parameters/GUIDoubleParameter.java | 110 | ||||
-rw-r--r-- | src/jcgp/gui/settings/parameters/GUIIntegerParameter.java | 107 | ||||
-rw-r--r-- | src/jcgp/gui/settings/parameters/GUIParameter.java | 235 | ||||
-rw-r--r-- | src/jcgp/gui/settings/testcase/TestCaseTable.java | 124 |
6 files changed, 0 insertions, 1253 deletions
diff --git a/src/jcgp/gui/settings/SettingsPane.java b/src/jcgp/gui/settings/SettingsPane.java deleted file mode 100644 index bad42cd..0000000 --- a/src/jcgp/gui/settings/SettingsPane.java +++ /dev/null @@ -1,595 +0,0 @@ -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.constants.Constants; -import jcgp.gui.settings.parameters.GUIParameter; -import jcgp.gui.settings.testcase.TestCaseTable; - -/** - * This is a fairly hefty class which encapsulates the entire right-hand - * control pane. It contains base parameters, module selectors and their - * associated parameters, flow controls and file loading/saving buttons. - * <br><br> - * A single instance of this class is used in {@code GUI}. - * - * - * @author Eduardo Pedroni - * - */ -public class SettingsPane extends AnchorPane { - - /* - * The primary containers, these make up each section of the settings pane. - */ - private VBox mainContainer; - private VBox baseParameterPane, eaPane, mutatorPane, problemPane; - private VBox nodeFunctions; - - // all buttons - 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"); - - // this is a list of parameters used for parameter validity checks - private ArrayList<GUIParameter<?>> parameters = new ArrayList<GUIParameter<?>>(); - - // the test case table stage - private TestCaseTable testCaseTable; - - // a reference to the parent GUI - private GUI gui; - - private int currentArity; - - /** - * Create a new instance of {@code SettingsPane} associated - * with the specified {@code GUI} object. - * - * @param gui a reference to this object's parent. - */ - public SettingsPane(GUI gui) { - super(); - this.gui = gui; - - // acquire a reference to jcgp, for convenience - final JCGP jcgp = gui.getExperiment(); - - // make the overarching container - mainContainer = new VBox(8); - mainContainer.setPadding(new Insets(5, Constants.RESIZE_MARGIN, 0, 2)); - - setMinWidth(Constants.SETTINGS_MIN_WIDTH); - setPrefWidth(Constants.SETTINGS_MIN_WIDTH); - - // initialise all sub-divisions - initialiseBaseParameters(jcgp); - - initialiseEAParameters(jcgp); - - initialiseMutatorParameters(jcgp); - - initialiseProblemTypeParameters(jcgp, gui); - - createControls(gui); - - // prepare the scroll pane - ScrollPane scroll = new ScrollPane(); - scroll.setFitToWidth(true); - scroll.setContent(mainContainer); - scroll.setStyle("-fx-background-color: #FFFFFF"); - - // anchor the scroll pane to itself, bearing in mind the resize margin - AnchorPane.setTopAnchor(scroll, 0.0); - AnchorPane.setBottomAnchor(scroll, 0.0); - AnchorPane.setRightAnchor(scroll, 0.0); - AnchorPane.setLeftAnchor(scroll, Constants.RESIZE_MARGIN); - - // add the scroll pane, all done! - getChildren().add(scroll); - } - - /** - * Creates the base parameters pane - * - * @param jcgp - */ - 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<EvolutionaryStrategy> esCBox = new ComboBox<EvolutionaryStrategy>(); - esCBox.getItems().addAll(jcgp.getEvolutionaryStrategies()); - esCBox.getSelectionModel().select(jcgp.getEvolutionaryStrategy()); - esCBox.prefWidthProperty().bind(mainContainer.widthProperty()); - - final VBox eaParameters = new VBox(2); - - refreshParameters(jcgp.getEvolutionaryStrategy().getLocalParameters(), eaParameters); - - esCBox.setOnAction(new EventHandler<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - jcgp.setEvolutionaryStrategy(esCBox.getSelectionModel().getSelectedIndex()); - refreshParameters(esCBox.getSelectionModel().getSelectedItem().getLocalParameters(), eaParameters); - gui.flushConsole(); - } - }); - - eaPane.getChildren().addAll(header, esCBox, 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<Mutator> mutatorCBox = new ComboBox<Mutator>(); - 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<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - jcgp.setMutator(mutatorCBox.getSelectionModel().getSelectedIndex()); - refreshParameters(mutatorCBox.getSelectionModel().getSelectedItem().getLocalParameters(), mutatorParameters); - gui.flushConsole(); - } - }); - - 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<Problem> problemCBox = new ComboBox<Problem>(); - 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<ActionEvent>() { - @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<ActionEvent>() { - @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 data"); - b.setOnAction(new EventHandler<ActionEvent>() { - @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<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - gui.runPause(); - } - }); - - step.setOnAction(new EventHandler<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - gui.step(); - } - }); - - reset.setOnAction(new EventHandler<ActionEvent>() { - @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<ActionEvent>() { - @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<ActionEvent>() { - @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, gui.getChromosomeIndex()); - gui.reDraw(); - } - gui.flushConsole(); - } - }); - saveChromosome.setOnAction(new EventHandler<ActionEvent>() { - @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, gui.getChromosomeIndex()); - } - 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); - } - - /** - * Builds {@code GUIParameter}s and adds them to the provided {@code VBox}. - * The parameters built are taken from the specified list. - * - * @param newParameters the list of parameters to add. - * @param container the container to add the parameters to. - */ - private void refreshParameters(ArrayList<Parameter<?>> newParameters, VBox container) { - // remove what is currently in the container from the parameter list - parameters.removeAll(container.getChildren()); - // remove everything in the container - container.getChildren().clear(); - // if there are parameters to add, add them all - if (newParameters != null) { - for (int i = 0; i < newParameters.size(); i++) { - // factory method returns the right subtype of GUIParameter - GUIParameter<?> guiParameter = GUIParameter.create(newParameters.get(i), this); - // make sure to add it to the parameter list as well - parameters.add(guiParameter); - container.getChildren().add(guiParameter); - } - } - // do a quick refresh just in case something is invalid - revalidateParameters(); - } - - /** - * This method handles a problem type change by updating the list of allowed - * node functions. - * <br><br> - * It does so by creating new checkboxes for each function in the function set. - */ - private void refreshFunctions() { - // remove all current functions - nodeFunctions.getChildren().clear(); - CheckBox checkBox; - // get a reference to the function set - final FunctionSet functionSet = gui.getExperiment().getResources().getFunctionSet(); - for (int i = 0; i < functionSet.getTotalFunctionCount(); i++) { - // add a checkbox for each function - checkBox = new CheckBox(functionSet.getFunction(i).toString()); - checkBox.setId(String.valueOf(i)); - // make sure the selection matches the function set - checkBox.setSelected(functionSet.isEnabled(functionSet.getFunction(i))); - final int index = i; - // set listener so function set gets updated if the checkboxes change - checkBox.setOnAction(new EventHandler<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - if (((CheckBox) event.getSource()).isSelected()) { - functionSet.enableFunction(index); - } else { - functionSet.disableFunction(index); - } - gui.updateFunctionSelector(); - revalidateParameters(); - } - }); - // add the new checkbox - nodeFunctions.getChildren().add(checkBox); - } - // make sure function selector has all functions - gui.updateFunctionSelector(); - } - - /** - * @return true if the experiment is currently evolving something, false otherwise. - */ - 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. - * <br><br> - * This also disables the controls if a reset is necessary, preventing the experiment - * from running until it has happened. - */ - 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. - * <br><br> - * It also closes the test case table, just in case. - */ - public void applyParameters() { - for (GUIParameter<?> parameter : parameters) { - parameter.applyValue(); - } - updateArity(); - if (testCaseTable != null) { - testCaseTable.close(); - } - } - - /** - * 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<Object>) 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(); - } -} diff --git a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java deleted file mode 100644 index a1f03fe..0000000 --- a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java +++ /dev/null @@ -1,82 +0,0 @@ -package jcgp.gui.settings.parameters; - -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.scene.control.CheckBox; -import javafx.scene.control.Control; -import jcgp.backend.parameters.BooleanParameter; -import jcgp.backend.parameters.ParameterStatus; -import jcgp.gui.constants.Constants; -import jcgp.gui.settings.SettingsPane; - -/** - * This extension of @code{GUIParameter} uses a @code{CheckBox} to display - * the value of a @code{BooleanParameter}. It cannot be constructed - * directly - instead, use @code{GUIParameter.create()}. - * <br><br> - * See {@link GUIParameter} for more information. - * - * @author Eduardo Pedroni - */ -public class GUIBooleanParameter extends GUIParameter<Boolean> { - - private CheckBox checkBox; - - /** - * This protected constructor is intended for use - * by the factory method only. - * - */ - protected GUIBooleanParameter(BooleanParameter parameter, SettingsPane sp) { - super(parameter, sp); - } - - @Override - protected Control makeControl() { - checkBox = new CheckBox(); - checkBox.setSelected(parameter.get()); - - return checkBox; - } - - @Override - protected void setControlListeners() { - /* pass the CheckBox value back to the parameter whenever it gets - * modified, provided the experiment isn't running */ - checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() { - @Override - public void changed( - ObservableValue<? extends Boolean> observable, - Boolean oldValue, Boolean newValue) { - if (!settingsPane.isExperimentRunning()) { - parameter.set(newValue); - settingsPane.revalidateParameters(); - } - } - }); - } - - @Override - protected void setValidityStyle() { - // update the Control's style and tooltip based on the status of the parameter - if (parameter.getStatus() == ParameterStatus.INVALID) { - checkBox.setStyle(Constants.BASE_CHECKBOX_STYLE + Constants.INVALID_PARAMETER_STYLE); - checkBox.setTooltip(tooltip); - tooltip.setText(parameter.getStatus().getDetails()); - } else if (parameter.getStatus() == ParameterStatus.WARNING - || parameter.getStatus() == ParameterStatus.WARNING_RESET) { - checkBox.setStyle(Constants.BASE_CHECKBOX_STYLE + Constants.WARNING_PARAMETER_STYLE); - checkBox.setTooltip(tooltip); - tooltip.setText(parameter.getStatus().getDetails()); - } else { - checkBox.setStyle(Constants.BASE_CHECKBOX_STYLE + Constants.VALID_PARAMETER_STYLE); - checkBox.setTooltip(null); - } - } - - @Override - public void refreshValue() { - checkBox.setSelected(parameter.get()); - } - -} diff --git a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java deleted file mode 100644 index feee34c..0000000 --- a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java +++ /dev/null @@ -1,110 +0,0 @@ -package jcgp.gui.settings.parameters; - -import java.text.DecimalFormat; - -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.geometry.Pos; -import javafx.scene.control.Control; -import javafx.scene.control.TextField; -import jcgp.backend.parameters.DoubleParameter; -import jcgp.backend.parameters.ParameterStatus; -import jcgp.gui.constants.Constants; -import jcgp.gui.settings.SettingsPane; - -/** - * This extension of @code{GUIParameter} uses a @code{TextField} to display - * the value of a @code{DoubleParameter}. It cannot be constructed - * directly - instead, use @code{GUIParameter.create()}. - * <br><br> - * See {@link GUIParameter} for more information. - * - * @author Eduardo Pedroni - */ -public class GUIDoubleParameter extends GUIParameter<Number> { - - private TextField textField; - private DecimalFormat decimalFormat; - - /** - * This protected constructor is intended for use - * by the factory method only. - * - */ - protected GUIDoubleParameter(DoubleParameter parameter, SettingsPane sp) { - super(parameter, sp); - } - - @Override - protected Control makeControl() { - // we use a text field, and a formatting class to enforce decimals - decimalFormat = new DecimalFormat(); - decimalFormat.setMaximumFractionDigits(10); - textField = new TextField(decimalFormat.format(parameter.get().doubleValue())); - textField.setStyle(Constants.VALID_PARAMETER_STYLE); - textField.setAlignment(Pos.CENTER_RIGHT); - textField.prefWidthProperty().bind(widthProperty().divide(2)); - return textField; - } - - @Override - protected void setControlListeners() { - /* pass the TextField value back to the parameter whenever it gets - * modified, provided it is not empty, the experiment isn't running - * and it matches the double-precision regex filter */ - textField.textProperty().addListener(new ChangeListener<String>() { - @Override - public void changed( - ObservableValue<? extends String> observable, - String oldValue, String newValue) { - if (!settingsPane.isExperimentRunning()) { - if (newValue.matches("^[-+]?[0-9]*\\.?[0-9]+$")) { - if (!newValue.isEmpty()) { - double value = Double.parseDouble(newValue); - parameter.set(value); - settingsPane.revalidateParameters(); - } - } else { - refreshValue(); - } - } - } - }); - /* if the TextField loses focus and is empty, set it to the current - * value of the parameter */ - textField.focusedProperty().addListener(new ChangeListener<Boolean>() { - @Override - public void changed( - ObservableValue<? extends Boolean> observable, - Boolean oldValue, Boolean newValue) { - if (!newValue) { - refreshValue(); - } - } - }); - } - - @Override - protected void setValidityStyle() { - // update the Control's style and tooltip based on the status of the parameter - if (parameter.getStatus() == ParameterStatus.INVALID) { - textField.setStyle(Constants.BASE_TEXT_STYLE + Constants.INVALID_PARAMETER_STYLE); - textField.setTooltip(tooltip); - tooltip.setText(parameter.getStatus().getDetails()); - } else if (parameter.getStatus() == ParameterStatus.WARNING || parameter.getStatus() == ParameterStatus.WARNING_RESET) { - textField.setStyle(Constants.BASE_TEXT_STYLE + Constants.WARNING_PARAMETER_STYLE); - textField.setTooltip(tooltip); - tooltip.setText(parameter.getStatus().getDetails()); - } else { - textField.setStyle(Constants.BASE_TEXT_STYLE + Constants.VALID_PARAMETER_STYLE); - textField.setTooltip(null); - } - } - - @Override - public void refreshValue() { - if (!textField.isFocused()) { - textField.setText(decimalFormat.format(parameter.get().doubleValue())); - } - } -} diff --git a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java deleted file mode 100644 index bcfbe50..0000000 --- a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java +++ /dev/null @@ -1,107 +0,0 @@ -package jcgp.gui.settings.parameters; - -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.geometry.Pos; -import javafx.scene.control.Control; -import javafx.scene.control.TextField; -import jcgp.backend.parameters.IntegerParameter; -import jcgp.backend.parameters.ParameterStatus; -import jcgp.gui.constants.Constants; -import jcgp.gui.settings.SettingsPane; - -/** - * This extension of @code{GUIParameter} uses a @code{TextField} to display - * the value of a @code{IntegerParameter}. It cannot be constructed - * directly - instead, use @code{GUIParameter.create()}. - * <br><br> - * See {@link GUIParameter} for more information. - * - * @author Eduardo Pedroni - */ -public class GUIIntegerParameter extends GUIParameter<Number> { - - private TextField textField; - - /** - * This protected constructor is intended for use - * by the factory method only. - * - */ - protected GUIIntegerParameter(IntegerParameter parameter, SettingsPane sp) { - super(parameter, sp); - } - - @Override - protected Control makeControl() { - // this uses a text field - textField = new TextField(String.valueOf(parameter.get())); - textField.setStyle(Constants.VALID_PARAMETER_STYLE); - textField.setAlignment(Pos.CENTER_RIGHT); - textField.prefWidthProperty().bind(widthProperty().divide(2)); - - return textField; - } - - @Override - protected void setControlListeners() { - /* pass the TextField value back to the parameter whenever it gets - * modified, provided it is not empty, the experiment isn't running - * and it matches the integer regex pattern */ - textField.textProperty().addListener(new ChangeListener<String>() { - @Override - public void changed( - ObservableValue<? extends String> observable, - String oldValue, String newValue) { - if (!settingsPane.isExperimentRunning()) { - if (newValue.matches("[0-9]*")) { - if (!newValue.isEmpty()) { - int value = Integer.parseInt(newValue); - parameter.set(value); - settingsPane.revalidateParameters(); - } - } else { - refreshValue(); - } - } - } - }); - /* if the TextField loses focus and is empty, set it to the current - * value of the parameter */ - textField.focusedProperty().addListener(new ChangeListener<Boolean>() { - @Override - public void changed( - ObservableValue<? extends Boolean> observable, - Boolean oldValue, Boolean newValue) { - if (!newValue) { - refreshValue(); - } - } - }); - } - - @Override - protected void setValidityStyle() { - // update the Control's style and tooltip based on the status of the parameter - if (parameter.getStatus() == ParameterStatus.INVALID) { - textField.setStyle(Constants.BASE_TEXT_STYLE + Constants.INVALID_PARAMETER_STYLE); - textField.setTooltip(tooltip); - tooltip.setText(parameter.getStatus().getDetails()); - } else if (parameter.getStatus() == ParameterStatus.WARNING - || parameter.getStatus() == ParameterStatus.WARNING_RESET) { - textField.setStyle(Constants.BASE_TEXT_STYLE + Constants.WARNING_PARAMETER_STYLE); - textField.setTooltip(tooltip); - tooltip.setText(parameter.getStatus().getDetails()); - } else { - textField.setStyle(Constants.BASE_TEXT_STYLE + Constants.VALID_PARAMETER_STYLE); - textField.setTooltip(null); - } - } - - @Override - public void refreshValue() { - if (!textField.isFocused()) { - textField.setText(parameter.get().toString()); - } - } -} diff --git a/src/jcgp/gui/settings/parameters/GUIParameter.java b/src/jcgp/gui/settings/parameters/GUIParameter.java deleted file mode 100644 index 59aecf6..0000000 --- a/src/jcgp/gui/settings/parameters/GUIParameter.java +++ /dev/null @@ -1,235 +0,0 @@ -package jcgp.gui.settings.parameters; - -import java.util.concurrent.atomic.AtomicBoolean; - -import javafx.application.Platform; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.geometry.Pos; -import javafx.scene.control.Control; -import javafx.scene.control.Label; -import javafx.scene.control.Tooltip; -import javafx.scene.layout.HBox; -import jcgp.backend.parameters.BooleanParameter; -import jcgp.backend.parameters.DoubleParameter; -import jcgp.backend.parameters.IntegerParameter; -import jcgp.backend.parameters.Parameter; -import jcgp.backend.parameters.ParameterStatus; -import jcgp.gui.settings.SettingsPane; - -/** - * - * This is the base class for all @code{GUIParameter}s. Using the factory method @code{GUIParameter.create()} - * generates an appropriate instance of this class for the specified parameter. - * <br><br> - * A @code{GUIParameter} is an @code{HBox} containing a @code{Text} for the parameter name - * and a @code{Control} for interaction. - * It stores an instance of its associated @code{Parameter} object and also contains a @code{Tooltip} for - * displaying status information. - * <br><br> - * Monitor parameters are updated automatically and have their @code{Control} disabled so - * that no changes can be made via the GUI. - * Non-monitor parameters are updated automatically as well, but may be changed by the user - * if the program is not evolving. - * - * @see Parameter - * @author Eduardo Pedroni - * @param <T> the parameter data type - */ -public abstract class GUIParameter<T> extends HBox { - - private Label name; - private Control valueControl; - - protected SettingsPane settingsPane; - protected Tooltip tooltip; - protected Parameter<T> parameter; - - /** This is the lock used to prevent more than one update task to be scheduled - * at the same time on the same GUIParameter. */ - private AtomicBoolean updateLock = new AtomicBoolean(false); - - /** - * This value is used to assert whether the control has changed values since - * the program last ran. Therefore, it is updated whenever a generation occurs - * or the experiment is reset. - */ - private T referenceValue; - - /** - * This protected template constructor contains the common elements to all - * @code{GUIParameter}s and should be invoked by any subclasses using @code{super()}. It - * defers the creation of the parameter {@code Control} object to the subclass - * currently being built (which in turn is defined by the factory method). - * - * @param parameter a @code{Parameter} for which to generate a @code{GUIParameter}. - * @param sp a reference to the @code{SettingsPane}. - */ - protected GUIParameter(Parameter<T> parameter, final SettingsPane settingsPane) { - this.parameter = parameter; - this.referenceValue = parameter.get(); - - this.settingsPane = settingsPane; - - setAlignment(Pos.CENTER_LEFT); - setSpacing(5); - - name = new Label(parameter.toString()); - // set text width to half of the total width of the GUIParameter - name.prefWidthProperty().bind(widthProperty().divide(2)); - - // the tooltip is the hover-over label containing status information, when appropriate - tooltip = new Tooltip(); - tooltip.setSkin(null); - - valueControl = makeControl(); - - // if the parameter is a monitor, it should be permanently disabled - valueControl.setDisable(parameter.isMonitor()); - - // bind to parameter value property in a thread-safe way - makeThreadSafeBinding(); - - // if parameter is not a monitor, make sure the control is constrained appropriately - if (!parameter.isMonitor()) { - setControlListeners(); - } - - getChildren().addAll(name, valueControl); - } - - /** - * Factory method to create @code{GUIParameter}s from @code{Parameter}s. - * Use this to create an appropriate @code{GUIParameter} from any instance of @code{Parameter}, - * rather than manually downcasting the @code{Parameter} object every time. - * - * @param parameter a parameter for which to generate a @code{GUIParameter}. - * @param sp a reference to the @code{SettingsPane}. - * @return an appropriate instance of @code{GUIParameter}. - */ - public static GUIParameter<?> create(Parameter<?> parameter, SettingsPane sp) { - if (parameter instanceof IntegerParameter) { - return new GUIIntegerParameter((IntegerParameter) parameter, sp); - } else if (parameter instanceof DoubleParameter) { - return new GUIDoubleParameter((DoubleParameter) parameter, sp); - } else if (parameter instanceof BooleanParameter) { - return new GUIBooleanParameter((BooleanParameter) parameter, sp); - } else { - throw new ClassCastException("No GUIParameter subclass exists for argument of type " + parameter.getClass()); - } - } - - /** - * Parameters are intended to communicate information from the experiment - * to the GUI. Since the experiment runs on a separate threads and it is illegal - * to modify JavaFX objects from outside the JavaFX Application thread, this - * special ChangeListener updates the GUIParameter in a safe way. - * <br><br> - * Note that this is applied to all parameters regardless of whether they are - * monitors or not; the only difference between monitor and non-monitor parameters - * is that monitor parameters cannot be modified from the GUI. - */ - private void makeThreadSafeBinding() { - parameter.valueProperty().addListener(new ChangeListener<Object>() { - @Override - public void changed( - ObservableValue<? extends Object> observable, - Object oldValue, Object newValue) { - // only do this if the experiment is running - if (settingsPane.isExperimentRunning() || !isFocused()) { - /* here's the catch - atomically get the lock state and set it to true - * the lock will only be false again when the runnable is finished executing, - * preventing multiple runnables to concurrently update the same GUIParameter - */ - if (!updateLock.getAndSet(true)) { - Platform.runLater(new Runnable() { - @Override - public void run() { - refreshValue(); - updateLock.set(false); - } - }); - } - } - } - }); - } - - /** - * @return true if the current value of the parameter does not prevent the - * experiment from running. - */ - public boolean isValid() { - return parameter.getStatus() != ParameterStatus.INVALID; - } - - /** - * Force the parameter to validate its current value, and apply the associated - * style to the @code{GUIParameter}. - */ - public void validate() { - parameter.validate(parameter.get()); - setValidityStyle(); - } - - /** - * Certain parameter changes might require the experiment to be reset, either - * because the parameter is critical or because its status requires a reset. - * - * @return true if an experiment reset is required due to this parameter changing. - */ - public boolean requiresReset() { - return (parameter.isCritical() && !parameter.get().equals(referenceValue)) - || parameter.getStatus() == ParameterStatus.WARNING_RESET; - } - - /** - * Set the current parameter value as the reference value of the @code{GUIParameter}. - * The new reference value will be used to determine the validity of the parameter, - * should its value change. - */ - public void applyValue() { - referenceValue = parameter.get(); - } - - /* - * The following prototypes are instance-dependent and are called from - * GUIParameter() as necessary. - */ - /** - * This method returns the @code{Control} object used to control the parameter. - * <br><br> - * Implementations of @code{GUIParameter} must override this method and return - * a @code{Control} appropriate to the type of parameter. This will typically be - * done by referencing the protected field @code{GUIParameter.parameter}. - * - * @return the Control object to be added to the GUIParameter. - */ - protected abstract Control makeControl(); - - /** - * Adds the necessary handlers to the @code{Control} object in order to modify - * the underlying parameter. This will typically consist of filtering key - * presses to ensure no invalid characters are inserted, applying the new - * value to the underlying parameter and revalidating the parameters to - * reflect the changes made. - */ - protected abstract void setControlListeners(); - - /** - * This method is called to style the @code{GUIParameter} according to the status of - * the parameter, which can be obtained with @code{parameter.getStatus()}. While the - * subclass is free to style itself in any way, the CSS strings defined here - * (INVALID_PARAMETER_STYLE, WARNING_PARAMETER_STYLE, VALID_PARAMETER_STYLE) - * provide a way to keep the GUI consistent. - * - * @see ParameterStatus - */ - protected abstract void setValidityStyle(); - - /** - * Update the control so it shows the correct value of the parameter. This method - * is used exclusively by the thread-safe binding created if the module is a monitor. - */ - protected abstract void refreshValue(); -} diff --git a/src/jcgp/gui/settings/testcase/TestCaseTable.java b/src/jcgp/gui/settings/testcase/TestCaseTable.java deleted file mode 100644 index 605b75e..0000000 --- a/src/jcgp/gui/settings/testcase/TestCaseTable.java +++ /dev/null @@ -1,124 +0,0 @@ -package jcgp.gui.settings.testcase; - -import java.util.ArrayList; - -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.collections.ObservableList; -import javafx.event.EventHandler; -import javafx.scene.Scene; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableColumn.CellDataFeatures; -import javafx.scene.control.TableView; -import javafx.stage.Stage; -import javafx.stage.WindowEvent; -import javafx.util.Callback; -import jcgp.backend.modules.problem.TestCaseProblem; -import jcgp.backend.modules.problem.TestCaseProblem.TestCase; -import jcgp.backend.resources.Resources; -import jcgp.gui.GUI; - -/** - * This is a test case table. For problems that have test cases, - * this table shows the test case inputs and outputs. Clicking on - * a test case (one is shown per row) applies the values to all - * chromosome inputs shows the calculated values throughout the chromosome. - * - * @author Eduardo Pedroni - * - */ -public class TestCaseTable extends Stage { - - private TableView<TestCase<Object>> table; - - /** - * Make a new instance of {@code TestCaseTable}. - * - * @param testCaseProblem the {@code TestCaseProblem} whose data must be displayed. - * @param gui a reference to the GUI. - */ - public TestCaseTable(final TestCaseProblem<Object> testCaseProblem, final GUI gui) { - super(); - - Resources resources = gui.getExperiment().getResources(); - - // create the actual table view - table = new TableView<TestCase<Object>>(); - // get test cases from problem - ObservableList<TestCase<Object>> testCaseList = testCaseProblem.getTestCases(); - - // prepare input and output columns - ArrayList<TableColumn<TestCase<Object>, String>> inputs = new ArrayList<TableColumn<TestCase<Object>, String>>(resources.inputs()); - ArrayList<TableColumn<TestCase<Object>, String>> outputs = new ArrayList<TableColumn<TestCase<Object>, String>>(resources.outputs()); - - // create input columns - TableColumn<TestCase<Object>, String> tc; - for (int i = 0; i < resources.inputs(); i++) { - tc = new TableColumn<TestCase<Object>, String>("I: " + i); - inputs.add(tc); - final int index = i; - tc.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<TestCase<Object>,String>, ObservableValue<String>>() { - @Override - public ObservableValue<String> call(CellDataFeatures<TestCase<Object>, String> param) { - // create a new string property and give it the test case value, no need for dynamic binding - this wont change often - return new SimpleStringProperty(param.getValue().getInputs()[index].toString()); - } - }); - tc.setSortable(false); - // set column width so all columns are distributed across the width of the stage - tc.prefWidthProperty().bind(table.widthProperty().divide(resources.inputs() + resources.outputs())); - } - - // create output columns - for (int o = 0; o < resources.outputs(); o++) { - tc = new TableColumn<TestCase<Object>, String>("O: " + o); - outputs.add(tc); - final int index = o; - tc.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<TestCase<Object>,String>, ObservableValue<String>>() { - @Override - public ObservableValue<String> call(CellDataFeatures<TestCase<Object>, String> param) { - // create a new string property and give it the test case value, no need for dynamic binding - this wont change often - return new SimpleStringProperty(param.getValue().getOutputs()[index].toString()); - } - }); - tc.setSortable(false); - // set column width so all columns are distributed across the width of the stage - tc.prefWidthProperty().bind(table.widthProperty().divide(resources.inputs() + resources.outputs())); - } - - // add created columns - table.getColumns().addAll(inputs); - table.getColumns().addAll(outputs); - - // populate table with actual data - table.setItems(testCaseList); - - // apply test case values when a new test case is selected - table.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TestCase<Object>>() { - @Override - public void changed(ObservableValue<? extends TestCase<Object>> observable, TestCase<Object> oldValue, TestCase<Object> newValue) { - gui.evaluateTestCase(newValue); - } - }); - - // when the stage is closed, clear the selection - // this doesn't work if the stage is closed by the program for some reason... - setOnCloseRequest(new EventHandler<WindowEvent>() { - @Override - public void handle(WindowEvent event) { - gui.hideGeneValues(); - table.getSelectionModel().clearSelection(); - } - }); - - setScene(new Scene(table)); - } - - /** - * @return a reference to the actual table of test cases. - */ - public TableView<TestCase<Object>> getTable() { - return table; - } -} |