aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/jcgp/gui')
-rw-r--r--src/jcgp/gui/GUI.java4
-rw-r--r--src/jcgp/gui/console/GUIConsole.java21
-rw-r--r--src/jcgp/gui/dragresize/HorizontalDragResize.java51
-rw-r--r--src/jcgp/gui/dragresize/VerticalDragResize.java46
-rw-r--r--src/jcgp/gui/population/ChromosomePane.java41
-rw-r--r--src/jcgp/gui/population/GUIGene.java6
-rw-r--r--src/jcgp/gui/population/GUIInput.java3
-rw-r--r--src/jcgp/gui/population/GUINode.java18
-rw-r--r--src/jcgp/gui/population/GUIOutput.java15
-rw-r--r--src/jcgp/gui/population/PopulationPane.java6
-rw-r--r--src/jcgp/gui/settings/SettingsPane.java9
-rw-r--r--src/jcgp/gui/settings/parameters/GUIParameter.java2
-rw-r--r--src/jcgp/gui/settings/testcase/TestCaseTable.java33
13 files changed, 190 insertions, 65 deletions
diff --git a/src/jcgp/gui/GUI.java b/src/jcgp/gui/GUI.java
index cd4778f..437a739 100644
--- a/src/jcgp/gui/GUI.java
+++ b/src/jcgp/gui/GUI.java
@@ -257,4 +257,8 @@ public class GUI extends Application {
public void flushConsole() {
console.flush();
}
+
+ public int getChromosomeIndex() {
+ return populationPane.getSelectionModel().getSelectedIndex();
+ }
}
diff --git a/src/jcgp/gui/console/GUIConsole.java b/src/jcgp/gui/console/GUIConsole.java
index de4b378..b3d037c 100644
--- a/src/jcgp/gui/console/GUIConsole.java
+++ b/src/jcgp/gui/console/GUIConsole.java
@@ -15,12 +15,25 @@ import javafx.scene.layout.AnchorPane;
import jcgp.backend.resources.Console;
import jcgp.gui.GUI;
+/**
+ * Console pane used by the GUI to display CGP output messages.
+ * This class realises {@code Console}. It consists of a JavaFX
+ * {@code TextArea} and a {@code StringBuffer}. The buffer is filled
+ * as print messages are queued. Calling {@code flush()} writes the
+ * contents of the buffer to the {@code TextArea} and empties the buffer.
+ *
+ * @see Console
+ * @author Eduardo Pedroni
+ *
+ */
public class GUIConsole extends AnchorPane implements Console {
private TextArea textArea = new TextArea("Welcome to JCGP!\n");
-
private StringBuffer printBuffer = new StringBuffer();
+ /**
+ * Creates a new instance of this class.
+ */
public GUIConsole() {
super();
textArea.setEditable(false);
@@ -31,7 +44,10 @@ public class GUIConsole extends AnchorPane implements Console {
* This has not been fixed as of 8/4/2014.
*
* The following code modifies the EventDispatcher to consume the right mouse
- * button click, preventing the default menu from appearing.
+ * button click, preventing the default menu from appearing. It propagates the mouse
+ * click further so other elements will respond appropriately.
+ *
+ * TODO this should be refactored once the API is updated.
*/
final EventDispatcher initial = textArea.getEventDispatcher();
textArea.setEventDispatcher(new EventDispatcher() {
@@ -76,6 +92,7 @@ public class GUIConsole extends AnchorPane implements Console {
new SeparatorMenuItem(),
clearConsole));
+ // anchor the text area so it resizes automatically
AnchorPane.setTopAnchor(textArea, GUI.RESIZE_MARGIN);
AnchorPane.setBottomAnchor(textArea, 0.0);
AnchorPane.setRightAnchor(textArea, 0.0);
diff --git a/src/jcgp/gui/dragresize/HorizontalDragResize.java b/src/jcgp/gui/dragresize/HorizontalDragResize.java
index 84c322f..b618b74 100644
--- a/src/jcgp/gui/dragresize/HorizontalDragResize.java
+++ b/src/jcgp/gui/dragresize/HorizontalDragResize.java
@@ -7,9 +7,11 @@ import javafx.scene.layout.Region;
import jcgp.gui.GUI;
/**
- *
- * Decorator pattern.
- *
+ * This class adds horizontal drag resize functionality to any
+ * arbitrary region provided. This is done by using the static
+ * method {@code makeDragResizable()}.
+ * <br><br>
+ * This is based on a class by Andrew Till found on:
* http://andrewtill.blogspot.co.uk/2012/12/dragging-to-resize-javafx-region.html
*
*/
@@ -18,13 +20,29 @@ public class HorizontalDragResize {
private boolean dragging = false;
private final Region region;
+ /**
+ * For internal use only, creates an instance of the actual
+ * resizer used.
+ *
+ * @param region the region to make resizable.
+ */
private HorizontalDragResize(Region region) {
this.region = region;
}
+ /**
+ * Makes the specified region drag resizable.
+ * This particular implementation only creates a resize
+ * click-and-drag area on the left side of the region.
+ * The resize area is defined by {@code GUI.RESIZE_MARGIN}.
+ *
+ * @param region the region to make resizable.
+ */
public static void makeDragResizable(final Region region) {
+ // make the instance, this actually performs the resizing
final HorizontalDragResize dr = new HorizontalDragResize(region);
+ // set mouse listeners
region.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
@@ -52,12 +70,22 @@ public class HorizontalDragResize {
}
+ /**
+ * If the press happened in the resize area, raise the drag flag.
+ *
+ * @param event the associated mouse event.
+ */
private void mousePressed(MouseEvent event) {
if(isInDraggableZone(event)) {
dragging = true;
}
}
+ /**
+ * If drag flag is high, resize the region to match the mouse position.
+ *
+ * @param event the associated mouse event.
+ */
private void mouseDragged(MouseEvent event) {
if(dragging) {
double newWidth = region.getWidth() - event.getX();
@@ -69,20 +97,33 @@ public class HorizontalDragResize {
}
}
+ /**
+ * Change the cursor if the mouse position overlaps with the resize area.
+ *
+ * @param event the associated mouse event.
+ */
private void mouseMoved(MouseEvent event) {
if(isInDraggableZone(event) || dragging) {
region.setCursor(Cursor.H_RESIZE);
- }
- else {
+ } else {
region.setCursor(Cursor.DEFAULT);
}
}
+ /**
+ * Finish resizing.
+ */
private void mouseReleased() {
dragging = false;
region.setCursor(Cursor.DEFAULT);
}
+ /**
+ * Assert whether the mouse cursor is in the draggable area defined by {@code GUI.RESIZE_MARGIN}.
+ *
+ * @param event the associated mouse event.
+ * @return true if the mouse position is in the draggable area.
+ */
private boolean isInDraggableZone(MouseEvent event) {
return event.getX() < (GUI.RESIZE_MARGIN);
}
diff --git a/src/jcgp/gui/dragresize/VerticalDragResize.java b/src/jcgp/gui/dragresize/VerticalDragResize.java
index 9397e5d..06186c6 100644
--- a/src/jcgp/gui/dragresize/VerticalDragResize.java
+++ b/src/jcgp/gui/dragresize/VerticalDragResize.java
@@ -7,7 +7,11 @@ import javafx.scene.layout.Region;
import jcgp.gui.GUI;
/**
- *
+ * This class adds vertical drag resize functionality to any
+ * arbitrary region provided. This is done by using the static
+ * method {@code makeDragResizable()}.
+ * <br><br>
+ * This is based on a class by Andrew Till found on:
* http://andrewtill.blogspot.co.uk/2012/12/dragging-to-resize-javafx-region.html
*
*/
@@ -16,13 +20,29 @@ public class VerticalDragResize {
private boolean dragging = false;
private final Region region;
+ /**
+ * For internal use only, creates an instance of the actual
+ * resizer used.
+ *
+ * @param region the region to make resizable.
+ */
private VerticalDragResize(Region region) {
this.region = region;
}
+ /**
+ * Makes the specified region drag resizable.
+ * This particular implementation only creates a resize
+ * click-and-drag area on the top side of the region.
+ * The resize area is defined by {@code GUI.RESIZE_MARGIN}.
+ *
+ * @param region the region to make resizable.
+ */
public static void makeDragResizable(final Region region) {
+ // make the instance, this actually performs the resizing
final VerticalDragResize dr = new VerticalDragResize(region);
+ // set mouse listeners
region.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
@@ -50,12 +70,22 @@ public class VerticalDragResize {
}
+ /**
+ * If the press happened in the resize area, raise the drag flag.
+ *
+ * @param event the associated mouse event.
+ */
private void mousePressed(MouseEvent event) {
if(isInDraggableZone(event)) {
dragging = true;
}
}
+ /**
+ * If drag flag is high, resize the region to match the mouse position.
+ *
+ * @param event the associated mouse event.
+ */
private void mouseDragged(MouseEvent event) {
if(dragging) {
double newHeight = region.getHeight() - event.getY();
@@ -67,6 +97,11 @@ public class VerticalDragResize {
}
}
+ /**
+ * Change the cursor if the mouse position overlaps with the resize area.
+ *
+ * @param event the associated mouse event.
+ */
private void mouseMoved(MouseEvent event) {
if(isInDraggableZone(event) || dragging) {
region.setCursor(Cursor.V_RESIZE);
@@ -76,11 +111,20 @@ public class VerticalDragResize {
}
}
+ /**
+ * Finish resizing.
+ */
private void mouseReleased() {
dragging = false;
region.setCursor(Cursor.DEFAULT);
}
+ /**
+ * Assert whether the mouse cursor is in the draggable area defined by {@code GUI.RESIZE_MARGIN}.
+ *
+ * @param event the associated mouse event.
+ * @return true if the mouse position is in the draggable area.
+ */
private boolean isInDraggableZone(MouseEvent event) {
return event.getY() < (GUI.RESIZE_MARGIN);
}
diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java
index 4a47f34..d40de2e 100644
--- a/src/jcgp/gui/population/ChromosomePane.java
+++ b/src/jcgp/gui/population/ChromosomePane.java
@@ -25,6 +25,8 @@ public class ChromosomePane extends ScrollPane {
private int rows, columns;
+ private Object[] testInputs;
+
private boolean target = false;
private PopulationPane parent;
@@ -111,20 +113,21 @@ public class ChromosomePane extends ScrollPane {
target = newValue;
}
- public void updateGenes() {
+ public void updateGenes(Chromosome chr) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
+ guiNodes[r][c].setNode(chr.getNode(r, c));
guiNodes[r][c].updateLines();
guiNodes[r][c].updateText();
}
}
for (int i = 0; i < guiOutputs.length; i++) {
+ guiOutputs[i].setOutput(chr.getOutput(i));
guiOutputs[i].updateLines();
}
if (isEvaluating()) {
- evaluate(0);
+ setInputs(testInputs);
}
-
}
public void unlockOutputs() {
@@ -144,29 +147,27 @@ public class ChromosomePane extends ScrollPane {
}
public void setInputs(Object[] values) {
+ testInputs = values;
for (int i = 0; i < guiInputs.length; i++) {
guiInputs[i].setValue(values[i]);
- guiInputs[i].updateText();
}
- evaluate(0);
+ updateValues();
}
- public void evaluate(int start) {
- if (start >= 0 || start < columns) {
- for (int c = start; c < columns; c++) {
- for (int r = 0; r < rows; r++) {
- guiNodes[r][c].calculate();
- guiNodes[r][c].updateText();
- }
- }
- for (int o = 0; o < guiOutputs.length; o++) {
- guiOutputs[o].calculate();
- guiOutputs[o].updateText();
- }
- }
- }
+// public void evaluate(int start) {
+// if (start >= 0 || start < columns) {
+// for (int c = 0; c < columns; c++) {
+// for (int r = 0; r < rows; r++) {
+// guiNodes[r][c].updateText();
+// }
+// }
+// for (int o = 0; o < guiOutputs.length; o++) {
+// guiOutputs[o].updateText();
+// }
+// }
+// }
- public void hideValues() {
+ public void updateValues() {
for (int i = 0; i < guiInputs.length; i++) {
guiInputs[i].updateText();
}
diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java
index 3ace150..0eea045 100644
--- a/src/jcgp/gui/population/GUIGene.java
+++ b/src/jcgp/gui/population/GUIGene.java
@@ -39,8 +39,6 @@ public abstract class GUIGene extends Group {
protected ChromosomePane parent;
protected int locked = 0;
-
- protected Object value;
public GUIGene() {
text.setFont(Font.font("Arial", 12));
@@ -92,9 +90,5 @@ public abstract class GUIGene extends Group {
public abstract void setConnectionLine(GUIGene gene);
- public Object getValue() {
- return value;
- }
-
public abstract void updateText();
}
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index 05372c4..fd66ab4 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -219,14 +219,13 @@ public class GUIInput extends GUIGene {
}
public void setValue(Object newValue) {
- value = newValue;
input.setValue(newValue);
}
@Override
public void updateText() {
if (parent.isEvaluating()) {
- text.setText("I: " + input.getIndex() + "\n" + value.toString());
+ text.setText("I: " + input.getIndex() + "\n" + input.getValue().toString());
} else {
text.setText("I: " + input.getIndex());
}
diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java
index 6dfeaa4..d3ae27f 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -398,7 +398,8 @@ public class GUINode extends GUIGene {
public void setChangingConnection(Connection newConnection) {
node.setConnection(connectionIndex, newConnection);
if (parent.isEvaluating()) {
- parent.evaluate(node.getColumn());
+ parent.updateValues();
+// parent.evaluate(node.getColumn());
}
}
@@ -452,24 +453,23 @@ public class GUINode extends GUIGene {
public void updateText() {
if (parent.isEvaluating()) {
- text.setText(node.getFunction() + "\n" + value.toString());
+ text.setText(node.getFunction() + "\n" + node.getValue().toString());
} else {
text.setText(node.getFunction().toString());
}
}
-
- public void calculate() {
- value = node.getValue();
- }
public void setFunction(Function function) {
node.setFunction(function);
if (parent.isEvaluating()) {
- calculate();
- parent.evaluate(node.getColumn());
+// parent.evaluate(node.getColumn());
+ parent.updateValues();
} else {
updateText();
}
-
+ }
+
+ public void setNode(Node newNode) {
+ node = newNode;
}
}
diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java
index 29752cd..5a76298 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -267,10 +267,7 @@ public class GUIOutput extends GUIGene {
@Override
public void setChangingConnection(Connection newConnection) {
output.setConnection(0, newConnection);
- if (parent.isEvaluating()) {
- calculate();
- updateText();
- }
+ updateText();
}
@Override
@@ -308,19 +305,19 @@ public class GUIOutput extends GUIGene {
setLocked(true);
}
}
-
- public void calculate() {
- value = output.getSource().getValue();
- }
@Override
public void updateText() {
if (parent.isEvaluating()) {
- text.setText("O: " + output.getIndex() + "\n" + value.toString());
+ text.setText("O: " + output.getIndex() + "\n" + output.getSource().getValue().toString());
} else {
text.setText("O: " + output.getIndex());
}
}
+ public void setOutput(Output newOutput) {
+ output = newOutput;
+ }
+
}
diff --git a/src/jcgp/gui/population/PopulationPane.java b/src/jcgp/gui/population/PopulationPane.java
index 5fa6067..4b1b7f8 100644
--- a/src/jcgp/gui/population/PopulationPane.java
+++ b/src/jcgp/gui/population/PopulationPane.java
@@ -27,7 +27,7 @@ public class PopulationPane extends TabPane {
Tab tab;
ChromosomePane cp;
for (int i = 0; i < jcgp.getResources().populationSize(); i++) {
- cp = new ChromosomePane(jcgp.getPopulation().getChromosome(i), gui, this);
+ cp = new ChromosomePane(jcgp.getPopulation().get(i), gui, this);
tab = new Tab("Chr " + i);
tab.setContent(cp);
getTabs().add(tab);
@@ -39,7 +39,7 @@ public class PopulationPane extends TabPane {
evaluateTestCase(currentTestCase);
}
for (int i = 0; i < getTabs().size(); i++) {
- ((ChromosomePane) getTabs().get(i).getContent()).updateGenes();
+ ((ChromosomePane) getTabs().get(i).getContent()).updateGenes(gui.getExperiment().getPopulation().get(i));
}
}
@@ -73,7 +73,7 @@ public class PopulationPane extends TabPane {
public void hideValues() {
evaluating = false;
for (int i = 0; i < getTabs().size(); i++) {
- ((ChromosomePane) getTabs().get(i).getContent()).hideValues();
+ ((ChromosomePane) getTabs().get(i).getContent()).updateValues();
}
}
diff --git a/src/jcgp/gui/settings/SettingsPane.java b/src/jcgp/gui/settings/SettingsPane.java
index 802c1f1..2898dc3 100644
--- a/src/jcgp/gui/settings/SettingsPane.java
+++ b/src/jcgp/gui/settings/SettingsPane.java
@@ -255,7 +255,7 @@ public class SettingsPane extends AnchorPane {
}
private Button makeTestCaseButton() {
- Button b = new Button("Show data1");
+ Button b = new Button("Show data");
b.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
@@ -331,7 +331,7 @@ public class SettingsPane extends AnchorPane {
fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*"));
File chrFile = fc.showOpenDialog(gui.getStage());
if (chrFile != null) {
- gui.getExperiment().loadChromosome(chrFile, 0);
+ gui.getExperiment().loadChromosome(chrFile, gui.getChromosomeIndex());
gui.reDraw();
}
gui.flushConsole();
@@ -346,7 +346,7 @@ public class SettingsPane extends AnchorPane {
fc.getExtensionFilters().add(new ExtensionFilter("All files", "*.*"));
File chrFile = fc.showSaveDialog(gui.getStage());
if (chrFile != null) {
- gui.getExperiment().saveChromosome(chrFile, 0);
+ gui.getExperiment().saveChromosome(chrFile, gui.getChromosomeIndex());
}
gui.flushConsole();
}
@@ -474,6 +474,9 @@ public class SettingsPane extends AnchorPane {
parameter.applyValue();
}
updateArity();
+ if (testCaseTable != null) {
+ testCaseTable.close();
+ }
}
/**
diff --git a/src/jcgp/gui/settings/parameters/GUIParameter.java b/src/jcgp/gui/settings/parameters/GUIParameter.java
index 3009340..f896fa3 100644
--- a/src/jcgp/gui/settings/parameters/GUIParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIParameter.java
@@ -23,7 +23,7 @@ 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>
- * @code{GUIParameter} is an @code{HBox} containing a @code{Text} for the parameter name
+ * 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.
diff --git a/src/jcgp/gui/settings/testcase/TestCaseTable.java b/src/jcgp/gui/settings/testcase/TestCaseTable.java
index d4c1ff9..d4f789c 100644
--- a/src/jcgp/gui/settings/testcase/TestCaseTable.java
+++ b/src/jcgp/gui/settings/testcase/TestCaseTable.java
@@ -20,7 +20,10 @@ 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
*
@@ -29,17 +32,27 @@ 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);
@@ -48,13 +61,16 @@ public class TestCaseTable extends Stage {
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().getInput(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);
@@ -62,37 +78,46 @@ public class TestCaseTable extends Stage {
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().getOutput(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) {
+ 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().select(null);
+ table.getSelectionModel().clearSelection();
}
});
setScene(new Scene(table));
}
+ /**
+ * @return a reference to the actual table of test cases.
+ */
public TableView<TestCase<Object>> getTable() {
return table;
}