2017-07-31 16:48:04 -07:00
|
|
|
package org.nwapw.abacus.fx;
|
|
|
|
|
2017-08-03 14:04:09 -07:00
|
|
|
import javafx.application.Platform;
|
2017-07-31 17:49:57 -07:00
|
|
|
import javafx.collections.FXCollections;
|
|
|
|
import javafx.collections.ObservableList;
|
2017-07-31 16:52:34 -07:00
|
|
|
import javafx.fxml.FXML;
|
2017-07-31 22:53:42 -07:00
|
|
|
import javafx.scene.control.*;
|
2017-07-31 17:17:56 -07:00
|
|
|
import javafx.scene.text.Text;
|
2017-07-31 22:53:42 -07:00
|
|
|
import javafx.util.Callback;
|
2017-07-31 16:52:34 -07:00
|
|
|
import org.nwapw.abacus.Abacus;
|
2017-07-31 17:17:56 -07:00
|
|
|
import org.nwapw.abacus.number.NumberInterface;
|
|
|
|
import org.nwapw.abacus.tree.TreeNode;
|
2017-07-31 16:52:34 -07:00
|
|
|
|
2017-07-31 22:53:42 -07:00
|
|
|
|
2017-08-01 10:47:31 -07:00
|
|
|
/**
|
|
|
|
* The controller for the abacus FX UI, responsible
|
|
|
|
* for all the user interaction.
|
|
|
|
*/
|
2017-07-31 16:48:04 -07:00
|
|
|
public class AbacusController {
|
|
|
|
|
2017-08-01 10:47:31 -07:00
|
|
|
/**
|
|
|
|
* Constant string that is displayed if the text could not be lexed or parsed.
|
|
|
|
*/
|
2017-07-31 17:17:56 -07:00
|
|
|
private static final String ERR_SYNTAX = "Syntax Error";
|
2017-08-01 10:47:31 -07:00
|
|
|
/**
|
|
|
|
* Constant string that is displayed if the tree could not be reduced.
|
|
|
|
*/
|
2017-07-31 17:17:56 -07:00
|
|
|
private static final String ERR_EVAL = "Evaluation Error";
|
2017-08-03 14:04:09 -07:00
|
|
|
/**
|
|
|
|
* Constant string that is displayed if the calculations are stopped before they are done.
|
|
|
|
*/
|
|
|
|
private static final String ERR_STOP = "Stopped";
|
2017-07-31 22:29:44 -07:00
|
|
|
@FXML
|
|
|
|
private TableView<HistoryModel> historyTable;
|
|
|
|
@FXML
|
|
|
|
private TableColumn<HistoryModel, String> inputColumn;
|
|
|
|
@FXML
|
|
|
|
private TableColumn<HistoryModel, String> parsedColumn;
|
|
|
|
@FXML
|
|
|
|
private TableColumn<HistoryModel, String> outputColumn;
|
2017-07-31 17:17:56 -07:00
|
|
|
@FXML
|
|
|
|
private Text outputText;
|
|
|
|
@FXML
|
|
|
|
private TextField inputField;
|
|
|
|
@FXML
|
|
|
|
private Button inputButton;
|
2017-08-01 11:52:48 -07:00
|
|
|
@FXML
|
|
|
|
private ComboBox<String> numberImplementationBox;
|
2017-07-31 17:17:56 -07:00
|
|
|
|
2017-08-01 10:47:31 -07:00
|
|
|
/**
|
|
|
|
* The list of history entries, created by the users.
|
|
|
|
*/
|
2017-07-31 17:49:57 -07:00
|
|
|
private ObservableList<HistoryModel> historyData;
|
|
|
|
|
2017-08-01 10:47:31 -07:00
|
|
|
/**
|
|
|
|
* The abacus instance used for calculations and all
|
|
|
|
* other main processing code.
|
|
|
|
*/
|
2017-08-01 11:52:48 -07:00
|
|
|
private ObservableList<String> numberImplementationOptions;
|
|
|
|
|
2017-08-03 14:04:09 -07:00
|
|
|
/**
|
|
|
|
* Thread used for calculating.
|
|
|
|
*/
|
|
|
|
private Thread calcThread;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether the calculator is calculating.
|
|
|
|
*/
|
|
|
|
private boolean calculating;
|
|
|
|
|
2017-07-31 16:52:34 -07:00
|
|
|
private Abacus abacus;
|
|
|
|
|
|
|
|
@FXML
|
|
|
|
public void initialize(){
|
2017-07-31 22:53:42 -07:00
|
|
|
Callback<TableColumn<HistoryModel, String>, TableCell<HistoryModel, String>> cellFactory =
|
|
|
|
param -> new CopyableCell<>();
|
|
|
|
|
2017-07-31 17:49:57 -07:00
|
|
|
historyData = FXCollections.observableArrayList();
|
2017-07-31 22:29:44 -07:00
|
|
|
historyTable.setItems(historyData);
|
2017-08-01 11:52:48 -07:00
|
|
|
numberImplementationOptions = FXCollections.observableArrayList();
|
|
|
|
numberImplementationBox.setItems(numberImplementationOptions);
|
|
|
|
numberImplementationBox.valueProperty().addListener((observable, oldValue, newValue)
|
|
|
|
-> {
|
|
|
|
abacus.getConfiguration().setNumberImplementation(newValue);
|
|
|
|
abacus.getConfiguration().saveTo(Abacus.CONFIG_FILE);
|
|
|
|
});
|
2017-07-31 22:34:49 -07:00
|
|
|
historyTable.getSelectionModel().setCellSelectionEnabled(true);
|
2017-07-31 22:53:42 -07:00
|
|
|
inputColumn.setCellFactory(cellFactory);
|
2017-07-31 22:29:44 -07:00
|
|
|
inputColumn.setCellValueFactory(cell -> cell.getValue().inputProperty());
|
2017-07-31 22:53:42 -07:00
|
|
|
parsedColumn.setCellFactory(cellFactory);
|
2017-07-31 22:29:44 -07:00
|
|
|
parsedColumn.setCellValueFactory(cell -> cell.getValue().parsedProperty());
|
2017-07-31 22:53:42 -07:00
|
|
|
outputColumn.setCellFactory(cellFactory);
|
2017-07-31 22:29:44 -07:00
|
|
|
outputColumn.setCellValueFactory(cell -> cell.getValue().outputProperty());
|
2017-08-01 11:52:48 -07:00
|
|
|
|
|
|
|
abacus = new Abacus();
|
|
|
|
numberImplementationOptions.addAll(abacus.getPluginManager().getAllNumbers());
|
|
|
|
String actualImplementation = abacus.getConfiguration().getNumberImplementation();
|
|
|
|
String toSelect = (numberImplementationOptions.contains(actualImplementation)) ? actualImplementation : "naive";
|
|
|
|
numberImplementationBox.getSelectionModel().select(toSelect);
|
2017-07-31 16:52:34 -07:00
|
|
|
}
|
|
|
|
|
2017-07-31 17:17:56 -07:00
|
|
|
@FXML
|
|
|
|
private void performCalculation(){
|
2017-08-03 14:04:09 -07:00
|
|
|
Runnable calculator = new Runnable(){
|
|
|
|
public void run() {
|
|
|
|
calculating = true;
|
|
|
|
Platform.runLater(() -> inputButton.setDisable(true));
|
|
|
|
TreeNode constructedTree = abacus.parseString(inputField.getText());
|
|
|
|
if (constructedTree == null) {
|
|
|
|
Platform.runLater(() ->outputText.setText(ERR_SYNTAX));
|
|
|
|
Platform.runLater(() -> inputButton.setDisable(false));
|
|
|
|
//return;
|
|
|
|
}else {
|
|
|
|
NumberInterface evaluatedNumber = abacus.evaluateTree(constructedTree);
|
|
|
|
if (evaluatedNumber == null) {
|
|
|
|
if(Thread.currentThread().isInterrupted()){
|
|
|
|
Platform.runLater(() -> outputText.setText(ERR_STOP));
|
|
|
|
Platform.runLater(() -> inputButton.setDisable(false));
|
|
|
|
}else {
|
|
|
|
Platform.runLater(() -> outputText.setText(ERR_EVAL));
|
|
|
|
Platform.runLater(() -> inputButton.setDisable(false));
|
|
|
|
//return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Platform.runLater(() -> outputText.setText(evaluatedNumber.toString()));
|
|
|
|
|
|
|
|
historyData.add(new HistoryModel(inputField.getText(), constructedTree.toString(), evaluatedNumber.toString()));
|
2017-07-31 22:29:44 -07:00
|
|
|
|
2017-08-03 14:04:09 -07:00
|
|
|
Platform.runLater(() -> inputButton.setDisable(false));
|
|
|
|
Platform.runLater(() -> inputField.setText(""));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
calculating = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if(!calculating) {
|
|
|
|
calcThread = new Thread(calculator);
|
|
|
|
calcThread.start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@FXML
|
|
|
|
private void stopCalculation(){
|
|
|
|
calcThread.interrupt();
|
|
|
|
calculating = false;
|
2017-07-31 22:29:44 -07:00
|
|
|
inputButton.setDisable(false);
|
2017-07-31 17:17:56 -07:00
|
|
|
}
|
|
|
|
|
2017-07-31 16:48:04 -07:00
|
|
|
}
|