diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/App.java b/src/main/java/com/JayPi4c/RobbiSimulator/App.java
index f0122cc..721c7df 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/App.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/App.java
@@ -1,16 +1,11 @@
package com.JayPi4c.RobbiSimulator;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
-
-import java.util.ResourceBundle;
-
import com.JayPi4c.RobbiSimulator.controller.program.ProgramController;
import com.JayPi4c.RobbiSimulator.controller.tutor.TutorController;
import com.JayPi4c.RobbiSimulator.utils.AlertHelper;
import com.JayPi4c.RobbiSimulator.utils.HibernateUtils;
import com.JayPi4c.RobbiSimulator.utils.I18nUtils;
import com.JayPi4c.RobbiSimulator.utils.PropertiesLoader;
-
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.Alert.AlertType;
@@ -18,100 +13,101 @@
import lombok.extern.slf4j.Slf4j;
import javax.swing.*;
+import java.util.ResourceBundle;
+
+import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
/**
- *
- * Hauptklasse des Robbi Simulators.
- * Javaversion: 17
- *
- * @author Jonas Pohl
+ * Application entry point.
+ * Java version: 21
*
+ * @author Jonas Pohl
*/
@Slf4j
public class App extends Application {
- private static final String INIT_ERROR_MESSAGE = "Init.error.message";
- private static final String INIT_ERROR_TITLE = "Init.error.title";
- private static final String INIT_ERROR_HEADER = "Init.error.header";
-
- /**
- * Application entry point
- *
- * @param args the arguments from the command line
- */
- public static void main(String[] args) {
- try {
- launch(args);
- } catch (Exception e) {
- e.printStackTrace();
- JOptionPane.showMessageDialog(null, """
- Failed to load application.
- Further information can be obtained running the
- application in the command line.
- Please consider submitting your error.
- """);
- }
- }
-
- @Override
- public void init() {
- logger.info("Initialize application");
-
- logger.debug("Initializing properties...");
- if (PropertiesLoader.initialize()) {
- logger.debug("Loaded properties successfully");
- } else
- logger.debug("Failed to load properties.");
-
- I18nUtils.setBundle(ResourceBundle.getBundle("lang.messages", PropertiesLoader.getLocale()));
-
- logger.debug("Loading Program Controller");
- if (!ProgramController.initialize()) {
- logger.error("Failed to load Program Controller");
- AlertHelper.showAlertAndWait(AlertType.ERROR, i18n(INIT_ERROR_MESSAGE), null, null, i18n(INIT_ERROR_TITLE),
- i18n(INIT_ERROR_HEADER));
- Platform.exit();
- }
- logger.debug("loading Program Controller successfully");
-
- if (PropertiesLoader.isTutor()) {
- logger.debug("Starting Tutor RMI server");
- if (TutorController.initialize())
- logger.debug("RMI server started");
- else
- logger.debug("Failed to initialize RMI server.");
- }
- }
-
- @Override
- public void start(Stage primaryStage) {
- logger.info("Starting application");
- logger.debug("Creating scene");
- ProgramController.createAndShow(ProgramController.DEFAULT_ROBBI_FILE_NAME);
- logger.debug("Scene creation done");
- }
-
- @Override
- public void stop() {
-
- logger.debug("Shutting down database connection");
- HibernateUtils.shutdown();
-
- if (PropertiesLoader.isTutor()) {
- logger.debug("Stopping Tutor-Server.");
- if (TutorController.shutdown())
- logger.debug("Tutor RMI server stopped successfully.");
- else
- logger.debug("Failed to shutdown Tutor RMI server");
- }
-
- logger.debug("saving properties...");
- if (PropertiesLoader.finish())
- logger.debug("Properties saved");
- else
- logger.debug("Failed to save properties");
-
- logger.info("Quitting application");
- }
+ private static final String INIT_ERROR_MESSAGE = "Init.error.message";
+ private static final String INIT_ERROR_TITLE = "Init.error.title";
+ private static final String INIT_ERROR_HEADER = "Init.error.header";
+
+ /**
+ * Application entry point
+ *
+ * @param args the arguments from the command line
+ */
+ public static void main(String[] args) {
+ try {
+ launch(args);
+ } catch (Exception e) {
+ logger.error("Failed to load application", e);
+ JOptionPane.showMessageDialog(null, """
+ Failed to load application.
+ Further information can be obtained running the
+ application in the command line.
+ Please consider submitting your error.
+ """);
+ }
+ }
+
+ @Override
+ public void init() {
+ logger.info("Initialize application");
+
+ logger.debug("Initializing properties...");
+ if (PropertiesLoader.initialize()) {
+ logger.debug("Loaded properties successfully");
+ } else
+ logger.debug("Failed to load properties.");
+
+ I18nUtils.setBundle(ResourceBundle.getBundle("lang.messages", PropertiesLoader.getLocale()));
+
+ logger.debug("Loading Program Controller");
+ if (!ProgramController.initialize()) {
+ logger.error("Failed to load Program Controller");
+ AlertHelper.showAlertAndWait(AlertType.ERROR, i18n(INIT_ERROR_MESSAGE), null, null, i18n(INIT_ERROR_TITLE),
+ i18n(INIT_ERROR_HEADER));
+ Platform.exit();
+ }
+ logger.debug("loading Program Controller successfully");
+
+ if (PropertiesLoader.isTutor()) {
+ logger.debug("Starting Tutor RMI server");
+ if (TutorController.initialize())
+ logger.debug("RMI server started");
+ else
+ logger.debug("Failed to initialize RMI server.");
+ }
+ }
+
+ @Override
+ public void start(Stage primaryStage) {
+ logger.info("Starting application");
+ logger.debug("Creating scene");
+ ProgramController.createAndShow(ProgramController.DEFAULT_ROBBI_FILE_NAME);
+ logger.debug("Scene creation done");
+ }
+
+ @Override
+ public void stop() {
+
+ logger.debug("Shutting down database connection");
+ HibernateUtils.shutdown();
+
+ if (PropertiesLoader.isTutor()) {
+ logger.debug("Stopping Tutor-Server.");
+ if (TutorController.shutdown())
+ logger.debug("Tutor RMI server stopped successfully.");
+ else
+ logger.debug("Failed to shutdown Tutor RMI server");
+ }
+
+ logger.debug("saving properties...");
+ if (PropertiesLoader.finish())
+ logger.debug("Properties saved");
+ else
+ logger.debug("Failed to save properties");
+
+ logger.info("Quitting application");
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/ButtonState.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/ButtonState.java
index c3c079e..8590463 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/ButtonState.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/ButtonState.java
@@ -6,69 +6,68 @@
/**
* This class stores the state of the currently selected territory button state.
* The state should be modified by the editor tool buttons.
- *
+ *
* If the TerritoryEventHandler does register a click, the eventHandler gets the
* current state from this class
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
+@Getter
+@Setter
public class ButtonState {
- /**
- * Constant for the ButtonState NONE.
- */
- public static final int NONE = -1;
- /**
- * Constant for the ButtonState ROBBI.
- */
- public static final int ROBBI = 0;
+ /**
+ * Constant for the ButtonState NONE.
+ */
+ public static final int NONE = -1;
+ /**
+ * Constant for the ButtonState ROBBI.
+ */
+ public static final int ROBBI = 0;
- /**
- * Constant for the ButtonState HOLLOW.
- */
- public static final int HOLLOW = 1;
- /**
- * Constant for the ButtonState PILE_OF_SCRAP.
- */
- public static final int PILE_OF_SCRAP = 2;
- /**
- * Constant for the ButtonState STOCKPILE.
- */
- public static final int STOCKPILE = 3;
- /**
- * Constant for the ButtonState ACCU.
- */
- public static final int ACCU = 4;
- /**
- * Constant for the ButtonState SCREW.
- */
- public static final int SCREW = 5;
- /**
- * Constant for the ButtonState NUT.
- */
- public static final int NUT = 6;
- /**
- * Constant for the ButtonState CLEAR.
- */
- public static final int CLEAR = 7;
+ /**
+ * Constant for the ButtonState HOLLOW.
+ */
+ public static final int HOLLOW = 1;
+ /**
+ * Constant for the ButtonState PILE_OF_SCRAP.
+ */
+ public static final int PILE_OF_SCRAP = 2;
+ /**
+ * Constant for the ButtonState STOCKPILE.
+ */
+ public static final int STOCKPILE = 3;
+ /**
+ * Constant for the ButtonState ACCU.
+ */
+ public static final int ACCU = 4;
+ /**
+ * Constant for the ButtonState SCREW.
+ */
+ public static final int SCREW = 5;
+ /**
+ * Constant for the ButtonState NUT.
+ */
+ public static final int NUT = 6;
+ /**
+ * Constant for the ButtonState CLEAR.
+ */
+ public static final int CLEAR = 7;
- @Getter
- @Setter
- private int selected;
+ private int selected;
- /**
- * Creates a new ButtonState and sets the selected state to NONE
- */
- public ButtonState() {
- selected = NONE;
- }
+ /**
+ * Creates a new ButtonState and sets the selected state to NONE
+ */
+ public ButtonState() {
+ selected = NONE;
+ }
- /**
- * reset the currently selected state to NONE
- */
- public void deselect() {
- selected = NONE;
- }
+ /**
+ * reset the currently selected state to NONE
+ */
+ public void deselect() {
+ selected = NONE;
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/ChangeTerritorySizeHandler.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/ChangeTerritorySizeHandler.java
index 2e2043e..1ac8253 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/ChangeTerritorySizeHandler.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/ChangeTerritorySizeHandler.java
@@ -1,108 +1,102 @@
package com.JayPi4c.RobbiSimulator.controller;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
-
-import java.util.Optional;
-
import com.JayPi4c.RobbiSimulator.model.Dimension;
import com.JayPi4c.RobbiSimulator.model.Territory;
-
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
-import javafx.scene.control.ButtonType;
-import javafx.scene.control.Dialog;
-import javafx.scene.control.DialogPane;
-import javafx.scene.control.Label;
-import javafx.scene.control.TextField;
+import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.Modality;
import javafx.stage.Window;
+import java.util.Optional;
+
+import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
+
/**
* This EventHandler combines all the code needed to change the territory size
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class ChangeTerritorySizeHandler implements EventHandler {
- private Territory territory;
+ private final Territory territory;
- private Dialog dialog;
- private Window parent;
+ private Dialog dialog;
+ private final Window parent;
- // language keys
- private static final String CHANGESIZE_DIALOG_TITLE = "ChangeSize.dialog.title";
- private static final String CHANGESIZE_DIALOG_HEADER = "ChangeSize.dialog.header";
- private static final String CHANGESIZE_DIALOG_COLS = "ChangeSize.dialog.cols";
- private static final String CHANGESIZE_DIALOG_ROWS = "ChangeSize.dialog.rows";
+ // language keys
+ private static final String CHANGESIZE_DIALOG_TITLE = "ChangeSize.dialog.title";
+ private static final String CHANGESIZE_DIALOG_HEADER = "ChangeSize.dialog.header";
+ private static final String CHANGESIZE_DIALOG_COLS = "ChangeSize.dialog.cols";
+ private static final String CHANGESIZE_DIALOG_ROWS = "ChangeSize.dialog.rows";
- /**
- * Creates a new ChangeTerritorySizeHandler and sets up a new Dialog, which can
- * be invoked in the handle method
- *
- * @param territory The territory, which size should be changed
- * @param parent The parent window in order to set the dialog relative to the
- * current window
- */
- public ChangeTerritorySizeHandler(Window parent, Territory territory) {
- this.territory = territory;
- this.parent = parent;
- }
+ /**
+ * Creates a new ChangeTerritorySizeHandler and sets up a new Dialog, which can
+ * be invoked in the handle method
+ *
+ * @param territory The territory, which size should be changed
+ * @param parent The parent window in order to set the dialog relative to the
+ * current window
+ */
+ public ChangeTerritorySizeHandler(Window parent, Territory territory) {
+ this.territory = territory;
+ this.parent = parent;
+ }
- /**
- * Creates a new Dialog to handle the size change. The Dialog will be newly
- * created every time in order to have the correct language at every moment.
- */
- private void createDialog() {
- dialog = new Dialog<>();
- dialog.setTitle(i18n(CHANGESIZE_DIALOG_TITLE));
- dialog.setHeaderText(i18n(CHANGESIZE_DIALOG_HEADER));
- DialogPane dialogPane = dialog.getDialogPane();
- dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
- TextField rowField = new TextField();
- rowField.textProperty().addListener((observeable, oldVal, newVal) -> dialog.getDialogPane()
- .lookupButton(ButtonType.OK).setDisable(newVal.isEmpty() || !isValid(newVal)));
- TextField colField = new TextField();
- colField.textProperty().addListener((observable, oldVal, newVal) -> dialog.getDialogPane()
- .lookupButton(ButtonType.OK).setDisable(newVal.isEmpty() || !isValid(newVal)));
+ /**
+ * Creates a new Dialog to handle the size change. The Dialog will be newly
+ * created every time in order to have the correct language at every moment.
+ */
+ private void createDialog() {
+ dialog = new Dialog<>();
+ dialog.setTitle(i18n(CHANGESIZE_DIALOG_TITLE));
+ dialog.setHeaderText(i18n(CHANGESIZE_DIALOG_HEADER));
+ DialogPane dialogPane = dialog.getDialogPane();
+ dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
+ TextField rowField = new TextField();
+ rowField.textProperty().addListener((observeable, oldVal, newVal) -> dialog.getDialogPane()
+ .lookupButton(ButtonType.OK).setDisable(newVal.isEmpty() || !isValid(newVal)));
+ TextField colField = new TextField();
+ colField.textProperty().addListener((observable, oldVal, newVal) -> dialog.getDialogPane()
+ .lookupButton(ButtonType.OK).setDisable(newVal.isEmpty() || !isValid(newVal)));
- GridPane grid = new GridPane();
- grid.addRow(0, new Label(i18n(CHANGESIZE_DIALOG_COLS)), colField);
- grid.addRow(1, new Label(i18n(CHANGESIZE_DIALOG_ROWS)), rowField);
- grid.setHgap(20);
- dialogPane.setContent(grid);
- rowField.setText(Integer.toString(territory.getNumRows()));
- colField.setText(Integer.toString(territory.getNumCols()));
- Platform.runLater(colField::requestFocus);
- dialog.setResultConverter(button -> button == ButtonType.OK
- ? new Dimension(Integer.parseInt(colField.getText()), Integer.parseInt(rowField.getText()))
- : null);
- dialog.initModality(Modality.WINDOW_MODAL);
- dialog.initOwner(parent);
- }
+ GridPane grid = new GridPane();
+ grid.addRow(0, new Label(i18n(CHANGESIZE_DIALOG_COLS)), colField);
+ grid.addRow(1, new Label(i18n(CHANGESIZE_DIALOG_ROWS)), rowField);
+ grid.setHgap(20);
+ dialogPane.setContent(grid);
+ rowField.setText(Integer.toString(territory.getNumRows()));
+ colField.setText(Integer.toString(territory.getNumCols()));
+ Platform.runLater(colField::requestFocus);
+ dialog.setResultConverter(button -> button == ButtonType.OK
+ ? new Dimension(Integer.parseInt(colField.getText()), Integer.parseInt(rowField.getText()))
+ : null);
+ dialog.initModality(Modality.WINDOW_MODAL);
+ dialog.initOwner(parent);
+ }
- /**
- * Checks if the given String is between 1 and 100.
- *
- * @param s the String which represents the user-input
- * @return true if the s is > 0 and <= 100, false otherwise
- */
- private boolean isValid(String s) {
- try {
- int val = Integer.parseInt(s);
- return val > 0 && val <= 100;
- } catch (NumberFormatException e) {
- return false;
- }
- }
+ /**
+ * Checks if the given String is between 1 and 100.
+ *
+ * @param s the String which represents the user-input
+ * @return true if the s is > 0 and <= 100, false otherwise
+ */
+ private boolean isValid(String s) {
+ try {
+ int val = Integer.parseInt(s);
+ return val > 0 && val <= 100;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
- @Override
- public void handle(ActionEvent event) {
- createDialog();
- Optional optionalDimension = dialog.showAndWait();
- optionalDimension.ifPresent(result -> territory.changeSize(result.cols(), result.rows()));
- }
+ @Override
+ public void handle(ActionEvent event) {
+ createDialog();
+ Optional optionalDimension = dialog.showAndWait();
+ optionalDimension.ifPresent(result -> territory.changeSize(result.cols(), result.rows()));
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/LanguageController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/LanguageController.java
index 48ca825..086e76e 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/LanguageController.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/LanguageController.java
@@ -1,266 +1,253 @@
package com.JayPi4c.RobbiSimulator.controller;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.createBinding;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.createTooltip;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
-
-import java.util.Locale;
-
import com.JayPi4c.RobbiSimulator.utils.I18nUtils;
import com.JayPi4c.RobbiSimulator.utils.PropertiesLoader;
import com.JayPi4c.RobbiSimulator.view.MainStage;
import com.JayPi4c.RobbiSimulator.view.MenuBar;
import com.JayPi4c.RobbiSimulator.view.Toolbar;
+import java.util.Locale;
+
+import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.*;
+
/**
* Controller to handle the change of language.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class LanguageController {
- private MainStage stage;
-
- // language keys
- private static final String LANGUAGE_CHANGED = "language.changed";
-
- private static final String MENU_EDITOR_NEW = "Menu.editor.new";
- private static final String MENU_EDITOR_SAVE = "Menu.editor.save";
- private static final String MENU_EDITOR_OPEN = "Menu.editor.open";
- private static final String MENU_EDITOR_FORMAT = "Menu.editor.format";
- private static final String MENU_EDITOR_COMPILE = "Menu.editor.compile";
- private static final String MENU_EDITOR_PRINT = "Menu.editor.print";
- private static final String MENU_EDITOR_QUIT = "Menu.editor.quit";
- private static final String MENU_EDITOR = "Menu.editor";
-
- private static final String MENU_TERRITORY_SAVE_XML = "Menu.territory.save.xml";
- private static final String MENU_TERRITORY_SAVE_JAXB = "Menu.territory.save.jaxb";
- private static final String MENU_TERRITORY_SAVE_SERIALIZE = "Menu.territory.save.serialize";
- private static final String MENU_TERRITORY_SAVE = "Menu.territory.save";
- private static final String MENU_TERRITORY_LOAD_XML = "Menu.territory.load.xml";
- private static final String MENU_TERRITORY_LOAD_JAXB = "Menu.territory.load.jaxb";
- private static final String MENU_TERRITORY_LOAD_DESERIALIZE = "Menu.territory.load.deserialize";
- private static final String MENU_TERRITORY_LOAD = "Menu.territory.load";
- private static final String MENU_TERRITORY_SAVEASPIC_PNG = "Menu.territory.saveAsPic.png";
- private static final String MENU_TERRITORY_SAVEASPIC_GIF = "Menu.territory.saveAsPic.gif";
- private static final String MENU_TERRITORY_SAVEASPIC = "Menu.territory.saveAsPic";
- private static final String MENU_TERRITORY_PRINT = "Menu.territory.print";
- private static final String MENU_TERRITORY_SIZE = "Menu.territory.size";
- private static final String MENU_TERRITORY_PLACE_ROBBI = "Menu.territory.place.robbi";
- private static final String MENU_TERRITORY_PLACE_HOLLOW = "Menu.territory.place.hollow";
- private static final String MENU_TERRITORY_PLACE_PILEOFSCRAP = "Menu.territory.place.pileOfScrap";
- private static final String MENU_TERRITORY_PLACE_STOCKPILE = "Menu.territory.place.stockpile";
- private static final String MENU_TERRITORY_PLACE_ACCU = "Menu.territory.place.accu";
- private static final String MENU_TERRITORY_PLACE_SCREW = "Menu.territory.place.screw";
- private static final String MENU_TERRITORY_PLACE_NUT = "Menu.territory.place.nut";
- private static final String MENU_TERRITORY_DELETE = "Menu.territory.delete";
- private static final String MENU_TERRITORY = "Menu.territory";
-
- private static final String MENU_ROBBI_ITEMPRESENT = "Menu.robbi.itemPresent";
- private static final String MENU_ROBBI_ISSTOCKPILE = "Menu.robbi.isStockpile";
- private static final String MENU_ROBBI_HOLLOWAHEAD = "Menu.robbi.hollowAhead";
- private static final String MENU_ROBBI_PILEOFSCRAPAHEAD = "Menu.robbi.pileOfScrapAhead";
- private static final String MENU_ROBBI_ISBAGFULL = "Menu.robbi.isBagFull";
- private static final String MENU_ROBBI_PUSHPILEOFSCRAP = "Menu.robbi.pushPileOfScrap";
- private static final String MENU_ROBBI_MOVE = "Menu.robbi.move";
- private static final String MENU_ROBBI_TURNLEFT = "Menu.robbi.turnLeft";
- private static final String MENU_ROBBI_PUT = "Menu.robbi.put";
- private static final String MENU_ROBBI_TAKE = "Menu.robbi.take";
- private static final String MENU_ROBBI = "Menu.robbi";
- private static final String MENU_SIMULATION_RESET = "Menu.simulation.reset";
- private static final String MENU_SIMULATION_START = "Menu.simulation.start";
- private static final String MENU_SIMULATION_PAUSE = "Menu.simulation.pause";
- private static final String MENU_SIMULATION_STOP = "Menu.simulation.stop";
- private static final String MENU_SIMULATION = "Menu.simulation";
- private static final String MENU_WINDOW_LANGUAGE = "Menu.window.language";
- private static final String MENU_WINDOW_LANGUAGE_ENGLISH = "Menu.window.language.english";
- private static final String MENU_WINDOW_LANGUAGE_GERMAN = "Menu.window.language.german";
- private static final String MENU_WINDOW_CHANGECURSOR = "Menu.window.changeCursor";
- private static final String MENU_WINDOW = "Menu.window";
- private static final String MENU_WINDOW_DARKMODE = "Menu.window.darkmode";
- private static final String MENU_WINDOW_ENABLESOUNDS = "Menu.window.enableSounds";
- private static final String MENU_WINDOW_LIBRARIES = "Menu.window.libraries";
- private static final String MENU_WINDOW_INFO = "Menu.window.info";
-
- private static final String TOOLBAR_CONTROL_NEW = "Toolbar.control.new";
- private static final String TOOLBAR_CONTROL_LOAD = "Toolbar.control.load";
- private static final String TOOLBAR_CONTROL_SAVE = "Toolbar.control.save";
- private static final String TOOLBAR_CONTROL_COMPILE = "Toolbar.control.compile";
-
- private static final String TOOLBAR_TERRITORY_SIZE = "Toolbar.territory.size";
- private static final String TOOLBAR_TERRITORY_PLACEROBBI = "Toolbar.territory.placeRobbi";
- private static final String TOOLBAR_TERRITORY_PLACEHOLLOW = "Toolbar.territory.placeHollow";
- private static final String TOOLBAR_TERRITORY_PLACEPILEOFSCRAP = "Toolbar.territory.placePileOfScrap";
- private static final String TOOLBAR_TERRITORY_PLACESTOCKPILE = "Toolbar.territory.placeStockpile";
- private static final String TOOLBAR_TERRITORY_PLACEACCU = "Toolbar.territory.placeAccu";
- private static final String TOOLBAR_TERRITORY_PLACESCREW = "Toolbar.territory.placeScrew";
- private static final String TOOLBAR_TERRITORY_PLACENUT = "Toolbar.territory.placeNut";
- private static final String TOOLBAR_TERRITORY_DELETE = "Toolbar.territory.delete";
-
- private static final String TOOLBAR_ROBBI_TURNLEFT = "Toolbar.robbi.turnLeft";
- private static final String TOOLBAR_ROBBI_MOVE = "Toolbar.robbi.move";
- private static final String TOOLBAR_ROBBI_PUT = "Toolbar.robbi.put";
- private static final String TOOLBAR_ROBBI_TAKE = "Toolbar.robbi.take";
-
- private static final String TOOLBAR_ACTION_RESET = "Toolbar.action.reset";
- private static final String TOOLBAR_ACTION_START = "Toolbar.action.start";
- private static final String TOOLBAR_ACTION_PAUSE = "Toolbar.action.pause";
- private static final String TOOLBAR_ACTION_STOP = "Toolbar.action.stop";
- private static final String TOOLBAR_ACTION_SPEED = "Toolbar.action.speed";
-
- private static final String MENU_EXAMPLES = "Menu.examples";
- private static final String MENU_EXAMPLES_LOAD = "Menu.examples.load";
- private static final String MENU_EXAMPLES_SAVE = "Menu.examples.save";
- private static final String MENU_TUTOR_LOADREQUEST = "Menu.tutor.loadRequest";
- private static final String MENU_TUTOR_SAVEANSWER = "Menu.tutor.saveAnswer";
- private static final String MENU_TUTOR_SENDREQUEST = "Menu.tutor.sendRequest";
- private static final String MENU_TUTOR_RECEIVEANSWER = "Menu.tutor.receiveAnswer";
- private static final String MENU_TUTOR = "Menu.tutor";
-
- private static final String MAIN_TITLE = "Main.title";
-
- /**
- * Constructor to create a new LanguageController. Sets the actions to the
- * languageSelection and binds text to all graphical elements.
- *
- * @param mainStage the stage, this controller is for
- */
- public LanguageController(MainStage mainStage) {
- this.stage = mainStage;
-
- MenuBar menubar = mainStage.getMenubar();
-
- menubar.getGermanLanguageMenuItem().setOnAction(e -> {
- I18nUtils.setLocale(Locale.GERMANY);
- updateTitle();
- mainStage.getSnackbarController().showMessage(LANGUAGE_CHANGED);
- });
- menubar.getEnglishLanguageMenuItem().setOnAction(e -> {
- I18nUtils.setLocale(Locale.UK);
- updateTitle();
- mainStage.getSnackbarController().showMessage(LANGUAGE_CHANGED);
- });
-
- // text bindings
- menubar.getNewEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_NEW));
- menubar.getSaveEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_SAVE));
- menubar.getOpenEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_OPEN));
- menubar.getFormatSourceCodeMenuItem().textProperty().bind(createBinding(MENU_EDITOR_FORMAT));
- menubar.getCompileEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_COMPILE));
- menubar.getPrintEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_PRINT));
- menubar.getQuitEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_QUIT));
- menubar.getEditorMenu().textProperty().bind(createBinding(MENU_EDITOR));
-
- // territory Menu
- menubar.getSaveXMLTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVE_XML));
- menubar.getSaveJAXBTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVE_JAXB));
- menubar.getSaveSerialTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVE_SERIALIZE));
- menubar.getSaveTerritoryMenu().textProperty().bind(createBinding(MENU_TERRITORY_SAVE));
- menubar.getLoadXMLTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_LOAD_XML));
- menubar.getLoadJAXBTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_LOAD_JAXB));
- menubar.getLoadSerialTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_LOAD_DESERIALIZE));
- menubar.getLoadTerritoryMenu().textProperty().bind(createBinding(MENU_TERRITORY_LOAD));
- menubar.getSaveAsPNGMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVEASPIC_PNG));
- menubar.getSaveAsGifMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVEASPIC_GIF));
- menubar.getSaveAsPicMenu().textProperty().bind(createBinding(MENU_TERRITORY_SAVEASPIC));
- menubar.getPrintTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PRINT));
-
- menubar.getChangeSizeTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SIZE));
- menubar.getPlaceRobbiTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_ROBBI));
- menubar.getPlaceHollowTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_HOLLOW));
- menubar.getPlacePileOfScrapTerritoryRadioMenuItem().textProperty()
- .bind(createBinding(MENU_TERRITORY_PLACE_PILEOFSCRAP));
- menubar.getPlaceStockpileTerritoryRadioMenuItem().textProperty()
- .bind(createBinding(MENU_TERRITORY_PLACE_STOCKPILE));
- menubar.getPlaceAccuTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_ACCU));
- menubar.getPlaceScrewTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_SCREW));
- menubar.getPlaceNutTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_NUT));
- menubar.getDeleteFieldRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_DELETE));
- menubar.getTerritoryMenu().textProperty().bind(createBinding(MENU_TERRITORY));
-
- // robbi Menu
- menubar.getItemPresentMenuItem().textProperty().bind(createBinding(MENU_ROBBI_ITEMPRESENT));
- menubar.getIsStockpileMenuItem().textProperty().bind(createBinding(MENU_ROBBI_ISSTOCKPILE));
- menubar.getHollowAheadMenuItem().textProperty().bind(createBinding(MENU_ROBBI_HOLLOWAHEAD));
- menubar.getPileOfScrapAheadMenuItem().textProperty().bind(createBinding(MENU_ROBBI_PILEOFSCRAPAHEAD));
- menubar.getIsBagFullMenuItem().textProperty().bind(createBinding(MENU_ROBBI_ISBAGFULL));
- menubar.getPushPileOfScrapMenuItem().textProperty().bind(createBinding(MENU_ROBBI_PUSHPILEOFSCRAP));
- menubar.getMoveMenuItem().textProperty().bind(createBinding(MENU_ROBBI_MOVE));
- menubar.getTurnLeftMenuItem().textProperty().bind(createBinding(MENU_ROBBI_TURNLEFT));
- menubar.getPutMenuItem().textProperty().bind(createBinding(MENU_ROBBI_PUT));
- menubar.getTakeMenuItem().textProperty().bind(createBinding(MENU_ROBBI_TAKE));
- menubar.getRobbiMenu().textProperty().bind(createBinding(MENU_ROBBI));
-
- // simulation Menu
- menubar.getResetMenuItem().textProperty().bind(createBinding(MENU_SIMULATION_RESET));
- menubar.getStartMenuItem().textProperty().bind(createBinding(MENU_SIMULATION_START));
- menubar.getPauseMenuItem().textProperty().bind(createBinding(MENU_SIMULATION_PAUSE));
- menubar.getStopMenuItem().textProperty().bind(createBinding(MENU_SIMULATION_STOP));
- menubar.getSimulationMenu().textProperty().bind(createBinding(MENU_SIMULATION));
-
- // window Menu
- menubar.getLanguageMenu().textProperty().bind(createBinding(MENU_WINDOW_LANGUAGE));
- menubar.getEnglishLanguageMenuItem().textProperty().bind(createBinding(MENU_WINDOW_LANGUAGE_ENGLISH));
- menubar.getGermanLanguageMenuItem().textProperty().bind(createBinding(MENU_WINDOW_LANGUAGE_GERMAN));
- menubar.getChangeCursorMenuItem().textProperty().bind(createBinding(MENU_WINDOW_CHANGECURSOR));
- menubar.getWindowMenu().textProperty().bind(createBinding(MENU_WINDOW));
- menubar.getDarkModeMenuItem().textProperty().bind(createBinding(MENU_WINDOW_DARKMODE));
- menubar.getEnableSoundsMenuItem().textProperty().bind(createBinding(MENU_WINDOW_ENABLESOUNDS));
- menubar.getLibraryMenuItem().textProperty().bind(createBinding(MENU_WINDOW_LIBRARIES));
- menubar.getInfoMenuItem().textProperty().bind(createBinding(MENU_WINDOW_INFO));
-
- Toolbar toolbar = mainStage.getToolbar();
- // Tool bar
-
- toolbar.getNewButtonToolbar().setTooltip(createTooltip(TOOLBAR_CONTROL_NEW));
- toolbar.getLoadButtonToolbar().setTooltip(createTooltip(TOOLBAR_CONTROL_LOAD));
- toolbar.getSaveButtonToolbar().setTooltip(createTooltip(TOOLBAR_CONTROL_SAVE));
- toolbar.getCompileButtonToolbar().setTooltip(createTooltip(TOOLBAR_CONTROL_COMPILE));
-
- toolbar.getChangeSizeButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_SIZE));
- toolbar.getPlaceRobbiToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACEROBBI));
- toolbar.getPlaceHollowToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACEHOLLOW));
- toolbar.getPlacePileOfScrapToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACEPILEOFSCRAP));
- toolbar.getPlaceStockpileToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACESTOCKPILE));
- toolbar.getPlaceAccuToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACEACCU));
- toolbar.getPlaceScrewToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACESCREW));
- toolbar.getPlaceNutToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACENUT));
- toolbar.getDeleteFieldToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_DELETE));
-
- toolbar.getRobbiTurnLeftButtonToolbar().setTooltip(createTooltip(TOOLBAR_ROBBI_TURNLEFT));
- toolbar.getRobbiMoveButtonToolbar().setTooltip(createTooltip(TOOLBAR_ROBBI_MOVE));
- toolbar.getRobbiPutButtonToolbar().setTooltip(createTooltip(TOOLBAR_ROBBI_PUT));
- toolbar.getRobbiTakeButtonToolbar().setTooltip(createTooltip(TOOLBAR_ROBBI_TAKE));
-
- toolbar.getResetButtonToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_RESET));
- toolbar.getStartToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_START));
- toolbar.getPauseToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_PAUSE));
- toolbar.getStopToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_STOP));
- toolbar.getSpeedSliderToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_SPEED));
-
- menubar.getExamplesMenu().textProperty().bind(createBinding(MENU_EXAMPLES));
- menubar.getLoadExampleMenuItem().textProperty().bind(createBinding(MENU_EXAMPLES_LOAD));
- menubar.getSaveExampleMenuItem().textProperty().bind(createBinding(MENU_EXAMPLES_SAVE));
-
- if (PropertiesLoader.isTutor()) {
- menubar.getLoadRequestMenuItem().textProperty().bind(createBinding(MENU_TUTOR_LOADREQUEST));
- menubar.getSaveAnswerMenuItem().textProperty().bind(createBinding(MENU_TUTOR_SAVEANSWER));
- } else {
- menubar.getSendRequestMenuItem().textProperty().bind(createBinding(MENU_TUTOR_SENDREQUEST));
- menubar.getReceiveAnswerMenuItem().textProperty().bind(createBinding(MENU_TUTOR_RECEIVEANSWER));
- }
- menubar.getTutorMenu().textProperty().bind(createBinding(MENU_TUTOR));
- }
-
- /**
- * needed since the star (*) would mess with the binding property
- *
- * TODO use formatted String
- */
- public void updateTitle() {
- stage.setTitle(
- i18n(MAIN_TITLE) + ": " + stage.getProgram().getName() + (stage.getProgram().isEdited() ? "*" : ""));
- }
+ // language keys
+ private static final String LANGUAGE_CHANGED = "language.changed";
+ private static final String MENU_EDITOR_NEW = "Menu.editor.new";
+ private static final String MENU_EDITOR_SAVE = "Menu.editor.save";
+ private static final String MENU_EDITOR_OPEN = "Menu.editor.open";
+ private static final String MENU_EDITOR_FORMAT = "Menu.editor.format";
+ private static final String MENU_EDITOR_COMPILE = "Menu.editor.compile";
+ private static final String MENU_EDITOR_PRINT = "Menu.editor.print";
+ private static final String MENU_EDITOR_QUIT = "Menu.editor.quit";
+ private static final String MENU_EDITOR = "Menu.editor";
+ private static final String MENU_TERRITORY_SAVE_XML = "Menu.territory.save.xml";
+ private static final String MENU_TERRITORY_SAVE_JAXB = "Menu.territory.save.jaxb";
+ private static final String MENU_TERRITORY_SAVE_SERIALIZE = "Menu.territory.save.serialize";
+ private static final String MENU_TERRITORY_SAVE = "Menu.territory.save";
+ private static final String MENU_TERRITORY_LOAD_XML = "Menu.territory.load.xml";
+ private static final String MENU_TERRITORY_LOAD_JAXB = "Menu.territory.load.jaxb";
+ private static final String MENU_TERRITORY_LOAD_DESERIALIZE = "Menu.territory.load.deserialize";
+ private static final String MENU_TERRITORY_LOAD = "Menu.territory.load";
+ private static final String MENU_TERRITORY_SAVEASPIC_PNG = "Menu.territory.saveAsPic.png";
+ private static final String MENU_TERRITORY_SAVEASPIC_GIF = "Menu.territory.saveAsPic.gif";
+ private static final String MENU_TERRITORY_SAVEASPIC = "Menu.territory.saveAsPic";
+ private static final String MENU_TERRITORY_PRINT = "Menu.territory.print";
+ private static final String MENU_TERRITORY_SIZE = "Menu.territory.size";
+ private static final String MENU_TERRITORY_PLACE_ROBBI = "Menu.territory.place.robbi";
+ private static final String MENU_TERRITORY_PLACE_HOLLOW = "Menu.territory.place.hollow";
+ private static final String MENU_TERRITORY_PLACE_PILEOFSCRAP = "Menu.territory.place.pileOfScrap";
+ private static final String MENU_TERRITORY_PLACE_STOCKPILE = "Menu.territory.place.stockpile";
+ private static final String MENU_TERRITORY_PLACE_ACCU = "Menu.territory.place.accu";
+ private static final String MENU_TERRITORY_PLACE_SCREW = "Menu.territory.place.screw";
+ private static final String MENU_TERRITORY_PLACE_NUT = "Menu.territory.place.nut";
+ private static final String MENU_TERRITORY_DELETE = "Menu.territory.delete";
+ private static final String MENU_TERRITORY = "Menu.territory";
+ private static final String MENU_ROBBI_ITEMPRESENT = "Menu.robbi.itemPresent";
+ private static final String MENU_ROBBI_ISSTOCKPILE = "Menu.robbi.isStockpile";
+ private static final String MENU_ROBBI_HOLLOWAHEAD = "Menu.robbi.hollowAhead";
+ private static final String MENU_ROBBI_PILEOFSCRAPAHEAD = "Menu.robbi.pileOfScrapAhead";
+ private static final String MENU_ROBBI_ISBAGFULL = "Menu.robbi.isBagFull";
+ private static final String MENU_ROBBI_PUSHPILEOFSCRAP = "Menu.robbi.pushPileOfScrap";
+ private static final String MENU_ROBBI_MOVE = "Menu.robbi.move";
+ private static final String MENU_ROBBI_TURNLEFT = "Menu.robbi.turnLeft";
+ private static final String MENU_ROBBI_PUT = "Menu.robbi.put";
+ private static final String MENU_ROBBI_TAKE = "Menu.robbi.take";
+ private static final String MENU_ROBBI = "Menu.robbi";
+ private static final String MENU_SIMULATION_RESET = "Menu.simulation.reset";
+ private static final String MENU_SIMULATION_START = "Menu.simulation.start";
+ private static final String MENU_SIMULATION_PAUSE = "Menu.simulation.pause";
+ private static final String MENU_SIMULATION_STOP = "Menu.simulation.stop";
+ private static final String MENU_SIMULATION = "Menu.simulation";
+ private static final String MENU_WINDOW_LANGUAGE = "Menu.window.language";
+ private static final String MENU_WINDOW_LANGUAGE_ENGLISH = "Menu.window.language.english";
+ private static final String MENU_WINDOW_LANGUAGE_GERMAN = "Menu.window.language.german";
+ private static final String MENU_WINDOW_CHANGECURSOR = "Menu.window.changeCursor";
+ private static final String MENU_WINDOW = "Menu.window";
+ private static final String MENU_WINDOW_DARKMODE = "Menu.window.darkmode";
+ private static final String MENU_WINDOW_ENABLESOUNDS = "Menu.window.enableSounds";
+ private static final String MENU_WINDOW_LIBRARIES = "Menu.window.libraries";
+ private static final String MENU_WINDOW_INFO = "Menu.window.info";
+ private static final String TOOLBAR_CONTROL_NEW = "Toolbar.control.new";
+ private static final String TOOLBAR_CONTROL_LOAD = "Toolbar.control.load";
+ private static final String TOOLBAR_CONTROL_SAVE = "Toolbar.control.save";
+ private static final String TOOLBAR_CONTROL_COMPILE = "Toolbar.control.compile";
+ private static final String TOOLBAR_TERRITORY_SIZE = "Toolbar.territory.size";
+ private static final String TOOLBAR_TERRITORY_PLACEROBBI = "Toolbar.territory.placeRobbi";
+ private static final String TOOLBAR_TERRITORY_PLACEHOLLOW = "Toolbar.territory.placeHollow";
+ private static final String TOOLBAR_TERRITORY_PLACEPILEOFSCRAP = "Toolbar.territory.placePileOfScrap";
+ private static final String TOOLBAR_TERRITORY_PLACESTOCKPILE = "Toolbar.territory.placeStockpile";
+ private static final String TOOLBAR_TERRITORY_PLACEACCU = "Toolbar.territory.placeAccu";
+ private static final String TOOLBAR_TERRITORY_PLACESCREW = "Toolbar.territory.placeScrew";
+ private static final String TOOLBAR_TERRITORY_PLACENUT = "Toolbar.territory.placeNut";
+ private static final String TOOLBAR_TERRITORY_DELETE = "Toolbar.territory.delete";
+ private static final String TOOLBAR_ROBBI_TURNLEFT = "Toolbar.robbi.turnLeft";
+ private static final String TOOLBAR_ROBBI_MOVE = "Toolbar.robbi.move";
+ private static final String TOOLBAR_ROBBI_PUT = "Toolbar.robbi.put";
+ private static final String TOOLBAR_ROBBI_TAKE = "Toolbar.robbi.take";
+ private static final String TOOLBAR_ACTION_RESET = "Toolbar.action.reset";
+ private static final String TOOLBAR_ACTION_START = "Toolbar.action.start";
+ private static final String TOOLBAR_ACTION_PAUSE = "Toolbar.action.pause";
+ private static final String TOOLBAR_ACTION_STOP = "Toolbar.action.stop";
+ private static final String TOOLBAR_ACTION_SPEED = "Toolbar.action.speed";
+ private static final String MENU_EXAMPLES = "Menu.examples";
+ private static final String MENU_EXAMPLES_LOAD = "Menu.examples.load";
+ private static final String MENU_EXAMPLES_SAVE = "Menu.examples.save";
+ private static final String MENU_TUTOR_LOADREQUEST = "Menu.tutor.loadRequest";
+ private static final String MENU_TUTOR_SAVEANSWER = "Menu.tutor.saveAnswer";
+ private static final String MENU_TUTOR_SENDREQUEST = "Menu.tutor.sendRequest";
+ private static final String MENU_TUTOR_RECEIVEANSWER = "Menu.tutor.receiveAnswer";
+ private static final String MENU_TUTOR = "Menu.tutor";
+ private static final String MAIN_TITLE = "Main.title";
+ private final MainStage stage;
+
+ /**
+ * Constructor to create a new LanguageController. Sets the actions to the
+ * languageSelection and binds text to all graphical elements.
+ *
+ * @param mainStage the stage, this controller is for
+ */
+ public LanguageController(MainStage mainStage) {
+ this.stage = mainStage;
+
+ MenuBar menubar = mainStage.getMenubar();
+
+ menubar.getGermanLanguageMenuItem().setOnAction(e -> {
+ I18nUtils.setLocale(Locale.GERMANY);
+ updateTitle();
+ mainStage.getNotificationController().showMessage(3000, LANGUAGE_CHANGED);
+ });
+ menubar.getEnglishLanguageMenuItem().setOnAction(e -> {
+ I18nUtils.setLocale(Locale.UK);
+ updateTitle();
+ mainStage.getNotificationController().showMessage(3000, LANGUAGE_CHANGED);
+ });
+
+ // text bindings
+ menubar.getNewEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_NEW));
+ menubar.getSaveEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_SAVE));
+ menubar.getOpenEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_OPEN));
+ menubar.getFormatSourceCodeMenuItem().textProperty().bind(createBinding(MENU_EDITOR_FORMAT));
+ menubar.getCompileEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_COMPILE));
+ menubar.getPrintEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_PRINT));
+ menubar.getQuitEditorMenuItem().textProperty().bind(createBinding(MENU_EDITOR_QUIT));
+ menubar.getEditorMenu().textProperty().bind(createBinding(MENU_EDITOR));
+
+ // territory Menu
+ menubar.getSaveXMLTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVE_XML));
+ menubar.getSaveJAXBTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVE_JAXB));
+ menubar.getSaveSerialTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVE_SERIALIZE));
+ menubar.getSaveTerritoryMenu().textProperty().bind(createBinding(MENU_TERRITORY_SAVE));
+ menubar.getLoadXMLTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_LOAD_XML));
+ menubar.getLoadJAXBTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_LOAD_JAXB));
+ menubar.getLoadSerialTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_LOAD_DESERIALIZE));
+ menubar.getLoadTerritoryMenu().textProperty().bind(createBinding(MENU_TERRITORY_LOAD));
+ menubar.getSaveAsPNGMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVEASPIC_PNG));
+ menubar.getSaveAsGifMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SAVEASPIC_GIF));
+ menubar.getSaveAsPicMenu().textProperty().bind(createBinding(MENU_TERRITORY_SAVEASPIC));
+ menubar.getPrintTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PRINT));
+
+ menubar.getChangeSizeTerritoryMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_SIZE));
+ menubar.getPlaceRobbiTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_ROBBI));
+ menubar.getPlaceHollowTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_HOLLOW));
+ menubar.getPlacePileOfScrapTerritoryRadioMenuItem().textProperty()
+ .bind(createBinding(MENU_TERRITORY_PLACE_PILEOFSCRAP));
+ menubar.getPlaceStockpileTerritoryRadioMenuItem().textProperty()
+ .bind(createBinding(MENU_TERRITORY_PLACE_STOCKPILE));
+ menubar.getPlaceAccuTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_ACCU));
+ menubar.getPlaceScrewTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_SCREW));
+ menubar.getPlaceNutTerritoryRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_PLACE_NUT));
+ menubar.getDeleteFieldRadioMenuItem().textProperty().bind(createBinding(MENU_TERRITORY_DELETE));
+ menubar.getTerritoryMenu().textProperty().bind(createBinding(MENU_TERRITORY));
+
+ // robbi Menu
+ menubar.getItemPresentMenuItem().textProperty().bind(createBinding(MENU_ROBBI_ITEMPRESENT));
+ menubar.getIsStockpileMenuItem().textProperty().bind(createBinding(MENU_ROBBI_ISSTOCKPILE));
+ menubar.getHollowAheadMenuItem().textProperty().bind(createBinding(MENU_ROBBI_HOLLOWAHEAD));
+ menubar.getPileOfScrapAheadMenuItem().textProperty().bind(createBinding(MENU_ROBBI_PILEOFSCRAPAHEAD));
+ menubar.getIsBagFullMenuItem().textProperty().bind(createBinding(MENU_ROBBI_ISBAGFULL));
+ menubar.getPushPileOfScrapMenuItem().textProperty().bind(createBinding(MENU_ROBBI_PUSHPILEOFSCRAP));
+ menubar.getMoveMenuItem().textProperty().bind(createBinding(MENU_ROBBI_MOVE));
+ menubar.getTurnLeftMenuItem().textProperty().bind(createBinding(MENU_ROBBI_TURNLEFT));
+ menubar.getPutMenuItem().textProperty().bind(createBinding(MENU_ROBBI_PUT));
+ menubar.getTakeMenuItem().textProperty().bind(createBinding(MENU_ROBBI_TAKE));
+ menubar.getRobbiMenu().textProperty().bind(createBinding(MENU_ROBBI));
+
+ // simulation Menu
+ menubar.getResetMenuItem().textProperty().bind(createBinding(MENU_SIMULATION_RESET));
+ menubar.getStartMenuItem().textProperty().bind(createBinding(MENU_SIMULATION_START));
+ menubar.getPauseMenuItem().textProperty().bind(createBinding(MENU_SIMULATION_PAUSE));
+ menubar.getStopMenuItem().textProperty().bind(createBinding(MENU_SIMULATION_STOP));
+ menubar.getSimulationMenu().textProperty().bind(createBinding(MENU_SIMULATION));
+
+ // window Menu
+ menubar.getLanguageMenu().textProperty().bind(createBinding(MENU_WINDOW_LANGUAGE));
+ menubar.getEnglishLanguageMenuItem().textProperty().bind(createBinding(MENU_WINDOW_LANGUAGE_ENGLISH));
+ menubar.getGermanLanguageMenuItem().textProperty().bind(createBinding(MENU_WINDOW_LANGUAGE_GERMAN));
+ menubar.getChangeCursorMenuItem().textProperty().bind(createBinding(MENU_WINDOW_CHANGECURSOR));
+ menubar.getWindowMenu().textProperty().bind(createBinding(MENU_WINDOW));
+ menubar.getDarkModeMenuItem().textProperty().bind(createBinding(MENU_WINDOW_DARKMODE));
+ menubar.getEnableSoundsMenuItem().textProperty().bind(createBinding(MENU_WINDOW_ENABLESOUNDS));
+ menubar.getLibraryMenuItem().textProperty().bind(createBinding(MENU_WINDOW_LIBRARIES));
+ menubar.getInfoMenuItem().textProperty().bind(createBinding(MENU_WINDOW_INFO));
+
+ Toolbar toolbar = mainStage.getToolbar();
+ // Tool bar
+
+ toolbar.getNewButtonToolbar().setTooltip(createTooltip(TOOLBAR_CONTROL_NEW));
+ toolbar.getLoadButtonToolbar().setTooltip(createTooltip(TOOLBAR_CONTROL_LOAD));
+ toolbar.getSaveButtonToolbar().setTooltip(createTooltip(TOOLBAR_CONTROL_SAVE));
+ toolbar.getCompileButtonToolbar().setTooltip(createTooltip(TOOLBAR_CONTROL_COMPILE));
+
+ toolbar.getChangeSizeButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_SIZE));
+ toolbar.getPlaceRobbiToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACEROBBI));
+ toolbar.getPlaceHollowToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACEHOLLOW));
+ toolbar.getPlacePileOfScrapToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACEPILEOFSCRAP));
+ toolbar.getPlaceStockpileToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACESTOCKPILE));
+ toolbar.getPlaceAccuToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACEACCU));
+ toolbar.getPlaceScrewToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACESCREW));
+ toolbar.getPlaceNutToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_PLACENUT));
+ toolbar.getDeleteFieldToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_TERRITORY_DELETE));
+
+ toolbar.getRobbiTurnLeftButtonToolbar().setTooltip(createTooltip(TOOLBAR_ROBBI_TURNLEFT));
+ toolbar.getRobbiMoveButtonToolbar().setTooltip(createTooltip(TOOLBAR_ROBBI_MOVE));
+ toolbar.getRobbiPutButtonToolbar().setTooltip(createTooltip(TOOLBAR_ROBBI_PUT));
+ toolbar.getRobbiTakeButtonToolbar().setTooltip(createTooltip(TOOLBAR_ROBBI_TAKE));
+
+ toolbar.getResetButtonToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_RESET));
+ toolbar.getStartToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_START));
+ toolbar.getPauseToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_PAUSE));
+ toolbar.getStopToggleButtonToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_STOP));
+ toolbar.getSpeedSliderToolbar().setTooltip(createTooltip(TOOLBAR_ACTION_SPEED));
+
+ menubar.getExamplesMenu().textProperty().bind(createBinding(MENU_EXAMPLES));
+ menubar.getLoadExampleMenuItem().textProperty().bind(createBinding(MENU_EXAMPLES_LOAD));
+ menubar.getSaveExampleMenuItem().textProperty().bind(createBinding(MENU_EXAMPLES_SAVE));
+
+ if (PropertiesLoader.isTutor()) {
+ menubar.getLoadRequestMenuItem().textProperty().bind(createBinding(MENU_TUTOR_LOADREQUEST));
+ menubar.getSaveAnswerMenuItem().textProperty().bind(createBinding(MENU_TUTOR_SAVEANSWER));
+ } else {
+ menubar.getSendRequestMenuItem().textProperty().bind(createBinding(MENU_TUTOR_SENDREQUEST));
+ menubar.getReceiveAnswerMenuItem().textProperty().bind(createBinding(MENU_TUTOR_RECEIVEANSWER));
+ }
+ menubar.getTutorMenu().textProperty().bind(createBinding(MENU_TUTOR));
+ }
+
+ /**
+ * needed since the star (*) would mess with the binding property
+ *
+ * TODO use formatted String
+ */
+ public void updateTitle() {
+ stage.setTitle(
+ i18n(MAIN_TITLE) + ": " + stage.getProgram().getName() + (stage.getProgram().isEdited() ? "*" : ""));
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/MainStageController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/MainStageController.java
index 082cbe0..4556a9d 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/MainStageController.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/MainStageController.java
@@ -1,36 +1,13 @@
package com.JayPi4c.RobbiSimulator.controller;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
-
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-
-import javax.imageio.ImageIO;
-
-import org.apache.logging.log4j.Logger;
-import org.hibernate.Version;
-
import com.JayPi4c.RobbiSimulator.controller.program.Program;
import com.JayPi4c.RobbiSimulator.controller.program.ProgramController;
-import com.JayPi4c.RobbiSimulator.model.BagIsEmptyException;
-import com.JayPi4c.RobbiSimulator.model.BagIsFullException;
-import com.JayPi4c.RobbiSimulator.model.HollowAheadException;
-import com.JayPi4c.RobbiSimulator.model.NoItemException;
-import com.JayPi4c.RobbiSimulator.model.NoPileOfScrapAheadException;
-import com.JayPi4c.RobbiSimulator.model.TileBlockedException;
-import com.JayPi4c.RobbiSimulator.model.TileIsFullException;
-import com.JayPi4c.RobbiSimulator.utils.AlertHelper;
-import com.JayPi4c.RobbiSimulator.utils.Observable;
-import com.JayPi4c.RobbiSimulator.utils.Observer;
-import com.JayPi4c.RobbiSimulator.utils.SceneManager;
-import com.JayPi4c.RobbiSimulator.utils.SoundManager;
+import com.JayPi4c.RobbiSimulator.model.*;
+import com.JayPi4c.RobbiSimulator.utils.*;
import com.JayPi4c.RobbiSimulator.view.MainStage;
import com.JayPi4c.RobbiSimulator.view.MenuBar;
import com.JayPi4c.RobbiSimulator.view.TerritoryPanel;
import com.JayPi4c.RobbiSimulator.view.Toolbar;
-import com.jfoenix.utils.JFXUtilities;
-
import eu.mihosoft.monacofx.MonacoFX;
import jakarta.xml.bind.JAXBContext;
import javafx.embed.swing.SwingFXUtils;
@@ -53,430 +30,434 @@
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.Logger;
+import org.hibernate.Version;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
/**
* This controller contains all the settings for the mainStage
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
public class MainStageController implements Observer {
- private ButtonState buttonState;
-
- private MainStage mainStage;
-
- @Setter
- private boolean changeCursor = false;
- @Getter
- private boolean soundsEnabled = false;
-
- private RadioMenuItem selectedRadioMenuItem = null;
-
- /**
- * Creates a new MainStageController and sets all the actions for the buttons in
- * the mainStage
- *
- * @param mainStage the mainStage for this controller
- * @param buttonState the buttonState for this controller
- */
- public MainStageController(MainStage mainStage, ButtonState buttonState) {
- this.mainStage = mainStage;
- this.buttonState = buttonState;
- this.mainStage.getProgram().addObserver(this);
-
- mainStage.setTitle(i18n("Main.title") + ": " + mainStage.getProgram().getName());
-
- mainStage.setOnCloseRequest(e -> {
- mainStage.getProgram().save(mainStage.getTextArea().getEditor().getDocument().getText());
- ProgramController.close(mainStage.getProgram().getName());
- });
-
- MenuBar menuBar = mainStage.getMenubar();
-
- // editor (menuBar)
- menuBar.getNewEditorMenuItem().setOnAction(e -> ProgramController.createAndShow(mainStage));
- menuBar.getOpenEditorMenuItem().setOnAction(e -> ProgramController.openProgram(mainStage));
- menuBar.getSaveEditorMenuItem().setOnAction(e -> {
- mainStage.getProgram().save(mainStage.getTextArea().getEditor().getDocument().getText());
- mainStage.setTitle(getTitle(mainStage.getProgram()));
- });
-
- menuBar.getFormatSourceCodeMenuItem().setOnAction(e -> {
- mainStage.getSnackbarController().showMessage("not.implemented");
- // For this the following PR should first be merged:
- // https://github.com/miho/MonacoFX/pull/25
- });
-
- menuBar.getCompileEditorMenuItem().setOnAction(e -> {
- mainStage.getSimulationController().stopSimulation();
- Program program = mainStage.getProgram();
- program.save(mainStage.getTextArea().getEditor().getDocument().getText());
- mainStage.setTitle(getTitle(program));
- ProgramController.compile(program, mainStage);
- });
- // TODO print editor content
- menuBar.getPrintEditorMenuItem()
- .setOnAction(e -> mainStage.getSnackbarController().showMessage("not.implemented"));
- menuBar.getQuitEditorMenuItem().setOnAction(e -> {
- Program program = mainStage.getProgram();
- logger.info("exiting {}", program.getName());
- program.save(mainStage.getTextArea().getEditor().getDocument().getText());
- ProgramController.close(program.getName());
- mainStage.close();
- });
- // Territory (menuBar)
- // save -> TerritorySaveController
- menuBar.getSaveAsPNGMenuItem().setOnAction(e -> {
- String extension = ".png";
- File file = getFile(i18n("Menu.territory.saveAsPic.png.description"), extension);
- if (file == null)
- return;
-
- if (!saveAsImage(file, extension)) {
- mainStage.getSnackbarController().showMessage("Menu.territory.saveAsPic.error");
- }
- });
- menuBar.getSaveAsGifMenuItem().setOnAction(e -> {
- String extension = ".gif";
- File file = getFile(i18n("Menu.territory.saveAsPic.gif.description"), extension);
- if (file == null)
- return;
-
- if (!saveAsImage(file, extension)) {
- mainStage.getSnackbarController().showMessage("Menu.territory.saveAsPic.error");
- }
- });
- menuBar.getPrintTerritoryMenuItem().setOnAction(e -> printTerritory());
- menuBar.getChangeSizeTerritoryMenuItem()
- .setOnAction(new ChangeTerritorySizeHandler(mainStage, mainStage.getTerritory()));
-
- menuBar.getPlaceRobbiTerritoryRadioMenuItem()
- .setOnAction(getRadioHandler(MainStage.menuRobbiImage, ButtonState.ROBBI));
- menuBar.getPlaceHollowTerritoryRadioMenuItem()
- .setOnAction(getRadioHandler(MainStage.menuHollowImage, ButtonState.HOLLOW));
- menuBar.getPlacePileOfScrapTerritoryRadioMenuItem()
- .setOnAction(getRadioHandler(MainStage.menuPileOfScrapImage, ButtonState.PILE_OF_SCRAP));
- menuBar.getPlaceStockpileTerritoryRadioMenuItem()
- .setOnAction(getRadioHandler(MainStage.menuStockpileImage, ButtonState.STOCKPILE));
- menuBar.getPlaceAccuTerritoryRadioMenuItem()
- .setOnAction(getRadioHandler(MainStage.menuAccuImage, ButtonState.ACCU));
- menuBar.getPlaceScrewTerritoryRadioMenuItem()
- .setOnAction(getRadioHandler(MainStage.menuScrewImage, ButtonState.SCREW));
- menuBar.getPlaceNutTerritoryRadioMenuItem()
- .setOnAction(getRadioHandler(MainStage.menuNutImage, ButtonState.NUT));
- menuBar.getDeleteFieldRadioMenuItem()
- .setOnAction(getRadioHandler(MainStage.menuDeleteImage, ButtonState.CLEAR));
- // Robbi (menuBar)
- menuBar.getMoveMenuItem().setOnAction(e -> {
- try {
- mainStage.getTerritory().getRobbi().vor();
- } catch (HollowAheadException ex) {
- mainStage.getSnackbarController().showMessage(ex.getMessage());
- }
- });
- menuBar.getTurnLeftMenuItem().setOnAction(e -> mainStage.getTerritory().getRobbi().linksUm());
- menuBar.getPutMenuItem().setOnAction(e -> {
- try {
- mainStage.getTerritory().getRobbi().legeAb();
- } catch (BagIsEmptyException | TileIsFullException ex) {
- mainStage.getSnackbarController().showMessage(ex.getMessage());
- }
- });
- menuBar.getTakeMenuItem().setOnAction(e -> {
- try {
- mainStage.getTerritory().getRobbi().nehmeAuf();
- } catch (NoItemException | BagIsFullException ex) {
- mainStage.getSnackbarController().showMessage(ex.getMessage());
- }
- });
- menuBar.getPushPileOfScrapMenuItem().setOnAction(e -> {
- try {
- mainStage.getTerritory().getRobbi().schiebeSchrotthaufen();
- } catch (NoPileOfScrapAheadException | TileBlockedException ex) {
- mainStage.getSnackbarController().showMessage(ex.getMessage());
- }
- });
-
- menuBar.getItemPresentMenuItem().setOnAction(e -> {
- boolean itemPresent = mainStage.getTerritory().getRobbi().gegenstandDa();
- mainStage.getSnackbarController().showMessage("Execution.information.itemPresent", itemPresent);
- });
- menuBar.getIsStockpileMenuItem().setOnAction(e -> {
- boolean stockpilePresent = mainStage.getTerritory().getRobbi().istLagerplatz();
- mainStage.getSnackbarController().showMessage("Execution.information.stockpile", stockpilePresent);
- });
- menuBar.getHollowAheadMenuItem().setOnAction(e -> {
- boolean hollowAhead = mainStage.getTerritory().getRobbi().vornKuhle();
- mainStage.getSnackbarController().showMessage("Execution.information.hollow", hollowAhead);
- });
- menuBar.getPileOfScrapAheadMenuItem().setOnAction(e -> {
- boolean pileOfScrapAhead = mainStage.getTerritory().getRobbi().vornSchrotthaufen();
- mainStage.getSnackbarController().showMessage("Execution.information.pileOfScrap", pileOfScrapAhead);
- });
- menuBar.getIsBagFullMenuItem().setOnAction(e -> {
- boolean isBagFull = mainStage.getTerritory().getRobbi().istTascheVoll();
- mainStage.getSnackbarController().showMessage("Execution.information.bag", isBagFull);
- });
-
- // simulation (menuBar) -> SimualtionController
- // examples (menuBar) -> ExamplesController
- // tutor (menuBar) -> TutorController / StudentController
- // window (menuBar)
- // language -> LangaugeController
-
- menuBar.getChangeCursorMenuItem().setOnAction(e -> {
- setChangeCursor(menuBar.getChangeCursorMenuItem().isSelected());
- if (!menuBar.getChangeCursorMenuItem().isSelected())
- mainStage.getScene().setCursor(Cursor.DEFAULT);
- });
- menuBar.getDarkModeMenuItem().selectedProperty().bindBidirectional(SceneManager.darkmodeProperty());
- SceneManager.darkmodeProperty().addListener((obs, oldVal, newVal) -> {
- if (Boolean.TRUE.equals(newVal)) {
- mainStage.getScene().getStylesheets().add(SceneManager.getDarkmodeCss());
- mainStage.getTextArea().getEditor().setCurrentTheme("vs-dark");
- } else {
- mainStage.getScene().getStylesheets().remove(SceneManager.getDarkmodeCss());
- mainStage.getTextArea().getEditor().setCurrentTheme("vs-light");
- }
- });
- if (SceneManager.getDarkmode()) {
- mainStage.getScene().getStylesheets().add(SceneManager.getDarkmodeCss());
- mainStage.getTextArea().getEditor().setCurrentTheme("vs-dark");
- }
- menuBar.getEnableSoundsMenuItem().selectedProperty().bindBidirectional(SoundManager.soundProperty());
- menuBar.getInfoMenuItem()
- .setOnAction(e -> AlertHelper.showAlertAndWait(AlertType.INFORMATION, i18n("Menu.window.info.content"),
- mainStage, Modality.WINDOW_MODAL, i18n("Menu.window.info.title"),
- i18n("Menu.window.info.header")));
- menuBar.getLibraryMenuItem().setOnAction(e -> {
- String javaFxVersion = System.getProperty("javafx.version");
- String javaVersion = System.getProperty("java.version");
- String derbyVersion = "10.x"; // TODO: read info from derby's info.properties
- String jaxbVersion = JAXBContext.class.getPackage().getImplementationVersion();
- String hibernateVersion = Version.getVersionString();
- String lombokVersion = Generated.class.getPackage().getImplementationVersion();
- String log4jVersion = Logger.class.getPackage().getImplementationVersion();
- String jfoenixVersion = JFXUtilities.class.getPackage().getImplementationVersion();
- String monacoFxVersion = MonacoFX.class.getPackage().getImplementationVersion();
- AlertHelper.showAlertAndWait(AlertType.INFORMATION,
- i18n("Menu.window.libraries.content", javaVersion, javaFxVersion, jfoenixVersion, monacoFxVersion,
- derbyVersion, jaxbVersion, hibernateVersion, log4jVersion, lombokVersion),
- mainStage, Modality.WINDOW_MODAL, i18n("Menu.window.libraries.title"),
- i18n("Menu.window.libraries.header"));
- });
-
- Toolbar toolbar = mainStage.getToolbar();
-
- // Editor (toolbar)
- toolbar.getNewButtonToolbar().onActionProperty().bind(menuBar.getNewEditorMenuItem().onActionProperty());
- toolbar.getLoadButtonToolbar().onActionProperty().bind(menuBar.getOpenEditorMenuItem().onActionProperty());
- toolbar.getSaveButtonToolbar().onActionProperty().bind(menuBar.getSaveEditorMenuItem().onActionProperty());
- toolbar.getCompileButtonToolbar().onActionProperty()
- .bind(menuBar.getCompileEditorMenuItem().onActionProperty());
- // Territory (toolbar)
- toolbar.getChangeSizeButtonToolbar().onActionProperty()
- .bind(menuBar.getChangeSizeTerritoryMenuItem().onActionProperty());
- toolbar.getPlaceRobbiToggleButtonToolbar()
- .setOnAction(getButtonHandler(MainStage.menuRobbiImage, ButtonState.ROBBI));
- toolbar.getPlaceHollowToggleButtonToolbar()
- .setOnAction(getButtonHandler(MainStage.menuHollowImage, ButtonState.HOLLOW));
- toolbar.getPlacePileOfScrapToggleButtonToolbar()
- .setOnAction(getButtonHandler(MainStage.menuPileOfScrapImage, ButtonState.PILE_OF_SCRAP));
- toolbar.getPlaceStockpileToggleButtonToolbar()
- .setOnAction(getButtonHandler(MainStage.menuStockpileImage, ButtonState.STOCKPILE));
- toolbar.getPlaceAccuToggleButtonToolbar()
- .setOnAction(getButtonHandler(MainStage.menuAccuImage, ButtonState.ACCU));
- toolbar.getPlaceScrewToggleButtonToolbar()
- .setOnAction(getButtonHandler(MainStage.menuScrewImage, ButtonState.SCREW));
- toolbar.getPlaceNutToggleButtonToolbar().setOnAction(getButtonHandler(MainStage.menuNutImage, ButtonState.NUT));
- toolbar.getDeleteFieldToggleButtonToolbar()
- .setOnAction(getButtonHandler(MainStage.menuDeleteImage, ButtonState.CLEAR));
- // Robbi (Toolbar)
- toolbar.getRobbiMoveButtonToolbar().onActionProperty().bind(menuBar.getMoveMenuItem().onActionProperty());
- toolbar.getRobbiTurnLeftButtonToolbar().onActionProperty()
- .bind(menuBar.getTurnLeftMenuItem().onActionProperty());
- toolbar.getRobbiPutButtonToolbar().onActionProperty().bind(menuBar.getPutMenuItem().onActionProperty());
- toolbar.getRobbiTakeButtonToolbar().onActionProperty().bind(menuBar.getTakeMenuItem().onActionProperty());
- // Simulation (Toolbar) -> SimulationController
-
- // editor Panel
- mainStage.getTextArea().getEditor().getDocument().textProperty().addListener((observalble, oldVal, newVal) -> {
- Program program = mainStage.getProgram();
- boolean before = program.isEdited();
- program.setEdited(!newVal.equals(program.getEditorContent()));
- if (before != program.isEdited())
- mainStage.setTitle(getTitle(program));
- });
-
- }
-
- /**
- * Saves the current territoryPanel in the given file with the given extension.
- * If the file does not have the correct extension, the given extension will be
- * appended to the files name.
- *
- * @param file The file the image should be written into
- * @param extension The image extension
- * @return false, if the creation failed, true otherwise
- */
- private boolean saveAsImage(File file, String extension) {
-
- if (!file.getName().endsWith(extension)) {
- file = new File(file.getAbsolutePath() + extension);
- }
-
- TerritoryPanel tPanel = mainStage.getTerritoryPanel();
- WritableImage snapshot = tPanel.snapshot(new SnapshotParameters(), null);
-
- BufferedImage bufferedImage = new BufferedImage((int) tPanel.getWidth(), (int) tPanel.getHeight(),
- BufferedImage.TYPE_INT_ARGB);
-
- BufferedImage image = SwingFXUtils.fromFXImage(snapshot, bufferedImage);
- try {
- logger.info("Saving territory to {}", file);
- if (!ImageIO.write(image, extension.substring(1), file))
- logger.debug("Failed to find appropiate ImageWriter");
-
- } catch (IOException e) {
- logger.info("Failed to save territory as image");
- return false;
- }
- return true;
- }
-
- /**
- * Opens a FileChooser in the default programs folder and asks the user to
- * select or save a file to save an image.
- *
- * @param description the description for the extension
- * @param extension the file-extension
- * @return the selected file, null otherwise
- */
- private File getFile(String description, String extension) {
- FileChooser chooser = new FileChooser();
- chooser.setInitialDirectory(new File(ProgramController.PATH_TO_PROGRAMS));
- chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(description, "*" + extension));
- return chooser.showSaveDialog(mainStage);
- }
-
- /**
- * Gets the title for the application by the corresponding program
- *
- * @param program The program for the current instance
- * @return the name of the application include a * at the end, if the program
- * has unsaved changes
- */
- private String getTitle(Program program) {
- StringBuilder builder = new StringBuilder();
- builder.append(i18n("Main.title")).append(": ").append(program.getName())
- .append((program.isEdited() ? "*" : ""));
- return builder.toString();
- }
-
- /**
- * Sends the territory to a printer in order to print it.
- */
- private void printTerritory() {
-
- PrinterJob printerJob = PrinterJob.createPrinterJob();
-
- if (printerJob != null) {
- boolean flag = printerJob.showPrintDialog(mainStage);
- if (!flag)
- return;
- TerritoryPanel node = mainStage.getTerritoryPanel();
-
- // scale the node
- // https://www.tabnine.com/code/java/methods/javafx.print.PageLayout/getPrintableWidth
- PageLayout pageLayout = printerJob.getJobSettings().getPageLayout();
- double scaleX = 1.0;
- if (pageLayout.getPrintableWidth() < node.getBoundsInParent().getWidth()) {
- scaleX = pageLayout.getPrintableWidth() / node.getBoundsInParent().getWidth();
- }
- double scaleY = 1.0;
- if (pageLayout.getPrintableHeight() < node.getBoundsInParent().getHeight()) {
- scaleY = pageLayout.getPrintableHeight() / node.getBoundsInParent().getHeight();
- }
- double scaleXY = Double.min(scaleX, scaleY);
- Scale scale = new Scale(scaleXY, scaleXY);
- node.getTransforms().add(scale);
- // Print the node
- flag = printerJob.printPage(node);
- node.getTransforms().remove(scale);
- if (flag) {
- // End the printer job
- if (!printerJob.endJob()) {
- logger.debug("Could not end printerJob");
- }
- } else {
- logger.info("Printing failed or cancled");
- }
- } else {
- logger.info("Failed to create printerJob");
- AlertHelper.showAlertAndWait(AlertType.ERROR, i18n("Menu.territory.print.error"), mainStage);
- }
- }
-
- /**
- * Creates an EventHandler for the Toolbar buttons. This EventHandlers are only
- * usable for the buttons which allow to interact with the territory, e.g.
- * placing something into the territory or removing items from it.
- *
- * @param img The image, the cursor should change to, if the button is pressed
- * @param index the buttonIndex, the buttonState should change to if the button
- * is pressed
- * @return the eventHandler for the Toolbar button
- */
- private EventHandler getButtonHandler(Image img, int index) {
- return e -> {
- if (((ToggleButton) (e.getSource())).isSelected()) {
- if (changeCursor && img != null)
- mainStage.getMainStageScene().setCursor(new ImageCursor(img));
- buttonState.setSelected(index);
- } else {
- if (changeCursor)
- mainStage.getMainStageScene().setCursor(Cursor.DEFAULT);
- buttonState.deselect();
- }
- };
- }
-
- /**
- * Creates an EventHandler for the MenuItem buttons. This EventHandlers are only
- * usable for the items which allow to interact with the territory, e.g. placing
- * something into the territory or removing items from it.
- *
- * @param img The image, the cursor should change to, if the item is selected
- * @param index the buttonIndex, the buttonState should change to if the item is
- * selected
- * @return the eventHandler for the MenuItem
- */
- private EventHandler getRadioHandler(Image img, int index) {
- return e -> {
- RadioMenuItem item = ((RadioMenuItem) (e.getSource()));
- if (item.equals(selectedRadioMenuItem)) {
- if (changeCursor)
- mainStage.getMainStageScene().setCursor(Cursor.DEFAULT);
- selectedRadioMenuItem.setSelected(false);
- selectedRadioMenuItem = null;
- buttonState.deselect();
- } else {
- if (changeCursor && img != null)
- mainStage.getMainStageScene().setCursor(new ImageCursor(img));
- selectedRadioMenuItem = item;
- buttonState.setSelected(index);
- }
-
- };
- }
-
- @Override
- public void update(Observable observable) {
- if (observable instanceof Program program) {
- mainStage.getTextArea().getEditor().getDocument().setText(program.getEditorContent());
- }
- }
+ private final ButtonState buttonState;
+
+ private final MainStage mainStage;
+
+ @Setter
+ private boolean changeCursor = false;
+ @Getter
+ private final boolean soundsEnabled = false;
+
+ private RadioMenuItem selectedRadioMenuItem = null;
+
+ /**
+ * Creates a new MainStageController and sets all the actions for the buttons in
+ * the mainStage
+ *
+ * @param mainStage the mainStage for this controller
+ * @param buttonState the buttonState for this controller
+ */
+ public MainStageController(MainStage mainStage, ButtonState buttonState) {
+ this.mainStage = mainStage;
+ this.buttonState = buttonState;
+ this.mainStage.getProgram().addObserver(this);
+
+ mainStage.setTitle(i18n("Main.title") + ": " + mainStage.getProgram().getName());
+
+ mainStage.setOnCloseRequest(e -> {
+ mainStage.getProgram().save(mainStage.getTextArea().getEditor().getDocument().getText());
+ ProgramController.close(mainStage.getProgram().getName());
+ });
+
+ MenuBar menuBar = mainStage.getMenubar();
+
+ // editor (menuBar)
+ menuBar.getNewEditorMenuItem().setOnAction(e -> ProgramController.createAndShow(mainStage));
+ menuBar.getOpenEditorMenuItem().setOnAction(e -> ProgramController.openProgram(mainStage));
+ menuBar.getSaveEditorMenuItem().setOnAction(e -> {
+ mainStage.getProgram().save(mainStage.getTextArea().getEditor().getDocument().getText());
+ mainStage.setTitle(getTitle(mainStage.getProgram()));
+ });
+
+ menuBar.getFormatSourceCodeMenuItem().setOnAction(e -> {
+ mainStage.getNotificationController().showMessage(1500, "not.implemented");
+ // For this the following PR should first be merged:
+ // https://github.com/miho/MonacoFX/pull/25
+ });
+
+ menuBar.getCompileEditorMenuItem().setOnAction(e -> {
+ mainStage.getSimulationController().stopSimulation();
+ Program program = mainStage.getProgram();
+ program.save(mainStage.getTextArea().getEditor().getDocument().getText());
+ mainStage.setTitle(getTitle(program));
+ ProgramController.compile(program, mainStage);
+ });
+ // TODO print editor content
+ menuBar.getPrintEditorMenuItem()
+ .setOnAction(e -> mainStage.getNotificationController().showMessage(1500, "not.implemented"));
+ menuBar.getQuitEditorMenuItem().setOnAction(e -> {
+ Program program = mainStage.getProgram();
+ logger.info("exiting {}", program.getName());
+ program.save(mainStage.getTextArea().getEditor().getDocument().getText());
+ ProgramController.close(program.getName());
+ mainStage.close();
+ });
+ // Territory (menuBar)
+ // save -> TerritorySaveController
+ menuBar.getSaveAsPNGMenuItem().setOnAction(e -> {
+ String extension = ".png";
+ File file = getFile(i18n("Menu.territory.saveAsPic.png.description"), extension);
+ if (file == null)
+ return;
+
+ if (!saveAsImage(file, extension)) {
+ mainStage.getNotificationController().showMessage(3000, "Menu.territory.saveAsPic.error");
+ }
+ });
+ menuBar.getSaveAsGifMenuItem().setOnAction(e -> {
+ String extension = ".gif";
+ File file = getFile(i18n("Menu.territory.saveAsPic.gif.description"), extension);
+ if (file == null)
+ return;
+
+ if (!saveAsImage(file, extension)) {
+ mainStage.getNotificationController().showMessage(3000, "Menu.territory.saveAsPic.error");
+ }
+ });
+ menuBar.getPrintTerritoryMenuItem().setOnAction(e -> printTerritory());
+ menuBar.getChangeSizeTerritoryMenuItem()
+ .setOnAction(new ChangeTerritorySizeHandler(mainStage, mainStage.getTerritory()));
+
+ menuBar.getPlaceRobbiTerritoryRadioMenuItem()
+ .setOnAction(getRadioHandler(MainStage.menuRobbiImage, ButtonState.ROBBI));
+ menuBar.getPlaceHollowTerritoryRadioMenuItem()
+ .setOnAction(getRadioHandler(MainStage.menuHollowImage, ButtonState.HOLLOW));
+ menuBar.getPlacePileOfScrapTerritoryRadioMenuItem()
+ .setOnAction(getRadioHandler(MainStage.menuPileOfScrapImage, ButtonState.PILE_OF_SCRAP));
+ menuBar.getPlaceStockpileTerritoryRadioMenuItem()
+ .setOnAction(getRadioHandler(MainStage.menuStockpileImage, ButtonState.STOCKPILE));
+ menuBar.getPlaceAccuTerritoryRadioMenuItem()
+ .setOnAction(getRadioHandler(MainStage.menuAccuImage, ButtonState.ACCU));
+ menuBar.getPlaceScrewTerritoryRadioMenuItem()
+ .setOnAction(getRadioHandler(MainStage.menuScrewImage, ButtonState.SCREW));
+ menuBar.getPlaceNutTerritoryRadioMenuItem()
+ .setOnAction(getRadioHandler(MainStage.menuNutImage, ButtonState.NUT));
+ menuBar.getDeleteFieldRadioMenuItem()
+ .setOnAction(getRadioHandler(MainStage.menuDeleteImage, ButtonState.CLEAR));
+ // Robbi (menuBar)
+ menuBar.getMoveMenuItem().setOnAction(e -> {
+ try {
+ mainStage.getTerritory().getRobbi().vor();
+ } catch (HollowAheadException ex) {
+ mainStage.getNotificationController().showMessage(3000, ex.getMessage());
+ }
+ });
+ menuBar.getTurnLeftMenuItem().setOnAction(e -> mainStage.getTerritory().getRobbi().linksUm());
+ menuBar.getPutMenuItem().setOnAction(e -> {
+ try {
+ mainStage.getTerritory().getRobbi().legeAb();
+ } catch (BagIsEmptyException | TileIsFullException ex) {
+ mainStage.getNotificationController().showMessage(3000, ex.getMessage());
+ }
+ });
+ menuBar.getTakeMenuItem().setOnAction(e -> {
+ try {
+ mainStage.getTerritory().getRobbi().nehmeAuf();
+ } catch (NoItemException | BagIsFullException ex) {
+ mainStage.getNotificationController().showMessage(3000, ex.getMessage());
+ }
+ });
+ menuBar.getPushPileOfScrapMenuItem().setOnAction(e -> {
+ try {
+ mainStage.getTerritory().getRobbi().schiebeSchrotthaufen();
+ } catch (NoPileOfScrapAheadException | TileBlockedException ex) {
+ mainStage.getNotificationController().showMessage(3000, ex.getMessage());
+ }
+ });
+
+ menuBar.getItemPresentMenuItem().setOnAction(e -> {
+ boolean itemPresent = mainStage.getTerritory().getRobbi().gegenstandDa();
+ mainStage.getNotificationController().showMessage(3000, "Execution.information.itemPresent", itemPresent);
+ });
+ menuBar.getIsStockpileMenuItem().setOnAction(e -> {
+ boolean stockpilePresent = mainStage.getTerritory().getRobbi().istLagerplatz();
+ mainStage.getNotificationController().showMessage(3000, "Execution.information.stockpile", stockpilePresent);
+ });
+ menuBar.getHollowAheadMenuItem().setOnAction(e -> {
+ boolean hollowAhead = mainStage.getTerritory().getRobbi().vornKuhle();
+ mainStage.getNotificationController().showMessage(3000, "Execution.information.hollow", hollowAhead);
+ });
+ menuBar.getPileOfScrapAheadMenuItem().setOnAction(e -> {
+ boolean pileOfScrapAhead = mainStage.getTerritory().getRobbi().vornSchrotthaufen();
+ mainStage.getNotificationController().showMessage(3000, "Execution.information.pileOfScrap", pileOfScrapAhead);
+ });
+ menuBar.getIsBagFullMenuItem().setOnAction(e -> {
+ boolean isBagFull = mainStage.getTerritory().getRobbi().istTascheVoll();
+ mainStage.getNotificationController().showMessage(3000, "Execution.information.bag", isBagFull);
+ });
+
+ // simulation (menuBar) -> SimualtionController
+ // examples (menuBar) -> ExamplesController
+ // tutor (menuBar) -> TutorController / StudentController
+ // window (menuBar)
+ // language -> LangaugeController
+
+ menuBar.getChangeCursorMenuItem().setOnAction(e -> {
+ setChangeCursor(menuBar.getChangeCursorMenuItem().isSelected());
+ if (!menuBar.getChangeCursorMenuItem().isSelected())
+ mainStage.getScene().setCursor(Cursor.DEFAULT);
+ });
+ menuBar.getDarkModeMenuItem().selectedProperty().bindBidirectional(SceneManager.darkmodeProperty());
+ SceneManager.darkmodeProperty().addListener((obs, oldVal, newVal) -> {
+ if (Boolean.TRUE.equals(newVal)) {
+ mainStage.getScene().getStylesheets().add(SceneManager.getDarkmodeCss());
+ mainStage.getTextArea().getEditor().setCurrentTheme("vs-dark");
+ } else {
+ mainStage.getScene().getStylesheets().remove(SceneManager.getDarkmodeCss());
+ mainStage.getTextArea().getEditor().setCurrentTheme("vs-light");
+ }
+ });
+ if (SceneManager.getDarkmode()) {
+ mainStage.getScene().getStylesheets().add(SceneManager.getDarkmodeCss());
+ mainStage.getTextArea().getEditor().setCurrentTheme("vs-dark");
+ }
+ menuBar.getEnableSoundsMenuItem().selectedProperty().bindBidirectional(SoundManager.soundProperty());
+ menuBar.getInfoMenuItem()
+ .setOnAction(e -> AlertHelper.showAlertAndWait(AlertType.INFORMATION, i18n("Menu.window.info.content"),
+ mainStage, Modality.WINDOW_MODAL, i18n("Menu.window.info.title"),
+ i18n("Menu.window.info.header")));
+ menuBar.getLibraryMenuItem().setOnAction(e -> {
+ String javaFxVersion = System.getProperty("javafx.version");
+ String javaVersion = System.getProperty("java.version");
+ String derbyVersion = "10.x"; // TODO: read info from derby's info.properties
+ String jaxbVersion = JAXBContext.class.getPackage().getImplementationVersion();
+ String hibernateVersion = Version.getVersionString();
+ String lombokVersion = Generated.class.getPackage().getImplementationVersion();
+ String log4jVersion = Logger.class.getPackage().getImplementationVersion();
+ String monacoFxVersion = MonacoFX.class.getPackage().getImplementationVersion();
+ AlertHelper.showAlertAndWait(AlertType.INFORMATION,
+ i18n("Menu.window.libraries.content", javaVersion, javaFxVersion, monacoFxVersion,
+ derbyVersion, jaxbVersion, hibernateVersion, log4jVersion, lombokVersion),
+ mainStage, Modality.WINDOW_MODAL, i18n("Menu.window.libraries.title"),
+ i18n("Menu.window.libraries.header"));
+ });
+
+ Toolbar toolbar = mainStage.getToolbar();
+
+ // Editor (toolbar)
+ toolbar.getNewButtonToolbar().onActionProperty().bind(menuBar.getNewEditorMenuItem().onActionProperty());
+ toolbar.getLoadButtonToolbar().onActionProperty().bind(menuBar.getOpenEditorMenuItem().onActionProperty());
+ toolbar.getSaveButtonToolbar().onActionProperty().bind(menuBar.getSaveEditorMenuItem().onActionProperty());
+ toolbar.getCompileButtonToolbar().onActionProperty()
+ .bind(menuBar.getCompileEditorMenuItem().onActionProperty());
+ // Territory (toolbar)
+ toolbar.getChangeSizeButtonToolbar().onActionProperty()
+ .bind(menuBar.getChangeSizeTerritoryMenuItem().onActionProperty());
+ toolbar.getPlaceRobbiToggleButtonToolbar()
+ .setOnAction(getButtonHandler(MainStage.menuRobbiImage, ButtonState.ROBBI));
+ toolbar.getPlaceHollowToggleButtonToolbar()
+ .setOnAction(getButtonHandler(MainStage.menuHollowImage, ButtonState.HOLLOW));
+ toolbar.getPlacePileOfScrapToggleButtonToolbar()
+ .setOnAction(getButtonHandler(MainStage.menuPileOfScrapImage, ButtonState.PILE_OF_SCRAP));
+ toolbar.getPlaceStockpileToggleButtonToolbar()
+ .setOnAction(getButtonHandler(MainStage.menuStockpileImage, ButtonState.STOCKPILE));
+ toolbar.getPlaceAccuToggleButtonToolbar()
+ .setOnAction(getButtonHandler(MainStage.menuAccuImage, ButtonState.ACCU));
+ toolbar.getPlaceScrewToggleButtonToolbar()
+ .setOnAction(getButtonHandler(MainStage.menuScrewImage, ButtonState.SCREW));
+ toolbar.getPlaceNutToggleButtonToolbar().setOnAction(getButtonHandler(MainStage.menuNutImage, ButtonState.NUT));
+ toolbar.getDeleteFieldToggleButtonToolbar()
+ .setOnAction(getButtonHandler(MainStage.menuDeleteImage, ButtonState.CLEAR));
+ // Robbi (Toolbar)
+ toolbar.getRobbiMoveButtonToolbar().onActionProperty().bind(menuBar.getMoveMenuItem().onActionProperty());
+ toolbar.getRobbiTurnLeftButtonToolbar().onActionProperty()
+ .bind(menuBar.getTurnLeftMenuItem().onActionProperty());
+ toolbar.getRobbiPutButtonToolbar().onActionProperty().bind(menuBar.getPutMenuItem().onActionProperty());
+ toolbar.getRobbiTakeButtonToolbar().onActionProperty().bind(menuBar.getTakeMenuItem().onActionProperty());
+ // Simulation (Toolbar) -> SimulationController
+
+ // editor Panel
+ mainStage.getTextArea().getEditor().getDocument().textProperty().addListener((observalble, oldVal, newVal) -> {
+ Program program = mainStage.getProgram();
+ boolean before = program.isEdited();
+ program.setEdited(!newVal.equals(program.getEditorContent()));
+ if (before != program.isEdited())
+ mainStage.setTitle(getTitle(program));
+ });
+
+ }
+
+ /**
+ * Saves the current territoryPanel in the given file with the given extension.
+ * If the file does not have the correct extension, the given extension will be
+ * appended to the files name.
+ *
+ * @param file The file the image should be written into
+ * @param extension The image extension
+ * @return false, if the creation failed, true otherwise
+ */
+ private boolean saveAsImage(File file, String extension) {
+
+ if (!file.getName().endsWith(extension)) {
+ file = new File(file.getAbsolutePath() + extension);
+ }
+
+ TerritoryPanel tPanel = mainStage.getTerritoryPanel();
+ WritableImage snapshot = tPanel.snapshot(new SnapshotParameters(), null);
+
+ BufferedImage bufferedImage = new BufferedImage((int) tPanel.getWidth(), (int) tPanel.getHeight(),
+ BufferedImage.TYPE_INT_ARGB);
+
+ BufferedImage image = SwingFXUtils.fromFXImage(snapshot, bufferedImage);
+ try {
+ logger.info("Saving territory to {}", file);
+ if (!ImageIO.write(image, extension.substring(1), file))
+ logger.debug("Failed to find appropiate ImageWriter");
+
+ } catch (IOException e) {
+ logger.info("Failed to save territory as image");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Opens a FileChooser in the default programs folder and asks the user to
+ * select or save a file to save an image.
+ *
+ * @param description the description for the extension
+ * @param extension the file-extension
+ * @return the selected file, null otherwise
+ */
+ private File getFile(String description, String extension) {
+ FileChooser chooser = new FileChooser();
+ chooser.setInitialDirectory(new File(ProgramController.PATH_TO_PROGRAMS));
+ chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(description, "*" + extension));
+ return chooser.showSaveDialog(mainStage);
+ }
+
+ /**
+ * Gets the title for the application by the corresponding program
+ *
+ * @param program The program for the current instance
+ * @return the name of the application include a * at the end, if the program
+ * has unsaved changes
+ */
+ private String getTitle(Program program) {
+ return i18n("Main.title") + ": " + program.getName() + (program.isEdited() ? "*" : "");
+ }
+
+ /**
+ * Sends the territory to a printer in order to print it.
+ */
+ private void printTerritory() {
+
+ PrinterJob printerJob = PrinterJob.createPrinterJob();
+
+ if (printerJob != null) {
+ boolean flag = printerJob.showPrintDialog(mainStage);
+ if (!flag)
+ return;
+ TerritoryPanel node = mainStage.getTerritoryPanel();
+
+ // scale the node
+ // https://www.tabnine.com/code/java/methods/javafx.print.PageLayout/getPrintableWidth
+ PageLayout pageLayout = printerJob.getJobSettings().getPageLayout();
+ double scaleX = 1.0;
+ if (pageLayout.getPrintableWidth() < node.getBoundsInParent().getWidth()) {
+ scaleX = pageLayout.getPrintableWidth() / node.getBoundsInParent().getWidth();
+ }
+ double scaleY = 1.0;
+ if (pageLayout.getPrintableHeight() < node.getBoundsInParent().getHeight()) {
+ scaleY = pageLayout.getPrintableHeight() / node.getBoundsInParent().getHeight();
+ }
+ double scaleXY = Double.min(scaleX, scaleY);
+ Scale scale = new Scale(scaleXY, scaleXY);
+ node.getTransforms().add(scale);
+ // Print the node
+ flag = printerJob.printPage(node);
+ node.getTransforms().remove(scale);
+ if (flag) {
+ // End the printer job
+ if (!printerJob.endJob()) {
+ logger.debug("Could not end printerJob");
+ }
+ } else {
+ logger.info("Printing failed or cancled");
+ }
+ } else {
+ logger.info("Failed to create printerJob");
+ AlertHelper.showAlertAndWait(AlertType.ERROR, i18n("Menu.territory.print.error"), mainStage);
+ }
+ }
+
+ /**
+ * Creates an EventHandler for the Toolbar buttons. This EventHandlers are only
+ * usable for the buttons which allow to interact with the territory, e.g.
+ * placing something into the territory or removing items from it.
+ *
+ * @param img The image, the cursor should change to, if the button is pressed
+ * @param index the buttonIndex, the buttonState should change to if the button
+ * is pressed
+ * @return the eventHandler for the Toolbar button
+ */
+ private EventHandler getButtonHandler(Image img, int index) {
+ return e -> {
+ if (((ToggleButton) (e.getSource())).isSelected()) {
+ if (changeCursor && img != null)
+ mainStage.getMainStageScene().setCursor(new ImageCursor(img));
+ buttonState.setSelected(index);
+ } else {
+ if (changeCursor)
+ mainStage.getMainStageScene().setCursor(Cursor.DEFAULT);
+ buttonState.deselect();
+ }
+ };
+ }
+
+ /**
+ * Creates an EventHandler for the MenuItem buttons. This EventHandlers are only
+ * usable for the items which allow to interact with the territory, e.g. placing
+ * something into the territory or removing items from it.
+ *
+ * @param img The image, the cursor should change to, if the item is selected
+ * @param index the buttonIndex, the buttonState should change to if the item is
+ * selected
+ * @return the eventHandler for the MenuItem
+ */
+ private EventHandler getRadioHandler(Image img, int index) {
+ return e -> {
+ RadioMenuItem item = ((RadioMenuItem) (e.getSource()));
+ if (item.equals(selectedRadioMenuItem)) {
+ if (changeCursor)
+ mainStage.getMainStageScene().setCursor(Cursor.DEFAULT);
+ selectedRadioMenuItem.setSelected(false);
+ selectedRadioMenuItem = null;
+ buttonState.deselect();
+ } else {
+ if (changeCursor && img != null)
+ mainStage.getMainStageScene().setCursor(new ImageCursor(img));
+ selectedRadioMenuItem = item;
+ buttonState.setSelected(index);
+ }
+
+ };
+ }
+
+ @Override
+ public void update(Observable observable) {
+ if (observable instanceof Program program) {
+ mainStage.getTextArea().getEditor().getDocument().setText(program.getEditorContent());
+ }
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/MethodHandler.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/MethodHandler.java
index 9e133ac..7158944 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/MethodHandler.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/MethodHandler.java
@@ -1,33 +1,34 @@
package com.JayPi4c.RobbiSimulator.controller;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Parameter;
-import java.util.ArrayList;
-import java.util.List;
-
import com.JayPi4c.RobbiSimulator.model.RobbiException;
import com.JayPi4c.RobbiSimulator.model.Territory;
import com.JayPi4c.RobbiSimulator.utils.AlertHelper;
import com.JayPi4c.RobbiSimulator.utils.I18nUtils;
import com.JayPi4c.RobbiSimulator.utils.annotations.Default;
import com.JayPi4c.RobbiSimulator.view.MainStage;
-
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Alert.AlertType;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.ArrayList;
+import java.util.List;
/**
* MethodHandler to handle a methods invocation
*
* @author Jonas Pohl
*/
+@Slf4j
public class MethodHandler implements EventHandler {
- private Method method;
- private Territory territory;
- private MainStage parent;
+ private final Method method;
+ private final Territory territory;
+ private final MainStage parent;
/**
* Creates a new MethodHandler with the method and the territory the message is
@@ -65,13 +66,13 @@ public void handle(ActionEvent event) {
if (result != null) {
AlertHelper.showAlertAndWait(AlertType.INFORMATION,
- I18nUtils.i18n("Execution.information.result") + result.toString(), parent);
+ I18nUtils.i18n("Execution.information.result") + result, parent);
}
} catch (IllegalArgumentException | IllegalAccessException e) {
- e.printStackTrace();
+ logger.error("Failed to invoke method", e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof RobbiException) {
- parent.getSnackbarController().showMessage(e.getCause().getLocalizedMessage());
+ parent.getNotificationController().showMessage(3000, e.getCause().getLocalizedMessage());
} else {
AlertHelper.showAlertAndWait(AlertType.ERROR, e.getCause().getMessage(), parent);
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/NotificationController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/NotificationController.java
new file mode 100644
index 0000000..c65ceb7
--- /dev/null
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/NotificationController.java
@@ -0,0 +1,49 @@
+package com.JayPi4c.RobbiSimulator.controller;
+
+import javafx.animation.KeyFrame;
+import javafx.animation.Timeline;
+import javafx.scene.Node;
+import javafx.scene.Parent;
+import javafx.util.Duration;
+import lombok.extern.slf4j.Slf4j;
+import org.controlsfx.control.NotificationPane;
+
+import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
+
+@Slf4j
+public class NotificationController {
+
+ private final NotificationPane notificationPane;
+ private final Timeline hideTimeline = new Timeline();
+
+ public NotificationController(Node node) {
+ notificationPane = new NotificationPane(node);
+ notificationPane.setShowFromTop(false);
+ notificationPane.getStyleClass().add(NotificationPane.STYLE_CLASS_DARK);
+ hideTimeline.setCycleCount(1);
+ }
+
+ public Parent getScene() {
+ return notificationPane;
+ }
+
+ /**
+ * Shows a message in a notification pane. The message will be shown for the given timeout in milliseconds.
+ * If a message is already shown, it will be replaced by the new message and the timeout will be reset.
+ *
+ * @param timeout in milliseconds
+ * @param key the key of the message
+ * @param args the arguments for the message
+ */
+ public void showMessage(int timeout, String key, Object... args) {
+ hideTimeline.stop();
+ notificationPane.show(i18n(key, args));
+ KeyFrame kf = new KeyFrame(Duration.millis(timeout), e -> {
+ if (notificationPane.isShowing())
+ notificationPane.hide();
+ });
+ hideTimeline.getKeyFrames().setAll(kf);
+ hideTimeline.play();
+ }
+
+}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/SnackbarController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/SnackbarController.java
deleted file mode 100644
index ca39c0b..0000000
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/SnackbarController.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.JayPi4c.RobbiSimulator.controller;
-
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
-
-import com.jfoenix.controls.JFXSnackbar;
-import com.jfoenix.controls.JFXSnackbar.SnackbarEvent;
-import com.jfoenix.controls.JFXSnackbarLayout;
-
-import javafx.scene.layout.Pane;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class SnackbarController {
-
- private JFXSnackbar snackbar;
-
- public SnackbarController(Pane root) {
- snackbar = new JFXSnackbar(root);
- }
-
- public void showMessage(String key, Object... args) {
- logger.debug("Showing snackbar-message: {}; {}", key, i18n(key, args));
- snackbar.fireEvent(new SnackbarEvent(new JFXSnackbarLayout(i18n(key, args))));
- }
-
-}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/TerritoryEventHandler.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/TerritoryEventHandler.java
index 62fbc2a..fc26435 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/TerritoryEventHandler.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/TerritoryEventHandler.java
@@ -4,121 +4,119 @@
import com.JayPi4c.RobbiSimulator.view.MainStage;
import com.JayPi4c.RobbiSimulator.view.RobbiContextMenu;
import com.JayPi4c.RobbiSimulator.view.TerritoryPanel;
-
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
/**
* This class combines all functions needed to control the user interaction with
* the territory
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class TerritoryEventHandler implements EventHandler {
- private Territory territory;
+ private final Territory territory;
- private boolean robbiDragged = false;
+ private boolean robbiDragged = false;
- private ButtonState buttonState;
+ private final ButtonState buttonState;
- private RobbiContextMenu robbiContextMenu;
+ private RobbiContextMenu robbiContextMenu;
- /**
- * Creates a new TerritoryEventHandler and sets the contextMenuRequest to show a
- * RobbiContextMenu if the user right-clicks on Robbi
- *
- * @param territory the Territory this handler is for
- * @param territoryPanel the TerritoryPanel, this handler is handling
- * @param buttonState the ButtonState for this eventHandler
- * @param parent the parent window to show alerts relative to it
- */
- public TerritoryEventHandler(Territory territory, TerritoryPanel territoryPanel, ButtonState buttonState,
- MainStage parent) {
- this.territory = territory;
- this.buttonState = buttonState;
- territoryPanel.setOnContextMenuRequested(event -> {
- if (territory.robbiOnTile(getCol(event.getX()), getRow(event.getY()))) {
- robbiContextMenu = new RobbiContextMenu(territory, parent);
- robbiContextMenu.show(territoryPanel.getScene().getWindow(), event.getScreenX(), event.getScreenY());
- }
- });
+ /**
+ * Creates a new TerritoryEventHandler and sets the contextMenuRequest to show a
+ * RobbiContextMenu if the user right-clicks on Robbi
+ *
+ * @param territory the Territory this handler is for
+ * @param territoryPanel the TerritoryPanel, this handler is handling
+ * @param buttonState the ButtonState for this eventHandler
+ * @param parent the parent window to show alerts relative to it
+ */
+ public TerritoryEventHandler(Territory territory, TerritoryPanel territoryPanel, ButtonState buttonState,
+ MainStage parent) {
+ this.territory = territory;
+ this.buttonState = buttonState;
+ territoryPanel.setOnContextMenuRequested(event -> {
+ if (territory.robbiOnTile(getCol(event.getX()), getRow(event.getY()))) {
+ robbiContextMenu = new RobbiContextMenu(territory, parent);
+ robbiContextMenu.show(territoryPanel.getScene().getWindow(), event.getScreenX(), event.getScreenY());
+ }
+ });
- }
+ }
- /**
- * {@inheritDoc}
- * Places an Item or Object in the territory or drags and drops the robbi
- */
- @Override
- public void handle(MouseEvent event) {
- int col = getCol(event.getX());
- int row = getRow(event.getY());
- if (event.getEventType() == MouseEvent.MOUSE_PRESSED) {
- robbiDragged = territory.robbiOnTile(col, row);
- } else if (event.getEventType() == MouseEvent.MOUSE_DRAGGED) {
- if (robbiDragged)
- territory.placeRobbi(col, row);
- } else if (event.getEventType() == MouseEvent.MOUSE_RELEASED) {
- if (!robbiDragged) {
- switch (buttonState.getSelected()) {
- case ButtonState.ROBBI:
- territory.placeRobbi(col, row);
- break;
- case ButtonState.HOLLOW:
- territory.placeHollow(col, row);
- break;
- case ButtonState.PILE_OF_SCRAP:
- territory.placePileOfScrap(col, row);
- break;
- case ButtonState.STOCKPILE:
- territory.placeStockpile(col, row);
- break;
- case ButtonState.ACCU:
- territory.placeAccu(col, row);
- break;
- case ButtonState.SCREW:
- territory.placeScrew(col, row);
- break;
- case ButtonState.NUT:
- territory.placeNut(col, row);
- break;
- case ButtonState.CLEAR:
- territory.clearTile(col, row);
- break;
- case ButtonState.NONE:
- // fall through
- default:
- // Do nothing
- }
- }
- robbiDragged = false;
- }
+ /**
+ * {@inheritDoc}
+ * Places an Item or Object in the territory or drags and drops the robbi
+ */
+ @Override
+ public void handle(MouseEvent event) {
+ int col = getCol(event.getX());
+ int row = getRow(event.getY());
+ if (event.getEventType() == MouseEvent.MOUSE_PRESSED) {
+ robbiDragged = territory.robbiOnTile(col, row);
+ } else if (event.getEventType() == MouseEvent.MOUSE_DRAGGED) {
+ if (robbiDragged)
+ territory.placeRobbi(col, row);
+ } else if (event.getEventType() == MouseEvent.MOUSE_RELEASED) {
+ if (!robbiDragged) {
+ switch (buttonState.getSelected()) {
+ case ButtonState.ROBBI:
+ territory.placeRobbi(col, row);
+ break;
+ case ButtonState.HOLLOW:
+ territory.placeHollow(col, row);
+ break;
+ case ButtonState.PILE_OF_SCRAP:
+ territory.placePileOfScrap(col, row);
+ break;
+ case ButtonState.STOCKPILE:
+ territory.placeStockpile(col, row);
+ break;
+ case ButtonState.ACCU:
+ territory.placeAccu(col, row);
+ break;
+ case ButtonState.SCREW:
+ territory.placeScrew(col, row);
+ break;
+ case ButtonState.NUT:
+ territory.placeNut(col, row);
+ break;
+ case ButtonState.CLEAR:
+ territory.clearTile(col, row);
+ break;
+ case ButtonState.NONE:
+ // fall through
+ default:
+ // Do nothing
+ }
+ }
+ robbiDragged = false;
+ }
- }
+ }
- /**
- * Calculates the column to a given horizontal mouse-position
- *
- * @param x Horizontal position of the event relative to the origin of the
- * MouseEvent's source.
- * @return column corresponding to the given x
- */
- private int getCol(double x) {
- return (int) (x / (TerritoryPanel.getCellsize() + TerritoryPanel.getCellspacer()));
- }
+ /**
+ * Calculates the column to a given horizontal mouse-position
+ *
+ * @param x Horizontal position of the event relative to the origin of the
+ * MouseEvent's source.
+ * @return column corresponding to the given x
+ */
+ private int getCol(double x) {
+ return (int) (x / (TerritoryPanel.getCellsize() + TerritoryPanel.getCellspacer()));
+ }
- /**
- * Calculates the row to a given vertical mouse-position
- *
- * @param y Vertical position of the event relative to the origin of the
- * MouseEvent's source.
- * @return row corresponding to the given y
- */
- private int getRow(double y) {
- return (int) (y / (TerritoryPanel.getCellsize() + TerritoryPanel.getCellspacer()));
+ /**
+ * Calculates the row to a given vertical mouse-position
+ *
+ * @param y Vertical position of the event relative to the origin of the
+ * MouseEvent's source.
+ * @return row corresponding to the given y
+ */
+ private int getRow(double y) {
+ return (int) (y / (TerritoryPanel.getCellsize() + TerritoryPanel.getCellspacer()));
- }
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/TerritorySaveController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/TerritorySaveController.java
index 4a07c0d..c901caa 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/TerritorySaveController.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/TerritorySaveController.java
@@ -1,36 +1,9 @@
package com.JayPi4c.RobbiSimulator.controller;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.util.Optional;
-
import com.JayPi4c.RobbiSimulator.controller.program.ProgramController;
-import com.JayPi4c.RobbiSimulator.model.Accu;
-import com.JayPi4c.RobbiSimulator.model.DIRECTION;
-import com.JayPi4c.RobbiSimulator.model.Hollow;
-import com.JayPi4c.RobbiSimulator.model.InvalidTerritoryException;
-import com.JayPi4c.RobbiSimulator.model.Item;
-import com.JayPi4c.RobbiSimulator.model.Nut;
-import com.JayPi4c.RobbiSimulator.model.PileOfScrap;
-import com.JayPi4c.RobbiSimulator.model.Screw;
-import com.JayPi4c.RobbiSimulator.model.Stockpile;
-import com.JayPi4c.RobbiSimulator.model.Territory;
-import com.JayPi4c.RobbiSimulator.model.TerritoryState;
+import com.JayPi4c.RobbiSimulator.model.*;
import com.JayPi4c.RobbiSimulator.utils.AlertHelper;
import com.JayPi4c.RobbiSimulator.view.MainStage;
-
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
@@ -39,242 +12,242 @@
import javafx.stage.FileChooser;
import lombok.extern.slf4j.Slf4j;
+import java.io.*;
+import java.util.Optional;
+
+import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
+
/**
* Controller to handle all territory save action. It handles load and save
* actions for all supported formats.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
public class TerritorySaveController {
- private static final String DEFAULT_SERIALISATION_FILE_EXTENSION = ".ter";
- private static final String DEFAULT_XML_FILE_EXTENSION = ".rsxml";
- private static final String DEFAULT_JAXB_FILE_EXTENSION = ".rsjaxb";
-
- private MainStage mainStage;
-
- /**
- * Constructor to create a new TerritorySaveController for the given mainStage.
- *
- * @param mainStage the mainStage this controller is for
- */
- public TerritorySaveController(MainStage mainStage) {
- this.mainStage = mainStage;
- this.mainStage.getMenubar().getSaveSerialTerritoryMenuItem().setOnAction(e -> serialize());
- this.mainStage.getMenubar().getLoadSerialTerritoryMenuItem().setOnAction(e -> deserialize());
-
- this.mainStage.getMenubar().getSaveXMLTerritoryMenuItem().setOnAction(e -> saveXMLtoFile());
- this.mainStage.getMenubar().getLoadXMLTerritoryMenuItem().setOnAction(e -> loadXMLfromFile());
-
- this.mainStage.getMenubar().getSaveJAXBTerritoryMenuItem().setOnAction(e -> saveJAXB());
- this.mainStage.getMenubar().getLoadJAXBTerritoryMenuItem().setOnAction(e -> loadJAXB());
- }
-
- /**
- * Helper to serialize the territory of the mainStage into a file.
- */
- private void serialize() {
- Optional fileOpt = getSaveFile(i18n("Territory.save.dialog.title"),
- i18n("Territory.save.dialog.filter.serial"), DEFAULT_SERIALISATION_FILE_EXTENSION);
-
- if (fileOpt.isEmpty()) {
- logger.debug("No file was selected to serialze in.");
- return;
- }
-
- File file = fileOpt.get();
- if (!file.getName().endsWith(DEFAULT_SERIALISATION_FILE_EXTENSION)) {
- file = new File(file.getAbsolutePath() + DEFAULT_SERIALISATION_FILE_EXTENSION);
- }
-
- logger.debug("serialize in file {}", file);
- try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
- synchronized (mainStage.getTerritory()) {
- oos.writeObject(mainStage.getTerritory());
- oos.writeObject(mainStage.getTerritory().getRobbiItem());
- oos.writeInt(mainStage.getTerritory().getRobbiX());
- oos.writeInt(mainStage.getTerritory().getRobbiY());
- oos.writeObject(mainStage.getTerritory().getRobbiDirection());
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- logger.info("finished serialization");
- }
-
- }
-
- /**
- * Helper to deserialize a territory from a file and update the old territory to
- * the new values.
- */
- private void deserialize() {
- Optional fileOpt = getLoadFile(i18n("Territory.load.dialog.title"),
- i18n("Territory.load.dialog.filter.deserial"), DEFAULT_SERIALISATION_FILE_EXTENSION);
-
- if (fileOpt.isEmpty()) {
- logger.debug("No file was selected to deserialize from.");
- return;
- }
- File file = fileOpt.get();
-
- try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
- logger.debug("deserialize from file {}", file);
- Territory t = (Territory) ois.readObject();
- Item item = (Item) ois.readObject();
- int x = ois.readInt();
- int y = ois.readInt();
- DIRECTION facing = (DIRECTION) ois.readObject();
- mainStage.getTerritory().update(t, item, x, y, facing);
- } catch (InvalidTerritoryException e) {
- AlertHelper.showAlertAndWait(AlertType.WARNING, i18n("Territory.load.failure"), mainStage);
- } catch (IOException | ClassNotFoundException e) {
- e.printStackTrace();
- } finally {
- logger.info("finished deserialization");
- }
- }
-
- /**
- * Asks for a file to save the xml to and then writes the territory into this
- * file.
- */
- private void saveXMLtoFile() {
- Optional fileOpt = getSaveFile(i18n("Territory.save.dialog.title"),
- i18n("Territory.save.dialog.filter.xml"), DEFAULT_XML_FILE_EXTENSION);
-
- if (fileOpt.isEmpty()) {
- logger.debug("No file selected to save territory in.");
- return;
- }
- File file = fileOpt.get();
-
- if (!file.getName().endsWith(DEFAULT_XML_FILE_EXTENSION)) {
- file = new File(file.getAbsolutePath() + DEFAULT_XML_FILE_EXTENSION);
- }
-
- logger.debug("save as XML in file {}", file);
- try (ByteArrayOutputStream baos = mainStage.getTerritory().toXML();
- OutputStream outputStream = new FileOutputStream(file.getAbsolutePath())) {
- baos.writeTo(outputStream);
- } catch (IOException e) {
- logger.debug("failed");
- }
-
- }
-
- /**
- * Asks for an XML-File and loads the contents into the territory.
- */
- private void loadXMLfromFile() {
- Optional fileOpt = getLoadFile(i18n("Territory.load.dialog.title"),
- i18n("Territory.load.dialog.filter.xml"), DEFAULT_XML_FILE_EXTENSION);
-
- if (fileOpt.isEmpty()) {
- logger.debug("No file selected to load XML from.");
- return;
- }
-
- File file = fileOpt.get();
- logger.debug("load territory from xml-file {}", file);
- try {
- if (mainStage.getTerritory().fromXML(new FileInputStream(file)))
- logger.info("finished loading from xml-file");
- else
- logger.info("Failed loading from xml-file");
- } catch (FileNotFoundException e) {
- logger.debug("Could not find file {}", file.getAbsolutePath());
- }
-
- }
-
- /**
- * Loads a territory by a filename using JAXB
- *
- * @return true if the territory was loaded successfully, false otherwise
- */
- private void loadJAXB() {
- Optional fileOpt = getLoadFile(i18n("Territory.load.dialog.title"),
- i18n("Territory.load.dialog.filter.jaxb"), DEFAULT_JAXB_FILE_EXTENSION);
-
- if (fileOpt.isEmpty()) {
- logger.debug("No file selected");
- return;
- }
- File file = fileOpt.get();
- logger.debug("load territory from jaxb-file {}", file);
- try {
- JAXBContext context = JAXBContext.newInstance(TerritoryState.class, Nut.class, Screw.class, Accu.class,
- Stockpile.class, PileOfScrap.class, Hollow.class);
- Unmarshaller um = context.createUnmarshaller();
- TerritoryState ter = (TerritoryState) um.unmarshal(new FileReader(file));
- mainStage.getTerritory().restore(ter);
- } catch (IOException | JAXBException e) {
- e.printStackTrace();
- logger.debug("failed to load JAXB");
- }
- }
-
- /**
- * Saves the territory using JAXB.
- */
- private void saveJAXB() {
- Optional fileOpt = getSaveFile(i18n("Territory.save.dialog.title"),
- i18n("Territory.save.dialog.filter.jaxb"), DEFAULT_JAXB_FILE_EXTENSION);
-
- if (fileOpt.isEmpty()) {
- logger.debug("No file selected to save territory in.");
- return;
- }
- File file = fileOpt.get();
- if (!file.getName().endsWith(DEFAULT_JAXB_FILE_EXTENSION)) {
- file = new File(file.getAbsolutePath() + DEFAULT_JAXB_FILE_EXTENSION);
- }
- logger.debug("save territory from jaxb-file {}", file);
- try (Writer w = new FileWriter(file)) {
- JAXBContext context = JAXBContext.newInstance(TerritoryState.class, Nut.class, Screw.class, Accu.class,
- Stockpile.class, PileOfScrap.class, Hollow.class);
- Marshaller m = context.createMarshaller();
- m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
- m.marshal(mainStage.getTerritory().save(), w);
- } catch (IOException | JAXBException e) {
- e.printStackTrace();
- logger.debug("failed to save jaxb");
- }
- }
-
- /**
- * Opens a dialog to ask for a file to save the territory in.
- *
- * @param title the title of the dialog
- * @param description file description for the allowed files
- * @param fileExtension allowed file-extension
- * @return a file to save the territory in
- */
- private Optional getSaveFile(String title, String description, String fileExtension) {
- FileChooser chooser = new FileChooser();
- chooser.setTitle(title);
- chooser.setInitialDirectory(new File(ProgramController.PATH_TO_PROGRAMS));
- chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(description, "*" + fileExtension));
- return Optional.ofNullable(chooser.showSaveDialog(mainStage));
- }
-
- /**
- * Opens a dialog to ask for a file to load a territory from.
- *
- * @param title the title of the dialog
- * @param description file description for allowed files
- * @param fileExtension allowed file-extension
- * @return a file to load a territory from
- */
- public Optional getLoadFile(String title, String description, String fileExtension) {
- FileChooser fileChooser = new FileChooser();
- fileChooser.setTitle(title);
- fileChooser.setInitialDirectory(new File(ProgramController.PATH_TO_PROGRAMS));
- fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(description, "*" + fileExtension));
- return Optional.ofNullable(fileChooser.showOpenDialog(mainStage));
- }
+ private static final String DEFAULT_SERIALISATION_FILE_EXTENSION = ".ter";
+ private static final String DEFAULT_XML_FILE_EXTENSION = ".rsxml";
+ private static final String DEFAULT_JAXB_FILE_EXTENSION = ".rsjaxb";
+
+ private final MainStage mainStage;
+
+ /**
+ * Constructor to create a new TerritorySaveController for the given mainStage.
+ *
+ * @param mainStage the mainStage this controller is for
+ */
+ public TerritorySaveController(MainStage mainStage) {
+ this.mainStage = mainStage;
+ this.mainStage.getMenubar().getSaveSerialTerritoryMenuItem().setOnAction(e -> serialize());
+ this.mainStage.getMenubar().getLoadSerialTerritoryMenuItem().setOnAction(e -> deserialize());
+
+ this.mainStage.getMenubar().getSaveXMLTerritoryMenuItem().setOnAction(e -> saveXMLtoFile());
+ this.mainStage.getMenubar().getLoadXMLTerritoryMenuItem().setOnAction(e -> loadXMLfromFile());
+
+ this.mainStage.getMenubar().getSaveJAXBTerritoryMenuItem().setOnAction(e -> saveJAXB());
+ this.mainStage.getMenubar().getLoadJAXBTerritoryMenuItem().setOnAction(e -> loadJAXB());
+ }
+
+ /**
+ * Helper to serialize the territory of the mainStage into a file.
+ */
+ private void serialize() {
+ Optional fileOpt = getSaveFile(i18n("Territory.save.dialog.title"),
+ i18n("Territory.save.dialog.filter.serial"), DEFAULT_SERIALISATION_FILE_EXTENSION);
+
+ if (fileOpt.isEmpty()) {
+ logger.debug("No file was selected to serialze in.");
+ return;
+ }
+
+ File file = fileOpt.get();
+ if (!file.getName().endsWith(DEFAULT_SERIALISATION_FILE_EXTENSION)) {
+ file = new File(file.getAbsolutePath() + DEFAULT_SERIALISATION_FILE_EXTENSION);
+ }
+
+ logger.debug("serialize in file {}", file);
+ try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
+ synchronized (mainStage.getTerritory()) {
+ oos.writeObject(mainStage.getTerritory());
+ oos.writeObject(mainStage.getTerritory().getRobbiItem());
+ oos.writeInt(mainStage.getTerritory().getRobbiX());
+ oos.writeInt(mainStage.getTerritory().getRobbiY());
+ oos.writeObject(mainStage.getTerritory().getRobbiDirection());
+ }
+ } catch (IOException e) {
+ logger.error("Failed to serialize territory", e);
+ } finally {
+ logger.info("finished serialization");
+ }
+
+ }
+
+ /**
+ * Helper to deserialize a territory from a file and update the old territory to
+ * the new values.
+ */
+ private void deserialize() {
+ Optional fileOpt = getLoadFile(i18n("Territory.load.dialog.title"),
+ i18n("Territory.load.dialog.filter.deserial"), DEFAULT_SERIALISATION_FILE_EXTENSION);
+
+ if (fileOpt.isEmpty()) {
+ logger.debug("No file was selected to deserialize from.");
+ return;
+ }
+ File file = fileOpt.get();
+
+ try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
+ logger.debug("deserialize from file {}", file);
+ Territory t = (Territory) ois.readObject();
+ Item item = (Item) ois.readObject();
+ int x = ois.readInt();
+ int y = ois.readInt();
+ DIRECTION facing = (DIRECTION) ois.readObject();
+ mainStage.getTerritory().update(t, item, x, y, facing);
+ } catch (InvalidTerritoryException e) {
+ AlertHelper.showAlertAndWait(AlertType.WARNING, i18n("Territory.load.failure"), mainStage);
+ } catch (IOException | ClassNotFoundException e) {
+ logger.error("Failed to deserialize territory", e);
+ } finally {
+ logger.info("finished deserialization");
+ }
+ }
+
+ /**
+ * Asks for a file to save the xml to and then writes the territory into this
+ * file.
+ */
+ private void saveXMLtoFile() {
+ Optional fileOpt = getSaveFile(i18n("Territory.save.dialog.title"),
+ i18n("Territory.save.dialog.filter.xml"), DEFAULT_XML_FILE_EXTENSION);
+
+ if (fileOpt.isEmpty()) {
+ logger.debug("No file selected to save territory in.");
+ return;
+ }
+ File file = fileOpt.get();
+
+ if (!file.getName().endsWith(DEFAULT_XML_FILE_EXTENSION)) {
+ file = new File(file.getAbsolutePath() + DEFAULT_XML_FILE_EXTENSION);
+ }
+
+ logger.debug("save as XML in file {}", file);
+ try (ByteArrayOutputStream baos = mainStage.getTerritory().toXML();
+ OutputStream outputStream = new FileOutputStream(file.getAbsolutePath())) {
+ baos.writeTo(outputStream);
+ } catch (IOException e) {
+ logger.debug("failed");
+ }
+
+ }
+
+ /**
+ * Asks for an XML-File and loads the contents into the territory.
+ */
+ private void loadXMLfromFile() {
+ Optional fileOpt = getLoadFile(i18n("Territory.load.dialog.title"),
+ i18n("Territory.load.dialog.filter.xml"), DEFAULT_XML_FILE_EXTENSION);
+
+ if (fileOpt.isEmpty()) {
+ logger.debug("No file selected to load XML from.");
+ return;
+ }
+
+ File file = fileOpt.get();
+ logger.debug("load territory from xml-file {}", file);
+ try {
+ if (mainStage.getTerritory().fromXML(new FileInputStream(file)))
+ logger.info("finished loading from xml-file");
+ else
+ logger.info("Failed loading from xml-file");
+ } catch (FileNotFoundException e) {
+ logger.debug("Could not find file {}", file.getAbsolutePath());
+ }
+
+ }
+
+ /**
+ * Loads a territory by a filename using JAXB
+ */
+ private void loadJAXB() {
+ Optional fileOpt = getLoadFile(i18n("Territory.load.dialog.title"),
+ i18n("Territory.load.dialog.filter.jaxb"), DEFAULT_JAXB_FILE_EXTENSION);
+
+ if (fileOpt.isEmpty()) {
+ logger.debug("No file selected");
+ return;
+ }
+ File file = fileOpt.get();
+ logger.debug("load territory from jaxb-file {}", file);
+ try {
+ JAXBContext context = JAXBContext.newInstance(TerritoryState.class, Nut.class, Screw.class, Accu.class,
+ Stockpile.class, PileOfScrap.class, Hollow.class);
+ Unmarshaller um = context.createUnmarshaller();
+ TerritoryState ter = (TerritoryState) um.unmarshal(new FileReader(file));
+ mainStage.getTerritory().restore(ter);
+ } catch (IOException | JAXBException e) {
+ logger.error("failed to load JAXB.", e);
+ }
+ }
+
+ /**
+ * Saves the territory using JAXB.
+ */
+ private void saveJAXB() {
+ Optional fileOpt = getSaveFile(i18n("Territory.save.dialog.title"),
+ i18n("Territory.save.dialog.filter.jaxb"), DEFAULT_JAXB_FILE_EXTENSION);
+
+ if (fileOpt.isEmpty()) {
+ logger.debug("No file selected to save territory in.");
+ return;
+ }
+ File file = fileOpt.get();
+ if (!file.getName().endsWith(DEFAULT_JAXB_FILE_EXTENSION)) {
+ file = new File(file.getAbsolutePath() + DEFAULT_JAXB_FILE_EXTENSION);
+ }
+ logger.debug("save territory from jaxb-file {}", file);
+ try (Writer w = new FileWriter(file)) {
+ JAXBContext context = JAXBContext.newInstance(TerritoryState.class, Nut.class, Screw.class, Accu.class,
+ Stockpile.class, PileOfScrap.class, Hollow.class);
+ Marshaller m = context.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ m.marshal(mainStage.getTerritory().save(), w);
+ } catch (IOException | JAXBException e) {
+ logger.debug("failed to save jaxb.", e);
+ }
+ }
+
+ /**
+ * Opens a dialog to ask for a file to save the territory in.
+ *
+ * @param title the title of the dialog
+ * @param description file description for the allowed files
+ * @param fileExtension allowed file-extension
+ * @return a file to save the territory in
+ */
+ private Optional getSaveFile(String title, String description, String fileExtension) {
+ FileChooser chooser = new FileChooser();
+ chooser.setTitle(title);
+ chooser.setInitialDirectory(new File(ProgramController.PATH_TO_PROGRAMS));
+ chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(description, "*" + fileExtension));
+ return Optional.ofNullable(chooser.showSaveDialog(mainStage));
+ }
+
+ /**
+ * Opens a dialog to ask for a file to load a territory from.
+ *
+ * @param title the title of the dialog
+ * @param description file description for allowed files
+ * @param fileExtension allowed file-extension
+ * @return a file to load a territory from
+ */
+ public Optional getLoadFile(String title, String description, String fileExtension) {
+ FileChooser fileChooser = new FileChooser();
+ fileChooser.setTitle(title);
+ fileChooser.setInitialDirectory(new File(ProgramController.PATH_TO_PROGRAMS));
+ fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(description, "*" + fileExtension));
+ return Optional.ofNullable(fileChooser.showOpenDialog(mainStage));
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/Example.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/Example.java
index f53cd69..e49cd4b 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/Example.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/Example.java
@@ -1,56 +1,46 @@
package com.JayPi4c.RobbiSimulator.controller.examples;
-import java.util.List;
-
import com.JayPi4c.RobbiSimulator.controller.program.ProgramController;
-
-import jakarta.persistence.CollectionTable;
-import jakarta.persistence.Column;
-import jakarta.persistence.ElementCollection;
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.Lob;
-import jakarta.persistence.Table;
+import jakarta.persistence.*;
import lombok.Data;
+import java.util.List;
+
/**
* This class holds all information needed for an example to be loaded. It
* provides a method to load a new MainStage with the given Information.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Data
@Entity
@Table(name = "EXAMPLES")
public class Example {
- @Id
- @Column(unique = true, nullable = false)
- @GeneratedValue(strategy = GenerationType.AUTO)
- private int id;
+ @Id
+ @Column(unique = true, nullable = false)
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private int id;
- private String programName;
+ private String programName;
- @Lob
- @Column(columnDefinition = "clob")
- private String code;
+ @Lob
+ @Column(columnDefinition = "clob")
+ private String code;
- @Lob
- @Column(columnDefinition = "clob")
- private String territory;
+ @Lob
+ @Column(columnDefinition = "clob")
+ private String territory;
- @ElementCollection
- @CollectionTable(name = "TAGS")
- private List tags;
+ @ElementCollection
+ @CollectionTable(name = "TAGS")
+ private List tags;
- /**
- * Loads a new MainStage with the given information.
- */
- public void load() {
- ProgramController.createAndShow(programName, code, territory);
- }
+ /**
+ * Loads a new MainStage with the given information.
+ */
+ public void load() {
+ ProgramController.createAndShow(programName, code, territory);
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/ExampleService.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/ExampleService.java
index 53cbdd8..51b9a3b 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/ExampleService.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/ExampleService.java
@@ -1,21 +1,19 @@
package com.JayPi4c.RobbiSimulator.controller.examples;
-import java.util.List;
-import java.util.Optional;
-
-import org.hibernate.Session;
-
import com.JayPi4c.RobbiSimulator.utils.HibernateUtils;
-
import javafx.util.Pair;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.hibernate.Session;
+
+import java.util.List;
+import java.util.Optional;
/**
* Service to easily access examples from the database using the HibernateUtils
* class.
- *
+ *
* @author Jonas Pohl
* @since 1.0.0
*/
@@ -23,79 +21,79 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExampleService {
- /**
- * Method to store an example with its tags in the database.
- *
- * @param programName the name of the program
- * @param editorContent the code in the editor
- * @param territoryXML the territory encoded in XML
- * @param tags the tags related to this example
- * @return true if the example was stored successfully, false otherwise
- */
- public static boolean store(String programName, String editorContent, String territoryXML, List tags) {
- Example example = new Example();
- example.setProgramName(programName);
- example.setCode(editorContent);
- example.setTerritory(territoryXML);
- example.setTags(tags);
+ /**
+ * Method to store an example with its tags in the database.
+ *
+ * @param programName the name of the program
+ * @param editorContent the code in the editor
+ * @param territoryXML the territory encoded in XML
+ * @param tags the tags related to this example
+ * @return true if the example was stored successfully, false otherwise
+ */
+ public static boolean store(String programName, String editorContent, String territoryXML, List tags) {
+ Example example = new Example();
+ example.setProgramName(programName);
+ example.setCode(editorContent);
+ example.setTerritory(territoryXML);
+ example.setTags(tags);
- try (Session session = HibernateUtils.getSessionFactory().openSession()) {
- session.beginTransaction();
- session.merge(example);
- session.getTransaction().commit();
- return true;
- } catch (Exception e) {
- logger.error("Could not store example", e);
- return false;
- }
- }
+ try (Session session = HibernateUtils.getSessionFactory().openSession()) {
+ session.beginTransaction();
+ session.merge(example);
+ session.getTransaction().commit();
+ return true;
+ } catch (Exception e) {
+ logger.error("Could not store example", e);
+ return false;
+ }
+ }
- /**
- * Method to get all examples identified by id and programName by their tag.
- *
- * @param tag the tag to search the examples for
- * @return List of examples as pairs of id and programName
- */
- public static Optional>> query(String tag) {
- try (Session session = HibernateUtils.getSessionFactory().openSession()) {
- List allExamples = session.createQuery("from Example", Example.class).list();
+ /**
+ * Method to get all examples identified by id and programName by their tag.
+ *
+ * @param tag the tag to search the examples for
+ * @return List of examples as pairs of id and programName
+ */
+ public static Optional>> query(String tag) {
+ try (Session session = HibernateUtils.getSessionFactory().openSession()) {
+ List allExamples = session.createQuery("from Example", Example.class).list();
- List taggedExamples = allExamples.stream().filter(ex -> ex.getTags().contains(tag)).toList();
+ List taggedExamples = allExamples.stream().filter(ex -> ex.getTags().contains(tag)).toList();
- return Optional.of(taggedExamples.stream().map(ex -> new Pair<>(ex.getId(), ex.getProgramName())).toList());
- }
- }
+ return Optional.of(taggedExamples.stream().map(ex -> new Pair<>(ex.getId(), ex.getProgramName())).toList());
+ }
+ }
- /**
- * Loads an example from the database by the given id.
- *
- * @param id the ID of the example to load
- * @return Optional containing the example or an empty Optional if no example
- * could be found
- */
- public static Optional loadExample(int id) {
- Example example;
- try (Session session = HibernateUtils.getSessionFactory().openSession()) {
- session.beginTransaction();
- example = session.get(Example.class, id);
- session.getTransaction().commit();
- }
- return Optional.ofNullable(example);
- }
+ /**
+ * Loads an example from the database by the given id.
+ *
+ * @param id the ID of the example to load
+ * @return Optional containing the example or an empty Optional if no example
+ * could be found
+ */
+ public static Optional loadExample(int id) {
+ Example example;
+ try (Session session = HibernateUtils.getSessionFactory().openSession()) {
+ session.beginTransaction();
+ example = session.get(Example.class, id);
+ session.getTransaction().commit();
+ }
+ return Optional.ofNullable(example);
+ }
- /**
- * Method to load all distinct tags from the database.
- *
- * @return List of all distinct tags stored in the database
- */
- public static Optional> getAllTags() {
- List tags;
- try (Session session = HibernateUtils.getSessionFactory().openSession()) {
- List allExamples = session.createQuery("from Example", Example.class).list();
- logger.debug("Found {} examples", allExamples.size());
- tags = allExamples.stream().flatMap(ex -> ex.getTags().stream()).distinct().toList();
- }
- return Optional.of(tags);
- }
+ /**
+ * Method to load all distinct tags from the database.
+ *
+ * @return List of all distinct tags stored in the database
+ */
+ public static Optional> getAllTags() {
+ List tags;
+ try (Session session = HibernateUtils.getSessionFactory().openSession()) {
+ List allExamples = session.createQuery("from Example", Example.class).list();
+ logger.debug("Found {} examples", allExamples.size());
+ tags = allExamples.stream().flatMap(ex -> ex.getTags().stream()).distinct().toList();
+ }
+ return Optional.of(tags);
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/ExamplesController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/ExamplesController.java
index 3cf9589..41eb404 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/ExamplesController.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/examples/ExamplesController.java
@@ -1,14 +1,6 @@
package com.JayPi4c.RobbiSimulator.controller.examples;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import java.util.StringTokenizer;
-
import com.JayPi4c.RobbiSimulator.view.MainStage;
-
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
@@ -18,350 +10,346 @@
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
-import javafx.scene.control.ButtonType;
-import javafx.scene.control.ComboBox;
-import javafx.scene.control.Control;
-import javafx.scene.control.Dialog;
-import javafx.scene.control.DialogPane;
-import javafx.scene.control.Label;
-import javafx.scene.control.ListView;
-import javafx.scene.control.TextField;
+import javafx.scene.control.*;
import javafx.scene.control.skin.ComboBoxListViewSkin;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.StringTokenizer;
+
+import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
+
/**
* This controller contains all settings for the examples menus.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
public class ExamplesController {
- private MainStage stage;
-
- // language keys
- private static final String EXAMPLES_LOAD_DIALOG_TAGS_FAIL = "Examples.load.dialog.tags.fail";
- private static final String EXAMPLES_LOAD_DIALOG_PROGRAM_TITLE = "Examples.load.dialog.program.title";
- private static final String EXAMPLES_LOAD_DIALOG_PROGRAM_HEADER = "Examples.load.dialog.program.header";
- private static final String EXAMPLES_LOAD_DIALOG_PROGRAM_NAME = "Examples.load.dialog.program.name";
- private static final String EXAMPLES_LOAD_DIALOG_TAGS_TITLE = "Examples.load.dialog.tags.title";
- private static final String EXAMPLES_LOAD_DIALOG_TAGS_HEADER = "Examples.load.dialog.tags.header";
- private static final String EXAMPLES_LOAD_DIALOG_TAGS_NAME = "Examples.load.dialog.tags.name";
- private static final String EXAMPLES_SAVE_TAGS_TITLE = "Examples.save.tags.title";
- private static final String EXAMPLES_SAVE_TAGS_HEADER = "Examples.save.tags.header";
- private static final String EXAMPLES_SAVE_TAGS_PROMPT = "Examples.save.tags.prompt";
- private static final String EXAMPLES_SAVE_TAGS_NAME = "Examples.save.tags.name";
-
- /**
- * Constructor to create a new ExamplesController for the mainStage.
- *
- * @param stage the mainStage, this controller is for
- */
- public ExamplesController(MainStage stage) {
- this.stage = stage;
-
- stage.getMenubar().getSaveExampleMenuItem().setOnAction(e -> {
- Optional> tags = enterTags();
- tags.ifPresentOrElse(ts -> {
- String territoryXML = stage.getTerritory().toXML().toString();
- if (!ExampleService.store(stage.getProgram().getName(), stage.getProgram().getEditorContent(),
- territoryXML, ts))
- logger.debug("Could not save example in database");
- }, () -> logger.debug("No tags were entered"));
- });
-
- stage.getMenubar().getLoadExampleMenuItem().setOnAction(e -> {
- Optional> tagsOpt = ExampleService.getAllTags();
- tagsOpt.ifPresentOrElse(tags -> {
- Optional s = showTagSelection(tags);
- s.ifPresentOrElse(selectedTag -> {
- Optional>> programsOpt = ExampleService.query(selectedTag);
- if (programsOpt.isPresent()) {
- Optional idOpt = showProgramSelection(programsOpt.get());
- idOpt.ifPresentOrElse(id -> {
- Optional exOpt = ExampleService.loadExample(id);
- exOpt.ifPresentOrElse(Example::load,
- () -> logger.debug("Could not load example from database"));
- }, () -> logger.debug("No example selected"));
- }
- }, () -> logger.debug("No tag selected"));
- }, () -> {
- logger.info("No tags are stored in database");
- stage.getSnackbarController().showMessage(EXAMPLES_LOAD_DIALOG_TAGS_FAIL);
- });
-
- });
- }
-
- /**
- *
- * Shows an DialogWindow listing all programNames and its IDs. The user can
- * select a program, which will be returned as an Optional containing the id.
- *
- * @param programs a list of pairs of IDs and programNames, representing a
- * program
- * @return the id of the selected Program
- */
- public Optional showProgramSelection(List> programs) {
- Dialog dialog = new Dialog<>();
- dialog.setTitle(i18n(EXAMPLES_LOAD_DIALOG_PROGRAM_TITLE));
- dialog.setHeaderText(i18n(EXAMPLES_LOAD_DIALOG_PROGRAM_HEADER));
- dialog.initOwner(stage);
- DialogPane dialogPane = dialog.getDialogPane();
- dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
-
- ComboBox>> comboBox = createComboBoxWithAutoCompletionSupport(programs);
- comboBox.getSelectionModel().select(0);
- GridPane grid = new GridPane();
- grid.addRow(0, new Label(i18n(EXAMPLES_LOAD_DIALOG_PROGRAM_NAME)), comboBox);
-
- dialogPane.setContent(grid);
- Platform.runLater(comboBox::requestFocus);
- dialog.setResultConverter(
- button -> (button == ButtonType.OK) ? comboBox.getValue().getObject().getKey() : null);
- return dialog.showAndWait();
- }
-
- /**
- * Shows an DialogWindow listing all tags. The user can select a tag, which will
- * be returned as an Optional.
- *
- * @param tags a list of tags to be shown to the user
- * @return the selected tag
- */
- public Optional showTagSelection(List tags) {
- Dialog dialog = new Dialog<>();
- dialog.setTitle(i18n(EXAMPLES_LOAD_DIALOG_TAGS_TITLE));
- dialog.setHeaderText(i18n(EXAMPLES_LOAD_DIALOG_TAGS_HEADER));
- dialog.initOwner(stage);
- DialogPane dialogPane = dialog.getDialogPane();
- dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
-
- ComboBox> comboBox = createComboBoxWithAutoCompletionSupport(tags);
- comboBox.getSelectionModel().select(0);
- GridPane grid = new GridPane();
- grid.addRow(0, new Label(i18n(EXAMPLES_LOAD_DIALOG_TAGS_NAME)), comboBox);
-
- dialogPane.setContent(grid);
- Platform.runLater(comboBox::requestFocus);
- dialog.setResultConverter(button -> (button == ButtonType.OK) ? comboBox.getValue().toString() : null);
- return dialog.showAndWait();
- }
-
- /**
- * Opens a dialog for the user to enter tags for the example to save them
- * by.
- * Tags must be entered comma-separated.
- *
- * @return a List of tags
- */
- private Optional> enterTags() {
- Dialog dialog = new Dialog<>();
- dialog.setTitle(i18n(EXAMPLES_SAVE_TAGS_TITLE));
- dialog.setHeaderText(i18n(EXAMPLES_SAVE_TAGS_HEADER));
- dialog.initOwner(stage);
- DialogPane dialogPane = dialog.getDialogPane();
- dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
- TextField tagsField = new TextField();
- tagsField.setPromptText(i18n(EXAMPLES_SAVE_TAGS_PROMPT));
-
- tagsField.textProperty().addListener((observable, oldVal, newVal) -> dialog.getDialogPane()
- .lookupButton(ButtonType.OK).setDisable(newVal.isBlank()));
-
- dialog.getDialogPane().lookupButton(ButtonType.OK).setDisable(true);
- GridPane grid = new GridPane();
- grid.addRow(0, new Label(i18n(EXAMPLES_SAVE_TAGS_NAME)), tagsField);
-
- dialogPane.setContent(grid);
- Platform.runLater(tagsField::requestFocus);
- dialog.setResultConverter(button -> (button == ButtonType.OK) ? tagsField.getText() : null);
-
- Optional result = dialog.showAndWait();
- if (result.isPresent()) {
- StringTokenizer tokenizer = new StringTokenizer(result.get());
- List tags = new ArrayList<>();
- while (tokenizer.hasMoreTokens()) {
- String token = tokenizer.nextToken();
- if (!tags.contains(token))
- tags.add(token);
- }
- return Optional.of(tags);
- } else
- return Optional.empty();
- }
-
- /**
- * Taken from
- * Stackoverflow.
- * This class holds information for the entries of the AutocompletionComboBox.
- *
- * @author Eng.Fouad
- *
- * @param Type of the objects stored in the instance
- */
- private static class HideableItem {
- private final ObjectProperty object = new SimpleObjectProperty<>();
- private final BooleanProperty hidden = new SimpleBooleanProperty();
-
- /**
- * Constructor to create a new HideableItem.
- *
- * @param object Object to be stored in the item.
- */
- private HideableItem(T object) {
- setObject(object);
- }
-
- /**
- * Getter for the ObjectProperty attribute
- *
- * @return the items objectProperty
- */
- private ObjectProperty objectProperty() {
- return this.object;
- }
-
- /**
- * Getter for the value stored in the item.
- *
- * @return the items value
- */
- private T getObject() {
- return this.objectProperty().get();
- }
-
- /**
- * Setter for the value stored in the item.
- *
- * @param object the items new value
- */
- private void setObject(T object) {
- this.objectProperty().set(object);
- }
-
- /**
- * Getter for the hiddenProperty attribute
- *
- * @return the items hiddenProperty
- */
- private BooleanProperty hiddenProperty() {
- return this.hidden;
- }
-
- /**
- * Getter for the hidden value of this item.
- *
- * @return true if the item is hidden, false otherwise
- */
- private boolean isHidden() {
- return this.hiddenProperty().get();
- }
-
- /**
- * Setter for the hidden value of this item.
- *
- * @param hidden the new hidden value
- */
- private void setHidden(boolean hidden) {
- this.hiddenProperty().set(hidden);
- }
-
- @Override
- public String toString() {
- return getObject() == null ? null : getObject().toString();
- }
- }
-
- /**
- * Taken from
- * Stackoverflow.
- *
- * In order to allow a quick search over the attributes in the comboBox, this
- * comboBox has the option to type in the name of the entry and if it is present
- * it will show the entry and select it.
- *
- * @param Type of the items stored in the comboBox
- * @param items the items to store in the ComboBox.
- * @return a comboBox, that supports Auto-Completion
- */
- private static ComboBox> createComboBoxWithAutoCompletionSupport(List items) {
- ObservableList> hideableHideableItems = FXCollections
- .observableArrayList(hidealbeItem -> new Observable[] { hidealbeItem.hiddenProperty() });
-
- items.forEach(item -> {
- HideableItem hideableItem = new HideableItem<>(item);
- hideableHideableItems.add(hideableItem);
- });
-
- FilteredList> filteredHideableItems = new FilteredList<>(hideableHideableItems,
- t -> !t.isHidden());
-
- ComboBox> comboBox = new ComboBox<>();
- comboBox.setItems(filteredHideableItems);
-
- @SuppressWarnings("unchecked")
- HideableItem[] selectedItem = new HideableItem[1];
-
- comboBox.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
- if (!comboBox.isShowing())
- return;
- comboBox.setEditable(true);
- comboBox.getEditor().clear();
- });
-
- comboBox.showingProperty().addListener((obs, oldVal, newVal) -> {
- if (Boolean.TRUE.equals(newVal)) {
- @SuppressWarnings("unchecked")
- ListView> lv = (ListView>) ((ComboBoxListViewSkin>) comboBox
- .getSkin()).getPopupContent();
-
- Platform.runLater(() -> {
- if (selectedItem[0] == null) { // first use
- double cellHeight = ((Control) lv.lookup(".list-cell")).getHeight();
- lv.setFixedCellSize(cellHeight);
- }
- });
- lv.scrollTo(comboBox.getValue());
- } else {
- HideableItem value = comboBox.getValue();
- if (value != null)
- selectedItem[0] = value;
- comboBox.setEditable(false);
- Platform.runLater(() -> {
- comboBox.getSelectionModel().select(selectedItem[0]);
- comboBox.setValue(selectedItem[0]);
- });
- }
- });
-
- comboBox.setOnHidden(event -> hideableHideableItems.forEach(item -> item.setHidden(false)));
-
- comboBox.getEditor().textProperty().addListener((obs, oldVal, newVal) -> {
- if (!comboBox.isShowing())
- return;
-
- Platform.runLater(() -> {
- if (comboBox.getSelectionModel().getSelectedItem() == null) {
- hideableHideableItems.forEach(item -> item
- .setHidden(!item.getObject().toString().toLowerCase().contains(newVal.toLowerCase())));
- } else {
- boolean validText = false;
- for (HideableItem> hideableItem : hideableHideableItems) {
- if (hideableItem.getObject().toString().equals(newVal)) {
- validText = true;
- break;
- }
- }
- if (!validText)
- comboBox.getSelectionModel().select(null);
- }
- });
- });
- return comboBox;
- }
+ // language keys
+ private static final String EXAMPLES_LOAD_DIALOG_TAGS_FAIL = "Examples.load.dialog.tags.fail";
+ private static final String EXAMPLES_LOAD_DIALOG_PROGRAM_TITLE = "Examples.load.dialog.program.title";
+ private static final String EXAMPLES_LOAD_DIALOG_PROGRAM_HEADER = "Examples.load.dialog.program.header";
+ private static final String EXAMPLES_LOAD_DIALOG_PROGRAM_NAME = "Examples.load.dialog.program.name";
+ private static final String EXAMPLES_LOAD_DIALOG_TAGS_TITLE = "Examples.load.dialog.tags.title";
+ private static final String EXAMPLES_LOAD_DIALOG_TAGS_HEADER = "Examples.load.dialog.tags.header";
+ private static final String EXAMPLES_LOAD_DIALOG_TAGS_NAME = "Examples.load.dialog.tags.name";
+ private static final String EXAMPLES_SAVE_TAGS_TITLE = "Examples.save.tags.title";
+ private static final String EXAMPLES_SAVE_TAGS_HEADER = "Examples.save.tags.header";
+ private static final String EXAMPLES_SAVE_TAGS_PROMPT = "Examples.save.tags.prompt";
+ private static final String EXAMPLES_SAVE_TAGS_NAME = "Examples.save.tags.name";
+ private MainStage stage;
+
+ /**
+ * Constructor to create a new ExamplesController for the mainStage.
+ *
+ * @param stage the mainStage, this controller is for
+ */
+ public ExamplesController(MainStage stage) {
+ this.stage = stage;
+
+ stage.getMenubar().getSaveExampleMenuItem().setOnAction(e -> {
+ Optional> tags = enterTags();
+ tags.ifPresentOrElse(ts -> {
+ String territoryXML = stage.getTerritory().toXML().toString();
+ if (!ExampleService.store(stage.getProgram().getName(), stage.getProgram().getEditorContent(),
+ territoryXML, ts))
+ logger.debug("Could not save example in database");
+ }, () -> logger.debug("No tags were entered"));
+ });
+
+ stage.getMenubar().getLoadExampleMenuItem().setOnAction(e -> {
+ Optional> tagsOpt = ExampleService.getAllTags();
+ tagsOpt.ifPresentOrElse(tags -> {
+ Optional s = showTagSelection(tags);
+ s.ifPresentOrElse(selectedTag -> {
+ Optional>> programsOpt = ExampleService.query(selectedTag);
+ if (programsOpt.isPresent()) {
+ Optional idOpt = showProgramSelection(programsOpt.get());
+ idOpt.ifPresentOrElse(id -> {
+ Optional exOpt = ExampleService.loadExample(id);
+ exOpt.ifPresentOrElse(Example::load,
+ () -> logger.debug("Could not load example from database"));
+ }, () -> logger.debug("No example selected"));
+ }
+ }, () -> logger.debug("No tag selected"));
+ }, () -> {
+ logger.info("No tags are stored in database");
+ stage.getNotificationController().showMessage(3000, EXAMPLES_LOAD_DIALOG_TAGS_FAIL);
+ });
+
+ });
+ }
+
+ /**
+ * Taken from
+ * Stackoverflow.
+ *
+ * In order to allow a quick search over the attributes in the comboBox, this
+ * comboBox has the option to type in the name of the entry and if it is present
+ * it will show the entry and select it.
+ *
+ * @param Type of the items stored in the comboBox
+ * @param items the items to store in the ComboBox.
+ * @return a comboBox, that supports Auto-Completion
+ */
+ private static ComboBox> createComboBoxWithAutoCompletionSupport(List items) {
+ ObservableList> hideableHideableItems = FXCollections
+ .observableArrayList(hidealbeItem -> new Observable[]{hidealbeItem.hiddenProperty()});
+
+ items.forEach(item -> {
+ HideableItem hideableItem = new HideableItem<>(item);
+ hideableHideableItems.add(hideableItem);
+ });
+
+ FilteredList> filteredHideableItems = new FilteredList<>(hideableHideableItems,
+ t -> !t.isHidden());
+
+ ComboBox> comboBox = new ComboBox<>();
+ comboBox.setItems(filteredHideableItems);
+
+ @SuppressWarnings("unchecked")
+ HideableItem[] selectedItem = new HideableItem[1];
+
+ comboBox.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
+ if (!comboBox.isShowing())
+ return;
+ comboBox.setEditable(true);
+ comboBox.getEditor().clear();
+ });
+
+ comboBox.showingProperty().addListener((obs, oldVal, newVal) -> {
+ if (Boolean.TRUE.equals(newVal)) {
+ @SuppressWarnings("unchecked")
+ ListView> lv = (ListView>) ((ComboBoxListViewSkin>) comboBox
+ .getSkin()).getPopupContent();
+
+ Platform.runLater(() -> {
+ if (selectedItem[0] == null) { // first use
+ double cellHeight = ((Control) lv.lookup(".list-cell")).getHeight();
+ lv.setFixedCellSize(cellHeight);
+ }
+ });
+ lv.scrollTo(comboBox.getValue());
+ } else {
+ HideableItem value = comboBox.getValue();
+ if (value != null)
+ selectedItem[0] = value;
+ comboBox.setEditable(false);
+ Platform.runLater(() -> {
+ comboBox.getSelectionModel().select(selectedItem[0]);
+ comboBox.setValue(selectedItem[0]);
+ });
+ }
+ });
+
+ comboBox.setOnHidden(event -> hideableHideableItems.forEach(item -> item.setHidden(false)));
+
+ comboBox.getEditor().textProperty().addListener((obs, oldVal, newVal) -> {
+ if (!comboBox.isShowing())
+ return;
+
+ Platform.runLater(() -> {
+ if (comboBox.getSelectionModel().getSelectedItem() == null) {
+ hideableHideableItems.forEach(item -> item
+ .setHidden(!item.getObject().toString().toLowerCase().contains(newVal.toLowerCase())));
+ } else {
+ boolean validText = false;
+ for (HideableItem> hideableItem : hideableHideableItems) {
+ if (hideableItem.getObject().toString().equals(newVal)) {
+ validText = true;
+ break;
+ }
+ }
+ if (!validText)
+ comboBox.getSelectionModel().select(null);
+ }
+ });
+ });
+ return comboBox;
+ }
+
+ /**
+ * Shows an DialogWindow listing all programNames and its IDs. The user can
+ * select a program, which will be returned as an Optional containing the id.
+ *
+ * @param programs a list of pairs of IDs and programNames, representing a
+ * program
+ * @return the id of the selected Program
+ */
+ public Optional showProgramSelection(List> programs) {
+ Dialog dialog = new Dialog<>();
+ dialog.setTitle(i18n(EXAMPLES_LOAD_DIALOG_PROGRAM_TITLE));
+ dialog.setHeaderText(i18n(EXAMPLES_LOAD_DIALOG_PROGRAM_HEADER));
+ dialog.initOwner(stage);
+ DialogPane dialogPane = dialog.getDialogPane();
+ dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
+
+ ComboBox>> comboBox = createComboBoxWithAutoCompletionSupport(programs);
+ comboBox.getSelectionModel().select(0);
+ GridPane grid = new GridPane();
+ grid.addRow(0, new Label(i18n(EXAMPLES_LOAD_DIALOG_PROGRAM_NAME)), comboBox);
+
+ dialogPane.setContent(grid);
+ Platform.runLater(comboBox::requestFocus);
+ dialog.setResultConverter(
+ button -> (button == ButtonType.OK) ? comboBox.getValue().getObject().getKey() : null);
+ return dialog.showAndWait();
+ }
+
+ /**
+ * Shows an DialogWindow listing all tags. The user can select a tag, which will
+ * be returned as an Optional.
+ *
+ * @param tags a list of tags to be shown to the user
+ * @return the selected tag
+ */
+ public Optional showTagSelection(List tags) {
+ Dialog dialog = new Dialog<>();
+ dialog.setTitle(i18n(EXAMPLES_LOAD_DIALOG_TAGS_TITLE));
+ dialog.setHeaderText(i18n(EXAMPLES_LOAD_DIALOG_TAGS_HEADER));
+ dialog.initOwner(stage);
+ DialogPane dialogPane = dialog.getDialogPane();
+ dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
+
+ ComboBox> comboBox = createComboBoxWithAutoCompletionSupport(tags);
+ comboBox.getSelectionModel().select(0);
+ GridPane grid = new GridPane();
+ grid.addRow(0, new Label(i18n(EXAMPLES_LOAD_DIALOG_TAGS_NAME)), comboBox);
+
+ dialogPane.setContent(grid);
+ Platform.runLater(comboBox::requestFocus);
+ dialog.setResultConverter(button -> (button == ButtonType.OK) ? comboBox.getValue().toString() : null);
+ return dialog.showAndWait();
+ }
+
+ /**
+ * Opens a dialog for the user to enter tags for the example to save them
+ * by.
+ * Tags must be entered comma-separated.
+ *
+ * @return a List of tags
+ */
+ private Optional> enterTags() {
+ Dialog dialog = new Dialog<>();
+ dialog.setTitle(i18n(EXAMPLES_SAVE_TAGS_TITLE));
+ dialog.setHeaderText(i18n(EXAMPLES_SAVE_TAGS_HEADER));
+ dialog.initOwner(stage);
+ DialogPane dialogPane = dialog.getDialogPane();
+ dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
+ TextField tagsField = new TextField();
+ tagsField.setPromptText(i18n(EXAMPLES_SAVE_TAGS_PROMPT));
+
+ tagsField.textProperty().addListener((observable, oldVal, newVal) -> dialog.getDialogPane()
+ .lookupButton(ButtonType.OK).setDisable(newVal.isBlank()));
+
+ dialog.getDialogPane().lookupButton(ButtonType.OK).setDisable(true);
+ GridPane grid = new GridPane();
+ grid.addRow(0, new Label(i18n(EXAMPLES_SAVE_TAGS_NAME)), tagsField);
+
+ dialogPane.setContent(grid);
+ Platform.runLater(tagsField::requestFocus);
+ dialog.setResultConverter(button -> (button == ButtonType.OK) ? tagsField.getText() : null);
+
+ Optional result = dialog.showAndWait();
+ if (result.isPresent()) {
+ StringTokenizer tokenizer = new StringTokenizer(result.get());
+ List tags = new ArrayList<>();
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (!tags.contains(token))
+ tags.add(token);
+ }
+ return Optional.of(tags);
+ } else
+ return Optional.empty();
+ }
+
+ /**
+ * Taken from
+ * Stackoverflow.
+ * This class holds information for the entries of the AutocompletionComboBox.
+ *
+ * @param Type of the objects stored in the instance
+ * @author Eng.Fouad
+ */
+ private static class HideableItem {
+ private final ObjectProperty object = new SimpleObjectProperty<>();
+ private final BooleanProperty hidden = new SimpleBooleanProperty();
+
+ /**
+ * Constructor to create a new HideableItem.
+ *
+ * @param object Object to be stored in the item.
+ */
+ private HideableItem(T object) {
+ setObject(object);
+ }
+
+ /**
+ * Getter for the ObjectProperty attribute
+ *
+ * @return the items objectProperty
+ */
+ private ObjectProperty objectProperty() {
+ return this.object;
+ }
+
+ /**
+ * Getter for the value stored in the item.
+ *
+ * @return the items value
+ */
+ private T getObject() {
+ return this.objectProperty().get();
+ }
+
+ /**
+ * Setter for the value stored in the item.
+ *
+ * @param object the items new value
+ */
+ private void setObject(T object) {
+ this.objectProperty().set(object);
+ }
+
+ /**
+ * Getter for the hiddenProperty attribute
+ *
+ * @return the items hiddenProperty
+ */
+ private BooleanProperty hiddenProperty() {
+ return this.hidden;
+ }
+
+ /**
+ * Getter for the hidden value of this item.
+ *
+ * @return true if the item is hidden, false otherwise
+ */
+ private boolean isHidden() {
+ return this.hiddenProperty().get();
+ }
+
+ /**
+ * Setter for the hidden value of this item.
+ *
+ * @param hidden the new hidden value
+ */
+ private void setHidden(boolean hidden) {
+ this.hiddenProperty().set(hidden);
+ }
+
+ @Override
+ public String toString() {
+ return getObject() == null ? null : getObject().toString();
+ }
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/Diagnostics.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/Diagnostics.java
index a7dd7c4..a58bf3a 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/Diagnostics.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/Diagnostics.java
@@ -4,52 +4,49 @@
import java.util.List;
/**
- *
* This class contains a list of Diagnostics, which are created during the
* post-compile annotation check.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class Diagnostics {
- private List diags;
-
- /**
- * Constructor for the Diagnostics-class. It creates the list to hold the
- * diagnostics.
- */
- public Diagnostics() {
- diags = new ArrayList<>();
- }
-
- /**
- * Adds the given diagnostic to the list of diagnostics
- *
- * @param d The Diagnostic to be added to the list of diagnostics
- */
- public void add(Diagnostic d) {
- diags.add(d);
- }
-
- /**
- * Returns a list of all collected Diagnostics.
- *
- * @return the list of all diagnostics
- */
- public List getDiagnosis() {
- return diags;
- }
-
- /**
- * Container to hold a single Diagnostic, which consists of a type and the
- * faulty value provided for this type.
- *
- * @author Jonas Pohl
- *
- */
- public record Diagnostic(String type, String value) {
-
- }
+ private final List diags;
+
+ /**
+ * Constructor for the Diagnostics-class. It creates the list to hold the
+ * diagnostics.
+ */
+ public Diagnostics() {
+ diags = new ArrayList<>();
+ }
+
+ /**
+ * Adds the given diagnostic to the list of diagnostics
+ *
+ * @param d The Diagnostic to be added to the list of diagnostics
+ */
+ public void add(Diagnostic d) {
+ diags.add(d);
+ }
+
+ /**
+ * Returns a list of all collected Diagnostics.
+ *
+ * @return the list of all diagnostics
+ */
+ public List getDiagnosis() {
+ return diags;
+ }
+
+ /**
+ * Container to hold a single Diagnostic, which consists of a type and the
+ * faulty value provided for this type.
+ *
+ * @author Jonas Pohl
+ */
+ public record Diagnostic(String type, String value) {
+
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/Program.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/Program.java
index 7685dad..b926aa8 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/Program.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/Program.java
@@ -1,108 +1,103 @@
package com.JayPi4c.RobbiSimulator.controller.program;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-
import com.JayPi4c.RobbiSimulator.utils.Observable;
-
import lombok.Getter;
import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.*;
/**
* This class contains the contents, the name of program and whether it is
* edited or not
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
+@Slf4j
@Getter
public class Program extends Observable {
- /**
- * The name of the program
- */
- @Setter
- private String name;
+ /**
+ * The name of the program
+ */
+ @Setter
+ private String name;
- private String editorContent;
- private File file;
+ private String editorContent;
+ private final File file;
- /**
- * Whether the program is edited or not
- */
- @Setter
- private boolean edited = false;
+ /**
+ * Whether the program is edited or not
+ */
+ @Setter
+ private boolean edited = false;
- /**
- * Creates and loads a program from a given file and the program name
- *
- * @param f the file on the fileSystem storing the program
- * @param name the name of the program
- */
- public Program(File f, String name) {
- this.file = f;
- this.name = name;
- try (BufferedReader reader = new BufferedReader(new FileReader(f))) {
- StringBuilder bobTheBuilder = new StringBuilder();
- String line;
- while ((line = reader.readLine()) != null) {
- bobTheBuilder.append(line);
- bobTheBuilder.append(System.lineSeparator());
- }
+ /**
+ * Creates and loads a program from a given file and the program name
+ *
+ * @param f the file on the fileSystem storing the program
+ * @param name the name of the program
+ */
+ public Program(File f, String name) {
+ this.file = f;
+ this.name = name;
+ try (BufferedReader reader = new BufferedReader(new FileReader(f))) {
+ StringBuilder bobTheBuilder = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ bobTheBuilder.append(line);
+ bobTheBuilder.append(System.lineSeparator());
+ }
- String content = bobTheBuilder.toString();
+ String content = bobTheBuilder.toString();
- editorContent = content.replace(ProgramController.createPrefix(name), "");
- int endIndex = editorContent.lastIndexOf('}');
- bobTheBuilder.setLength(0);
- editorContent = bobTheBuilder.append(editorContent).deleteCharAt(endIndex).toString().trim();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ editorContent = content.replace(ProgramController.createPrefix(name), "");
+ int endIndex = editorContent.lastIndexOf('}');
+ bobTheBuilder.setLength(0);
+ editorContent = bobTheBuilder.append(editorContent).deleteCharAt(endIndex).toString().trim();
+ } catch (IOException e) {
+ logger.error("Could not load program", e);
+ }
+ }
- /**
- * Sets the editorContent and notifies all Observers, namely the
- * MainStageController to update the textEditors content.
- *
- * @param content the new content
- */
- public void setEditorContent(String content) {
- this.editorContent = content;
- this.edited = true;
- this.setChanged();
- this.notifyAllObservers();
- }
+ /**
+ * Sets the editorContent and notifies all Observers, namely the
+ * MainStageController to update the textEditors content.
+ *
+ * @param content the new content
+ */
+ public void setEditorContent(String content) {
+ this.editorContent = content;
+ this.edited = true;
+ this.setChanged();
+ this.notifyAllObservers();
+ }
- /**
- * saves the text of the editor-content into the corresponding file It does only
- * save the given text, if the changes were made
- *
- * @param text the text to save in the file
- */
- public void save(String text) {
- if (!edited)
- return;
+ /**
+ * saves the text of the editor-content into the corresponding file It does only
+ * save the given text, if the changes were made
+ *
+ * @param text the text to save in the file
+ */
+ public void save(String text) {
+ if (!edited)
+ return;
- editorContent = text;
- save();
- }
+ editorContent = text;
+ save();
+ }
- /**
- * Forces the program to be saved even if it might not be edited.
- */
- public void save() {
- String content = ProgramController.createTemplate(name, editorContent);
- try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
- writer.write(content);
- } catch (IOException e) {
- e.printStackTrace();
- }
- edited = false;
- }
+ /**
+ * Forces the program to be saved even if it might not be edited.
+ */
+ public void save() {
+ String content = ProgramController.createTemplate(name, editorContent);
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
+ writer.write(content);
+ } catch (IOException e) {
+ logger.error("Could not save program", e);
+ }
+ edited = false;
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/ProgramController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/ProgramController.java
index 7539e9b..b26cc9e 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/ProgramController.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/program/ProgramController.java
@@ -1,51 +1,12 @@
package com.JayPi4c.RobbiSimulator.controller.program;
-import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Parameter;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-import javax.lang.model.SourceVersion;
-import javax.tools.Diagnostic;
-import javax.tools.DiagnosticCollector;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaCompiler.CompilationTask;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
-
import com.JayPi4c.RobbiSimulator.model.Robbi;
import com.JayPi4c.RobbiSimulator.utils.AlertHelper;
import com.JayPi4c.RobbiSimulator.utils.annotations.Default;
import com.JayPi4c.RobbiSimulator.view.MainStage;
-
import javafx.application.Platform;
-import javafx.scene.control.Alert;
+import javafx.scene.control.*;
import javafx.scene.control.Alert.AlertType;
-import javafx.scene.control.ButtonType;
-import javafx.scene.control.Dialog;
-import javafx.scene.control.DialogPane;
-import javafx.scene.control.Label;
-import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
@@ -55,677 +16,681 @@
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import javax.lang.model.SourceVersion;
+import javax.tools.*;
+import javax.tools.JavaCompiler.CompilationTask;
+import java.io.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static com.JayPi4c.RobbiSimulator.utils.I18nUtils.i18n;
+
/**
* This controller contains all functionality to initialize the application,
* load, save and compile a program. Furthermore, it creates and opens a new
* stage, if a new Program is loaded, or it loads the DefaultProgram on the
* Application start
- *
+ *
* @author Jonas Pohl
- *
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ProgramController {
- /**
- * Constant String with the Path name for the programs directory.
- */
- public static final String PATH_TO_PROGRAMS = "programs";
- /**
- * Constant String for the Default Robbi File name.
- */
- public static final String DEFAULT_ROBBI_FILE_NAME = "DefaultRobbi";
- /**
- * Constant String for the default file extension name.
- */
- public static final String DEFAULT_FILE_EXTENSION = ".java";
- /**
- * Constant String for the default content of the editor when the file is newly
- * created.
- * The comment "// place your code here" could also be internationalized. TODO
- */
- public static final String DEFAULT_CONTENT = "void main(){" + System.lineSeparator() + "\t// place your code here"
- + System.lineSeparator() + "}";
- /**
- * Constant String for the editor prefix which is needed to compile the class
- * and load into the simulator. This String will not be shown in the editor
- * content.
- */
- public static final String PREFIX_TEMPLATE = "import com.JayPi4c.RobbiSimulator.utils.annotations.*;import lombok.extern.slf4j.Slf4j; @Slf4j public class %s extends com.JayPi4c.RobbiSimulator.model.Robbi{";
- /**
- * Constant String for the editor postfix, to close the class and make it
- * compilable. This postfix will not be shown in the editor content.
- */
- public static final String POSTFIX_TEMPLATE = System.lineSeparator() + "}";
-
- private static HashMap programs;
-
- private static URLClassLoader classLoader;
-
- // language keys
- private static final String NEW_DIALOG_TITLE = "New.dialog.title";
- private static final String NEW_DIALOG_HEADER = "New.dialog.header";
- private static final String NEW_DIALOG_PROMPT = "New.dialog.prompt";
- private static final String NEW_DIALOG_NAME = "New.dialog.name";
- private static final String COMPILATION_DIAGNOSTIC_KIND = "Compilation.diagnostic.kind";
- private static final String COMPILATION_DIAGNOSTIC_CODEANDMESSAGE = "Compilation.diagnostic.CodeAndMessage";
- private static final String COMPILATION_DIAGNOSTIC_ROW = "Compilation.diagnostic.row";
- private static final String COMPILATION_DIAGNOSTIC_TITLE = "Compilation.diagnostic.title";
- private static final String COMPILATION_ANNOTATIONS_MSG_DEFAULT = "Compilation.annotations.msg.default";
- private static final String COMPILATION_ANNOTATIONS_MSG_INFO = "Compilation.annotations.msg.info";
- private static final String COMPILATION_ANNOTATIONS_TITLE = "Compilation.annotations.title";
- private static final String COMPILATION_ANNOTATIONS_HEADER = "Compilation.annotations.header";
- private static final String COMPILATION_SUCCESS_MESSAGE = "Compilation.success.message";
- private static final String COMPILATION_SUCCESS_TITLE = "Compilation.success.title";
- private static final String COMPILATION_SUCCESS_HEADER = "Compilation.success.header";
- private static final String COMPILATION_DIAGNOSTIC_OVERRIDE = "Compilation.diagnostic.override";
-
- /**
- * Initializes the Application on startup and makes sure the programs folder and
- * the DefaultRobbi class exists
- *
- * @return true if initialization finished successfully, false otherwise
- */
- public static boolean initialize() {
- File dir = new File(PATH_TO_PROGRAMS);
- if (!dir.exists() && !dir.mkdir()) {
- return false;
- }
-
- File defaultProgram = new File(
- PATH_TO_PROGRAMS + File.separatorChar + DEFAULT_ROBBI_FILE_NAME + DEFAULT_FILE_EXTENSION);
- if (!defaultProgram.exists()) {
- try {
- if (!defaultProgram.createNewFile())
- return false;
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- }
-
- try (BufferedWriter writer = new BufferedWriter(new FileWriter(defaultProgram))) {
- writer.write(createTemplate(DEFAULT_ROBBI_FILE_NAME, DEFAULT_CONTENT));
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- }
- }
- programs = new HashMap<>();
- return true;
- }
-
- /**
- * Looks into the programs directory and collects all java filenames.
- *
- * @return Collection of java filenames in programs directory
- */
- private static Collection getFilenamesInDirectory() {
- // get a list of all files in programs directory that end with .java
- File[] files = new File(PATH_TO_PROGRAMS)
- .listFiles(file -> (file.isFile() && file.getName().endsWith(DEFAULT_FILE_EXTENSION)));
- // get a String collection with all filenames in the programs directory
- Collection filenamesInDirectory = Arrays.stream(files)
- .map(file -> file.getName().replace(DEFAULT_FILE_EXTENSION, ""))
- .collect(Collectors.toCollection(ArrayList::new));
-
- logger.debug("Found following files in 'programs' directory:");
- filenamesInDirectory.forEach(logger::debug);
- return filenamesInDirectory;
- }
-
- /**
- * Creates a Dialog and asks the user to for the name of the new program.
- * Afterwards, it initiates the creation of a new stage for the program.
- *
- * @param parent the parent window to show alerts relative to the parent window
- * @see ProgramController#createAndShow(String)
- */
- public static void createAndShow(Window parent) {
- Optional result = getNameForProgram(parent);
- result.ifPresent(ProgramController::createAndShow);
- }
-
- /**
- * Asks the user to enter a name for the program. It only allows names, that are
- * no java identifiers and are not already used in the programs folder
- *
- * @param parent window to show the dialog relative to
- * @return the new name for the program
- */
- private static Optional getNameForProgram(Window parent) {
- Dialog dialog = new Dialog<>();
- dialog.setTitle(i18n(NEW_DIALOG_TITLE));
- dialog.setHeaderText(i18n(NEW_DIALOG_HEADER));
- dialog.initOwner(parent);
- DialogPane dialogPane = dialog.getDialogPane();
- dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
- TextField nameField = new TextField();
- nameField.setPromptText(i18n(NEW_DIALOG_PROMPT));
-
- Collection filenamesInDirectory = getFilenamesInDirectory();
-
- nameField.textProperty()
- .addListener((observable, oldVal, newVal) -> dialog.getDialogPane().lookupButton(ButtonType.OK)
- .setDisable(SourceVersion.isKeyword(nameField.getText()) // https://stackoverflow.com/a/54141029/13670629
- || !SourceVersion.isIdentifier(nameField.getText())
- // || !nameField.getText().matches(VALID_IDENTIFIER_REGEX)
- || filenamesInDirectory.contains(nameField.getText())));
-
- dialog.getDialogPane().lookupButton(ButtonType.OK).setDisable(true);
- GridPane grid = new GridPane();
- grid.addRow(0, new Label(i18n(NEW_DIALOG_NAME)), nameField);
-
- dialogPane.setContent(grid);
- Platform.runLater(nameField::requestFocus);
- dialog.setResultConverter(button -> (button == ButtonType.OK) ? nameField.getText() : null);
-
- return dialog.showAndWait();
- }
-
- /**
- * Creates a new file with default content, if it does not exist. Afterwards, it
- * creates a program and a new Stage. Finally, it compiles the code and loads
- * the Robbi instance into the simulation
- *
- * @param programName the name of the program to create
- */
- public static void createAndShow(String programName) {
- String content = createTemplate(programName, DEFAULT_CONTENT);
- File f = new File(PATH_TO_PROGRAMS + File.separatorChar + programName + DEFAULT_FILE_EXTENSION);
- if (!f.exists()) {
- try {
- if (!f.createNewFile())
- logger.debug("Could not create file '{}'", f.getAbsolutePath());
- } catch (IOException e) {
- e.printStackTrace();
- }
- try (BufferedWriter writer = new BufferedWriter(new FileWriter(f))) {
- writer.write(content);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- Program program = new Program(f, programName);
- Stage stage = new MainStage(program);
- programs.put(programName, stage);
- ProgramController.compile(program, false, stage);
- }
-
- private static final String EXAMPLES_DUPLICATION_MESSAGE = "Examples.duplication.message";
- private static final String EXAMPLES_DUPLICATION_HEADER = "Examples.duplication.header";
- private static final String EXAMPLES_DUPLICATION_TITLE = "Examples.duplication.title";
-
- /**
- * Creates a stage with the given programName, the programCode provided and the
- * territory encoded as XML. If the user has already a stage with the same name,
- * he will be warned, that his program will be overwritten. Optionally, he can
- * save his program and territory under another name. After that a new Stage
- * will be created according to the given information.
- * This method might only be used to load an example from the database.
- *
- * @param programName name of the program
- * @param programCode code of the program
- * @param territoryXML XML-encoded territory
- */
- public static void createAndShow(String programName, String programCode, String territoryXML) {
-
- String content = createTemplate(programName, DEFAULT_CONTENT);
- File f = new File(PATH_TO_PROGRAMS + File.separatorChar + programName + DEFAULT_FILE_EXTENSION);
- if (f.exists()) {
- logger.debug("There is a file with the name of the example");
- if (programs.containsKey(programName)) {
- logger.debug("Program is opened: closing...");
- MainStage stage = (MainStage) programs.get(programName);
- Program p = stage.getProgram();
- p.save(p.getEditorContent());
- stage.close();
- }
- Alert alert = AlertHelper.createAlert(AlertType.INFORMATION, i18n(EXAMPLES_DUPLICATION_MESSAGE), null);
- alert.setHeaderText(i18n(EXAMPLES_DUPLICATION_HEADER));
- alert.setTitle(i18n(EXAMPLES_DUPLICATION_TITLE));
- alert.getButtonTypes().remove(ButtonType.OK);
- alert.getButtonTypes().addAll(ButtonType.YES, ButtonType.NO);
- Optional result = alert.showAndWait();
- if (result.isPresent()) {
- ButtonType button = result.get();
- if (button.equals(ButtonType.YES)) {
- Optional newName = getNameForProgram(null);
- if (newName.isPresent()) {
- String name = newName.get();
-
- StringBuilder bobTheBuilder = new StringBuilder();
- try (BufferedReader reader = new BufferedReader(new FileReader(f))) {
- String line = null;
- while ((line = reader.readLine()) != null) {
- bobTheBuilder.append(line);
- bobTheBuilder.append(System.lineSeparator());
- }
- bobTheBuilder.replace(0, createPrefix(programName).length(), createPrefix(name));
-
- } catch (IOException e) {
- logger.debug("Failed to read class contents");
- }
- try (BufferedWriter writer = new BufferedWriter(new FileWriter(f))) {
- writer.write(bobTheBuilder.toString());
- } catch (IOException e) {
- logger.debug("Failed to write new classname in file");
- }
- if (!renameFile(f, name)) {
- logger.debug("Failed to rename file");
- }
- }
- }
- }
- }
-
- if (!f.exists()) {
- try {
- if (!f.createNewFile())
- logger.debug("Could not create file '{}'", f.getAbsolutePath());
- } catch (IOException e) {
- e.printStackTrace();
- }
- try (BufferedWriter writer = new BufferedWriter(new FileWriter(f))) {
- writer.write(content);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- Program program = new Program(f, programName);
- program.setEdited(true);
- program.save(programCode);
- MainStage stage = new MainStage(program);
- stage.getTerritory().fromXML(new ByteArrayInputStream(territoryXML.getBytes()));
- programs.put(programName, stage);
- ProgramController.compile(program, false, stage);
- }
-
- /**
- * Renames a java file in the programs directory to the new name.
- *
- * @param f the file to rename
- * @param newName the new name of the file
- * @return true if the renaming was successful, false otherwise
- */
- public static boolean renameFile(File f, String newName) {
- File newFile = new File(PATH_TO_PROGRAMS + File.separatorChar + newName + DEFAULT_FILE_EXTENSION);
-
- if (newFile.exists())
- return false;
- return f.renameTo(newFile);
- }
-
- /**
- * Creates the prefix for the program-file
- *
- * @param name the name of the class
- * @return the prefix for the class
- */
- public static String createPrefix(String name) {
- return String.format(PREFIX_TEMPLATE, name);
- }
-
- /**
- * Creates the postfix for the program-file
- *
- * @return the postfix for the class
- */
- public static String createPostfix() {
- return POSTFIX_TEMPLATE;
- }
-
- /**
- * Creates the template for a compilable class
- *
- * @param name the name of the class
- * @param content the content of the class
- * @return a String containing a compilable java code with the given content
- */
- public static String createTemplate(String name, String content) {
- return createPrefix(name) + content + createPostfix();
-
- }
-
- private static final String OPEN_DIALOG_TITLE = "Open.dialog.title";
- private static final String OPEN_DIALOG_FILTER = "Open.dialog.filter";
-
- /**
- * Opens a FileChooser and loads the selected file. If the file is already
- * loaded, the ProgramController requests the focus for the loaded program.
- * Otherwise it creates a new program and a new stage.
- *
- * @param parent the window to open the chooser relative to the calling window
- */
- public static void openProgram(Window parent) {
- FileChooser fileChooser = new FileChooser();
- fileChooser.setTitle(i18n(OPEN_DIALOG_TITLE));
- fileChooser.setInitialDirectory(new File(PATH_TO_PROGRAMS));
- fileChooser.getExtensionFilters()
- .add(new FileChooser.ExtensionFilter(i18n(OPEN_DIALOG_FILTER), "*" + DEFAULT_FILE_EXTENSION));
-
- File file = fileChooser.showOpenDialog(parent);
- if (file != null) {
- String name = file.getName().replaceFirst(DEFAULT_FILE_EXTENSION, "");
- if (!programs.containsKey(name)) {
- logger.debug("Opening '{}' since it is not loaded yet.", name);
- Program program = new Program(file, name);
- Stage stage = new MainStage(program);
- programs.put(name, stage);
- compile(program, false, parent);
- } else {
- logger.debug("File is already loaded! Requesting focus...");
- programs.get(name).requestFocus();
- }
- }
-
- }
-
- /**
- * Compiles the given Program and shows an error Alert if the Compilation failed
- * otherwise it shows an success alert. If the compilation finished
- * successfully, the new Robbi will be loaded into the territory.
- *
- * @param program the program to compile
- * @param parent the calling window to show alerts relative to the calling
- * window
- */
- public static void compile(Program program, Window parent) {
- compile(program, true, parent);
- }
-
- /**
- * Compiles the given Program and shows an error Alert if the Compilation failed
- * otherwise it shows an success alert. If the compilation finished
- * successfully, the new Robbi will be loaded into the territory. Before it does
- * this, it checks if the Annotations are set correctly and if the main-Method
- * is overwritten. An error with this post-compile check will be visualized with
- * an Alert.
- *
- * @param program the program to compile
- * @param showAlerts flag to determine if the alerts need to be shown or not
- * @param parent the window calling the method in order to show the alerts
- * relative to it
- */
- public static void compile(Program program, boolean showAlerts, Window parent) {
-
- JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
- DiagnosticCollector diagnostics = new DiagnosticCollector<>();
-
- try (StandardJavaFileManager manager = javac.getStandardFileManager(diagnostics, null, null)) {
- Iterable extends JavaFileObject> units = manager
- .getJavaFileObjectsFromFiles(Arrays.asList(program.getFile()));
- // https://stackoverflow.com/questions/60016127/can-toolprovider-getsystemjavacompiler-access-runtime-generated-in-memory-sour
- CompilationTask task = javac.getTask(null, manager, diagnostics, List.of("-p", System.getProperty("jdk.module.path")), null, units);
- task.addModules(List.of("RobbiSimulator")); //https://docs.oracle.com/javase%2F9%2Fdocs%2Fapi%2F%2F/javax/tools/JavaCompiler.CompilationTask.html
-
- if (Boolean.FALSE.equals(task.call())) {
- boolean showedAlert = false; // flag to indicate that only one alert is shown
- diagnostics.toString();
- logger.error("Compilation failed");
- for (Diagnostic> diagnostic : diagnostics.getDiagnostics()) {
- diagnostic.toString();
-
- logger.error("Kind: {}", diagnostic.getKind());
- logger.error("Quelle: {}", diagnostic.getSource());
- logger.error("Code und Nachricht: {}: {}", diagnostic.getCode(), diagnostic.getMessage(null));
- logger.error("Zeile: {}", diagnostic.getLineNumber());
- logger.error("Position/Spalte: {}/{}", diagnostic.getPosition(), diagnostic.getColumnNumber());
- logger.error("Startpostion/Endposition: {}/{}", diagnostic.getStartPosition(),
- diagnostic.getEndPosition());
- // TODO change String.format to use i18n directly
- if (showAlerts && !showedAlert) {
- StringBuilder bobTheBuilder = new StringBuilder();
- bobTheBuilder.append(String.format(i18n(COMPILATION_DIAGNOSTIC_KIND), diagnostic.getKind()));
- bobTheBuilder.append(String.format(i18n(COMPILATION_DIAGNOSTIC_CODEANDMESSAGE),
- diagnostic.getCode(), diagnostic.getMessage(null)));
- bobTheBuilder.append(
- String.format(i18n(COMPILATION_DIAGNOSTIC_ROW), diagnostic.getLineNumber() - 1));
- AlertHelper.showAlertAndWait(AlertType.ERROR, bobTheBuilder.toString(), parent,
- Modality.WINDOW_MODAL, i18n(COMPILATION_DIAGNOSTIC_TITLE),
- diagnostic.getKind().toString());
- showedAlert = true;
- }
- }
- } else {// compilation successful
- logger.info("Compilation successful");
- Optional robbi = loadNewRobbi(program.getName());
-
- robbi.ifPresentOrElse(r -> {
- Diagnostics diag = new Diagnostics();
- if (!hasValidAnnotations(r, diag)) {
- List diags = diag.getDiagnosis();
- String val = null;
- String type = null;
- if (!diags.isEmpty()) {
- Diagnostics.Diagnostic diagnostic = diags.get(0);
- val = diagnostic.value();
- type = diagnostic.type();
- logger.error("[Annotation Error]: {} is not applicable for {}", val, type);
- } else
- logger.error("[Annotation Error]: Error has been found but could not be diagnosed.");
-
- if (showAlerts) {
- String msg = i18n(COMPILATION_ANNOTATIONS_MSG_DEFAULT);
- if (val != null && type != null) {
- msg = String.format(i18n(COMPILATION_ANNOTATIONS_MSG_INFO), val, type);
- }
- AlertHelper.showAlertAndWait(AlertType.WARNING, msg, parent, Modality.WINDOW_MODAL,
- i18n(COMPILATION_ANNOTATIONS_TITLE), i18n(COMPILATION_ANNOTATIONS_HEADER));
- }
- } else {
- if (overwritesMainMethod(r)) {
- // set new Robbi in territory
- MainStage s = (MainStage) programs.get(program.getName());
- s.getTerritory().setRobbi(r);
- logger.debug("New Robbi instance loaded");
- if (showAlerts) {
- // TODO change to snackbar
- AlertHelper.showAlertAndWait(AlertType.INFORMATION,
- String.format(i18n(COMPILATION_SUCCESS_MESSAGE), program.getName()), parent,
- Modality.WINDOW_MODAL, i18n(COMPILATION_SUCCESS_TITLE),
- i18n(COMPILATION_SUCCESS_HEADER));
- }
- } else {
- AlertHelper.showAlertAndWait(AlertType.ERROR, i18n(COMPILATION_DIAGNOSTIC_OVERRIDE),
- parent);
- logger.error("The custom Robbi class does not overwrite the main-Method");
- }
- }
- }, () -> logger.error("Failed to load new Robbi instance..."));
-
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
- /**
- * Checks if the robbi overwrites the Main-Method.
- *
- * @param robbi the robbi to check if it overwrites the Main-Method
- * @return true if robbi overwrites it, false otherwise
- */
- private static boolean overwritesMainMethod(Robbi robbi) {
- if (Robbi.class == robbi.getClass()) {
- return true; // Default Robbi always has main-Method overwritten
- }
- for (Method m : robbi.getClass().getDeclaredMethods()) {
- if (m.getName().equals("main")) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks if the given robbi has valid annotations set. Currently it checks if
- * the default Annotation has values matching its parameter
- *
- * @param robbi Instance of the users robbi implementation to check
- * @return true if the annotions are valid, false otherwise
- */
- private static boolean hasValidAnnotations(Robbi robbi, Diagnostics diag) {
- Method[] methods = getCustomMethods(robbi);
- boolean result = true;
- for (Method method : methods) {
- if (!hasValidDefaultAnnotation(method, diag)) {
- result = false;
-
- // use return to fasten things up. Following annotation errors are ignored
- }
- }
- return result;
- }
-
- /**
- * Checks if the method has Default annotations matching the type of its
- * parameter
- *
- * @param method the method to check the annotations for
- * @return true if and only if all Default annotations match their parameter
- * type, false otherwise
- */
- private static boolean hasValidDefaultAnnotation(Method method, Diagnostics diag) {
- boolean result = true;
- for (Parameter parameter : method.getParameters()) {
- Annotation[] annotations = parameter.getAnnotations();
- for (Annotation annotation : annotations) {
- if (annotation instanceof Default anno && !valueAcceptable(parameter, anno, diag)) {
- result = false;
- }
- }
- }
- return result;
- }
-
- /**
- * Checks if the parameter and the Default Annotation match types. This is done
- * by checking, if the value of the Default annotation can be parsed to the type
- * of the parameter. If it fails, this method returns false.
- *
- * @param parameter The parameter to check the type of
- * @param annotation The annotation whose value has to be checked against the
- * parameter type
- * @return true if the annotation value matches the parameter type, false
- * otherwise
- */
- private static boolean valueAcceptable(Parameter parameter, Default annotation, Diagnostics diag) {
- String val = annotation.value();
- String type = parameter.getType().getName();
- try {
- switch (type) {
- case "int":
- Integer.parseInt(val);
- return true;
- case "boolean":
- return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("false");
- case "char":
- return !val.isBlank();
- case "double":
- Double.parseDouble(val);
- return true;
- case "float":
- Float.parseFloat(val);
- return true;
- case "long":
- Long.parseLong(val);
- return true;
- case "String":
- default:
- return true;
- }
- } catch (IllegalArgumentException | IndexOutOfBoundsException e) {
- diag.add(new Diagnostics.Diagnostic(type, val));
- return false;
- }
-
- }
-
- /**
- * Returns all methods, that are not part of the default robbi implementation,
- * i.e. returns all methods the user has implemented
- *
- * @param robbi the new robbi instance
- * @return an ArrayList of all new methods of the robbi
- */
- private static Method[] getCustomMethods(Robbi robbi) {
- List methods = new ArrayList<>();
- // if robbi is custom class
- if (Robbi.class != robbi.getClass()) {
- methods.addAll(Arrays.asList(robbi.getClass().getDeclaredMethods()));
- }
- return methods.toArray(Method[]::new);
- }
-
- /**
- * Loads a new Robbi by the name of the class
- *
- * @param name the name of the class
- * @return an Optional of the given robbi class
- */
- private static Optional loadNewRobbi(String name) {
- Optional robbi;
- try {
- // if an old classloader exists, close it
- if(classLoader != null)
- classLoader.close();
+ /**
+ * Constant String with the Path name for the programs' directory.
+ */
+ public static final String PATH_TO_PROGRAMS = "programs";
+ /**
+ * Constant String for the Default Robbi File name.
+ */
+ public static final String DEFAULT_ROBBI_FILE_NAME = "DefaultRobbi";
+ /**
+ * Constant String for the default file extension name.
+ */
+ public static final String DEFAULT_FILE_EXTENSION = ".java";
+ /**
+ * Constant String for the default content of the editor when the file is newly
+ * created.
+ * The comment "// place your code here" could also be internationalized. TODO
+ */
+ public static final String DEFAULT_CONTENT = "void main(){" + System.lineSeparator() + "\t// place your code here"
+ + System.lineSeparator() + "}";
+ /**
+ * Constant String for the editor prefix which is needed to compile the class
+ * and load into the simulator. This String will not be shown in the editor
+ * content.
+ */
+ public static final String PREFIX_TEMPLATE = "import com.JayPi4c.RobbiSimulator.utils.annotations.*;import lombok.extern.slf4j.Slf4j; @Slf4j public class %s extends com.JayPi4c.RobbiSimulator.model.Robbi{";
+ /**
+ * Constant String for the editor postfix, to close the class and make it
+ * compilable. This postfix will not be shown in the editor content.
+ */
+ public static final String POSTFIX_TEMPLATE = System.lineSeparator() + "}";
+ // language keys
+ private static final String NEW_DIALOG_TITLE = "New.dialog.title";
+ private static final String NEW_DIALOG_HEADER = "New.dialog.header";
+ private static final String NEW_DIALOG_PROMPT = "New.dialog.prompt";
+ private static final String NEW_DIALOG_NAME = "New.dialog.name";
+ private static final String COMPILATION_DIAGNOSTIC_KIND = "Compilation.diagnostic.kind";
+ private static final String COMPILATION_DIAGNOSTIC_CODEANDMESSAGE = "Compilation.diagnostic.CodeAndMessage";
+ private static final String COMPILATION_DIAGNOSTIC_ROW = "Compilation.diagnostic.row";
+ private static final String COMPILATION_DIAGNOSTIC_TITLE = "Compilation.diagnostic.title";
+ private static final String COMPILATION_ANNOTATIONS_MSG_DEFAULT = "Compilation.annotations.msg.default";
+ private static final String COMPILATION_ANNOTATIONS_MSG_INFO = "Compilation.annotations.msg.info";
+ private static final String COMPILATION_ANNOTATIONS_TITLE = "Compilation.annotations.title";
+ private static final String COMPILATION_ANNOTATIONS_HEADER = "Compilation.annotations.header";
+ private static final String COMPILATION_SUCCESS_MESSAGE = "Compilation.success.message";
+ private static final String COMPILATION_SUCCESS_TITLE = "Compilation.success.title";
+ private static final String COMPILATION_SUCCESS_HEADER = "Compilation.success.header";
+ private static final String COMPILATION_DIAGNOSTIC_OVERRIDE = "Compilation.diagnostic.override";
+ private static final String EXAMPLES_DUPLICATION_MESSAGE = "Examples.duplication.message";
+ private static final String EXAMPLES_DUPLICATION_HEADER = "Examples.duplication.header";
+ private static final String EXAMPLES_DUPLICATION_TITLE = "Examples.duplication.title";
+ private static final String OPEN_DIALOG_TITLE = "Open.dialog.title";
+ private static final String OPEN_DIALOG_FILTER = "Open.dialog.filter";
+ private static HashMap programs;
+ private static URLClassLoader classLoader;
+
+ /**
+ * Initializes the Application on startup and makes sure the programs folder and
+ * the DefaultRobbi class exists
+ *
+ * @return true if initialization finished successfully, false otherwise
+ */
+ public static boolean initialize() {
+ File dir = new File(PATH_TO_PROGRAMS);
+ if (!dir.exists() && !dir.mkdir()) {
+ return false;
+ }
+
+ File defaultProgram = new File(
+ PATH_TO_PROGRAMS + File.separatorChar + DEFAULT_ROBBI_FILE_NAME + DEFAULT_FILE_EXTENSION);
+ if (!defaultProgram.exists()) {
+ try {
+ if (!defaultProgram.createNewFile())
+ return false;
+ } catch (IOException e) {
+ logger.error("Could not create file", e);
+ return false;
+ }
+
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(defaultProgram))) {
+ writer.write(createTemplate(DEFAULT_ROBBI_FILE_NAME, DEFAULT_CONTENT));
+ } catch (IOException e) {
+ logger.error("Could not write to file", e);
+ return false;
+ }
+ }
+ programs = new HashMap<>();
+ return true;
+ }
+
+ /**
+ * Looks into the programs directory and collects all java filenames.
+ *
+ * @return Collection of java filenames in programs directory
+ */
+ private static Collection getFilenamesInDirectory() {
+ // get a list of all files in programs directory that end with .java
+ File[] files = new File(PATH_TO_PROGRAMS)
+ .listFiles(file -> (file.isFile() && file.getName().endsWith(DEFAULT_FILE_EXTENSION)));
+ if (files == null)
+ return Collections.emptySet();
+ // get a String collection with all filenames in the programs directory
+ Collection filenamesInDirectory = Arrays.stream(files)
+ .map(file -> file.getName().replace(DEFAULT_FILE_EXTENSION, ""))
+ .collect(Collectors.toCollection(ArrayList::new));
+
+ logger.debug("Found following files in 'programs' directory:");
+ filenamesInDirectory.forEach(logger::debug);
+ return filenamesInDirectory;
+ }
+
+ /**
+ * Creates a Dialog and asks the user to for the name of the new program.
+ * Afterward, it initiates the creation of a new stage for the program.
+ *
+ * @param parent the parent window to show alerts relative to the parent window
+ * @see ProgramController#createAndShow(String)
+ */
+ public static void createAndShow(Window parent) {
+ Optional result = getNameForProgram(parent);
+ result.ifPresent(ProgramController::createAndShow);
+ }
+
+ /**
+ * Asks the user to enter a name for the program. It only allows names, that are
+ * no java identifiers and are not already used in the programs folder
+ *
+ * @param parent window to show the dialog relative to
+ * @return the new name for the program
+ */
+ private static Optional getNameForProgram(Window parent) {
+ Dialog dialog = new Dialog<>();
+ dialog.setTitle(i18n(NEW_DIALOG_TITLE));
+ dialog.setHeaderText(i18n(NEW_DIALOG_HEADER));
+ dialog.initOwner(parent);
+ DialogPane dialogPane = dialog.getDialogPane();
+ dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
+ TextField nameField = new TextField();
+ nameField.setPromptText(i18n(NEW_DIALOG_PROMPT));
+
+ Collection filenamesInDirectory = getFilenamesInDirectory();
+
+ nameField.textProperty()
+ .addListener((observable, oldVal, newVal) -> dialog.getDialogPane().lookupButton(ButtonType.OK)
+ .setDisable(SourceVersion.isKeyword(nameField.getText()) // https://stackoverflow.com/a/54141029/13670629
+ || !SourceVersion.isIdentifier(nameField.getText())
+ // || !nameField.getText().matches(VALID_IDENTIFIER_REGEX)
+ || filenamesInDirectory.contains(nameField.getText())));
+
+ dialog.getDialogPane().lookupButton(ButtonType.OK).setDisable(true);
+ GridPane grid = new GridPane();
+ grid.addRow(0, new Label(i18n(NEW_DIALOG_NAME)), nameField);
+
+ dialogPane.setContent(grid);
+ Platform.runLater(nameField::requestFocus);
+ dialog.setResultConverter(button -> (button == ButtonType.OK) ? nameField.getText() : null);
+
+ return dialog.showAndWait();
+ }
+
+ /**
+ * Creates a new file with default content, if it does not exist. Afterwards, it
+ * creates a program and a new Stage. Finally, it compiles the code and loads
+ * the Robbi instance into the simulation
+ *
+ * @param programName the name of the program to create
+ */
+ public static void createAndShow(String programName) {
+ String content = createTemplate(programName, DEFAULT_CONTENT);
+ File f = new File(PATH_TO_PROGRAMS + File.separatorChar + programName + DEFAULT_FILE_EXTENSION);
+ if (!f.exists()) {
+ try {
+ if (!f.createNewFile())
+ logger.debug("Could not create file '{}'", f.getAbsolutePath());
+ } catch (IOException e) {
+ logger.error("Failed to create file", e);
+ }
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(f))) {
+ writer.write(content);
+ } catch (IOException e) {
+ logger.error("Failed to write to file", e);
+ }
+ }
+
+ Program program = new Program(f, programName);
+ Stage stage = new MainStage(program);
+ programs.put(programName, stage);
+ ProgramController.compile(program, false, stage);
+ }
+
+ /**
+ * Creates a stage with the given programName, the programCode provided and the
+ * territory encoded as XML. If the user has already a stage with the same name,
+ * he will be warned, that his program will be overwritten. Optionally, he can
+ * save his program and territory under another name. After that a new Stage
+ * will be created according to the given information.
+ * This method might only be used to load an example from the database.
+ *
+ * @param programName name of the program
+ * @param programCode code of the program
+ * @param territoryXML XML-encoded territory
+ */
+ public static void createAndShow(String programName, String programCode, String territoryXML) {
+
+ String content = createTemplate(programName, DEFAULT_CONTENT);
+ File f = new File(PATH_TO_PROGRAMS + File.separatorChar + programName + DEFAULT_FILE_EXTENSION);
+ if (f.exists()) {
+ logger.debug("There is a file with the name of the example");
+ if (programs.containsKey(programName)) {
+ logger.debug("Program is opened: closing...");
+ MainStage stage = (MainStage) programs.get(programName);
+ Program p = stage.getProgram();
+ p.save(p.getEditorContent());
+ stage.close();
+ }
+ Alert alert = AlertHelper.createAlert(AlertType.INFORMATION, i18n(EXAMPLES_DUPLICATION_MESSAGE), null);
+ alert.setHeaderText(i18n(EXAMPLES_DUPLICATION_HEADER));
+ alert.setTitle(i18n(EXAMPLES_DUPLICATION_TITLE));
+ alert.getButtonTypes().remove(ButtonType.OK);
+ alert.getButtonTypes().addAll(ButtonType.YES, ButtonType.NO);
+ Optional result = alert.showAndWait();
+ if (result.isPresent()) {
+ ButtonType button = result.get();
+ if (button.equals(ButtonType.YES)) {
+ Optional newName = getNameForProgram(null);
+ if (newName.isPresent()) {
+ String name = newName.get();
+
+ StringBuilder bobTheBuilder = new StringBuilder();
+ try (BufferedReader reader = new BufferedReader(new FileReader(f))) {
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ bobTheBuilder.append(line);
+ bobTheBuilder.append(System.lineSeparator());
+ }
+ bobTheBuilder.replace(0, createPrefix(programName).length(), createPrefix(name));
+
+ } catch (IOException e) {
+ logger.debug("Failed to read class contents");
+ }
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(f))) {
+ writer.write(bobTheBuilder.toString());
+ } catch (IOException e) {
+ logger.debug("Failed to write new classname in file");
+ }
+ if (!renameFile(f, name)) {
+ logger.debug("Failed to rename file");
+ }
+ }
+ }
+ }
+ }
+
+ if (!f.exists()) {
+ try {
+ if (!f.createNewFile())
+ logger.debug("Could not create file '{}'", f.getAbsolutePath());
+ } catch (IOException e) {
+ logger.error("Failed to create file", e);
+ }
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(f))) {
+ writer.write(content);
+ } catch (IOException e) {
+ logger.error("Failed to write to file", e);
+ }
+ }
+
+ Program program = new Program(f, programName);
+ program.setEdited(true);
+ program.save(programCode);
+ MainStage stage = new MainStage(program);
+ stage.getTerritory().fromXML(new ByteArrayInputStream(territoryXML.getBytes()));
+ programs.put(programName, stage);
+ ProgramController.compile(program, false, stage);
+ }
+
+ /**
+ * Renames a java file in the programs directory to the new name.
+ *
+ * @param f the file to rename
+ * @param newName the new name of the file
+ * @return true if the renaming was successful, false otherwise
+ */
+ public static boolean renameFile(File f, String newName) {
+ File newFile = new File(PATH_TO_PROGRAMS + File.separatorChar + newName + DEFAULT_FILE_EXTENSION);
+
+ if (newFile.exists())
+ return false;
+ return f.renameTo(newFile);
+ }
+
+ /**
+ * Creates the prefix for the program-file
+ *
+ * @param name the name of the class
+ * @return the prefix for the class
+ */
+ public static String createPrefix(String name) {
+ return String.format(PREFIX_TEMPLATE, name);
+ }
+
+ /**
+ * Creates the postfix for the program-file
+ *
+ * @return the postfix for the class
+ */
+ public static String createPostfix() {
+ return POSTFIX_TEMPLATE;
+ }
+
+ /**
+ * Creates the template for a compilable class
+ *
+ * @param name the name of the class
+ * @param content the content of the class
+ * @return a String containing a compilable java code with the given content
+ */
+ public static String createTemplate(String name, String content) {
+ return createPrefix(name) + content + createPostfix();
+
+ }
+
+ /**
+ * Opens a FileChooser and loads the selected file. If the file is already
+ * loaded, the ProgramController requests the focus for the loaded program.
+ * Otherwise it creates a new program and a new stage.
+ *
+ * @param parent the window to open the chooser relative to the calling window
+ */
+ public static void openProgram(Window parent) {
+ FileChooser fileChooser = new FileChooser();
+ fileChooser.setTitle(i18n(OPEN_DIALOG_TITLE));
+ fileChooser.setInitialDirectory(new File(PATH_TO_PROGRAMS));
+ fileChooser.getExtensionFilters()
+ .add(new FileChooser.ExtensionFilter(i18n(OPEN_DIALOG_FILTER), "*" + DEFAULT_FILE_EXTENSION));
+
+ File file = fileChooser.showOpenDialog(parent);
+ if (file != null) {
+ String name = file.getName().replaceFirst(DEFAULT_FILE_EXTENSION, "");
+ if (!programs.containsKey(name)) {
+ logger.debug("Opening '{}' since it is not loaded yet.", name);
+ Program program = new Program(file, name);
+ Stage stage = new MainStage(program);
+ programs.put(name, stage);
+ compile(program, false, parent);
+ } else {
+ logger.debug("File is already loaded! Requesting focus...");
+ programs.get(name).requestFocus();
+ }
+ }
+
+ }
+
+ /**
+ * Compiles the given Program and shows an error Alert if the Compilation failed
+ * otherwise it shows an success alert. If the compilation finished
+ * successfully, the new Robbi will be loaded into the territory.
+ *
+ * @param program the program to compile
+ * @param parent the calling window to show alerts relative to the calling
+ * window
+ */
+ public static void compile(Program program, Window parent) {
+ compile(program, true, parent);
+ }
+
+ /**
+ * Compiles the given Program and shows an error Alert if the Compilation failed
+ * otherwise it shows an success alert. If the compilation finished
+ * successfully, the new Robbi will be loaded into the territory. Before it does
+ * this, it checks if the Annotations are set correctly and if the main-Method
+ * is overwritten. An error with this post-compile check will be visualized with
+ * an Alert.
+ *
+ * @param program the program to compile
+ * @param showAlerts flag to determine if the alerts need to be shown or not
+ * @param parent the window calling the method in order to show the alerts
+ * relative to it
+ */
+ public static void compile(Program program, boolean showAlerts, Window parent) {
+
+ JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
+ DiagnosticCollector diagnostics = new DiagnosticCollector<>();
+
+ try (StandardJavaFileManager manager = javac.getStandardFileManager(diagnostics, null, null)) {
+ Iterable extends JavaFileObject> units = manager
+ .getJavaFileObjectsFromFiles(Collections.singletonList(program.getFile()));
+ // https://stackoverflow.com/questions/60016127/can-toolprovider-getsystemjavacompiler-access-runtime-generated-in-memory-sour
+ CompilationTask task = javac.getTask(null, manager, diagnostics, List.of("-p", System.getProperty("jdk.module.path")), null, units);
+ task.addModules(List.of("RobbiSimulator")); //https://docs.oracle.com/javase%2F9%2Fdocs%2Fapi%2F%2F/javax/tools/JavaCompiler.CompilationTask.html
+
+ if (Boolean.FALSE.equals(task.call())) {
+ boolean showedAlert = false; // flag to indicate that only one alert is shown
+ logger.error("Compilation failed");
+ for (Diagnostic> diagnostic : diagnostics.getDiagnostics()) {
+
+ logger.error("Kind: {}", diagnostic.getKind());
+ logger.error("Quelle: {}", diagnostic.getSource());
+ logger.error("Code und Nachricht: {}: {}", diagnostic.getCode(), diagnostic.getMessage(null));
+ logger.error("Zeile: {}", diagnostic.getLineNumber());
+ logger.error("Position/Spalte: {}/{}", diagnostic.getPosition(), diagnostic.getColumnNumber());
+ logger.error("Startpostion/Endposition: {}/{}", diagnostic.getStartPosition(),
+ diagnostic.getEndPosition());
+ // TODO change String.format to use i18n directly
+ if (showAlerts && !showedAlert) {
+ String bobTheBuilder = String.format(i18n(COMPILATION_DIAGNOSTIC_KIND), diagnostic.getKind()) +
+ String.format(i18n(COMPILATION_DIAGNOSTIC_CODEANDMESSAGE),
+ diagnostic.getCode(), diagnostic.getMessage(null)) +
+ String.format(i18n(COMPILATION_DIAGNOSTIC_ROW), diagnostic.getLineNumber() - 1);
+ AlertHelper.showAlertAndWait(AlertType.ERROR, bobTheBuilder, parent,
+ Modality.WINDOW_MODAL, i18n(COMPILATION_DIAGNOSTIC_TITLE),
+ diagnostic.getKind().toString());
+ showedAlert = true;
+ }
+ }
+ } else {// compilation successful
+ logger.info("Compilation successful");
+ Optional robbi = loadNewRobbi(program.getName());
+
+ robbi.ifPresentOrElse(r -> {
+ Diagnostics diag = new Diagnostics();
+ if (!hasValidAnnotations(r, diag)) {
+ List diags = diag.getDiagnosis();
+ String val = null;
+ String type = null;
+ if (!diags.isEmpty()) {
+ Diagnostics.Diagnostic diagnostic = diags.getFirst();
+ val = diagnostic.value();
+ type = diagnostic.type();
+ logger.error("[Annotation Error]: {} is not applicable for {}", val, type);
+ } else
+ logger.error("[Annotation Error]: Error has been found but could not be diagnosed.");
+
+ if (showAlerts) {
+ String msg = i18n(COMPILATION_ANNOTATIONS_MSG_DEFAULT);
+ if (val != null && type != null) {
+ msg = String.format(i18n(COMPILATION_ANNOTATIONS_MSG_INFO), val, type);
+ }
+ AlertHelper.showAlertAndWait(AlertType.WARNING, msg, parent, Modality.WINDOW_MODAL,
+ i18n(COMPILATION_ANNOTATIONS_TITLE), i18n(COMPILATION_ANNOTATIONS_HEADER));
+ }
+ } else {
+ if (overwritesMainMethod(r)) {
+ // set new Robbi in territory
+ MainStage s = (MainStage) programs.get(program.getName());
+ s.getTerritory().setRobbi(r);
+ logger.debug("New Robbi instance loaded");
+ if (showAlerts) {
+ ((MainStage) parent).getNotificationController().showMessage(5000, "Snackbar.message.compile.success", program.getName());
+ }
+ } else {
+ AlertHelper.showAlertAndWait(AlertType.ERROR, i18n(COMPILATION_DIAGNOSTIC_OVERRIDE),
+ parent);
+ logger.error("The custom Robbi class does not overwrite the main-Method");
+ }
+ }
+ }, () -> logger.error("Failed to load new Robbi instance..."));
+
+ }
+ } catch (IOException e) {
+ logger.error("Failed to compile program", e);
+ }
+
+ }
+
+ /**
+ * Checks if the robbi overwrites the Main-Method.
+ *
+ * @param robbi the robbi to check if it overwrites the Main-Method
+ * @return true if robbi overwrites it, false otherwise
+ */
+ private static boolean overwritesMainMethod(Robbi robbi) {
+ if (Robbi.class == robbi.getClass()) {
+ return true; // Default Robbi always has main-Method overwritten
+ }
+ for (Method m : robbi.getClass().getDeclaredMethods()) {
+ if (m.getName().equals("main")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the given robbi has valid annotations set. Currently it checks if
+ * the default Annotation has values matching its parameter
+ *
+ * @param robbi Instance of the users robbi implementation to check
+ * @return true if the annotions are valid, false otherwise
+ */
+ private static boolean hasValidAnnotations(Robbi robbi, Diagnostics diag) {
+ Method[] methods = getCustomMethods(robbi);
+ boolean result = true;
+ for (Method method : methods) {
+ if (!hasValidDefaultAnnotation(method, diag)) {
+ result = false;
+
+ // use return to fasten things up. Following annotation errors are ignored
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Checks if the method has Default annotations matching the type of its
+ * parameter
+ *
+ * @param method the method to check the annotations for
+ * @return true if and only if all Default annotations match their parameter
+ * type, false otherwise
+ */
+ private static boolean hasValidDefaultAnnotation(Method method, Diagnostics diag) {
+ boolean result = true;
+ for (Parameter parameter : method.getParameters()) {
+ Annotation[] annotations = parameter.getAnnotations();
+ for (Annotation annotation : annotations) {
+ if (annotation instanceof Default anno && !valueAcceptable(parameter, anno, diag)) {
+ result = false;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Checks if the parameter and the Default Annotation match types. This is done
+ * by checking, if the value of the Default annotation can be parsed to the type
+ * of the parameter. If it fails, this method returns false.
+ *
+ * @param parameter The parameter to check the type of
+ * @param annotation The annotation whose value has to be checked against the
+ * parameter type
+ * @return true if the annotation value matches the parameter type, false
+ * otherwise
+ */
+ private static boolean valueAcceptable(Parameter parameter, Default annotation, Diagnostics diag) {
+ String val = annotation.value();
+ String type = parameter.getType().getName();
+ try {
+ switch (type) {
+ case "int":
+ Integer.parseInt(val);
+ return true;
+ case "boolean":
+ return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("false");
+ case "char":
+ return !val.isBlank();
+ case "double":
+ Double.parseDouble(val);
+ return true;
+ case "float":
+ Float.parseFloat(val);
+ return true;
+ case "long":
+ Long.parseLong(val);
+ return true;
+ case "String":
+ default:
+ return true;
+ }
+ } catch (IllegalArgumentException | IndexOutOfBoundsException e) {
+ diag.add(new Diagnostics.Diagnostic(type, val));
+ return false;
+ }
+
+ }
+
+ /**
+ * Returns all methods, that are not part of the default robbi implementation,
+ * i.e. returns all methods the user has implemented
+ *
+ * @param robbi the new robbi instance
+ * @return an ArrayList of all new methods of the robbi
+ */
+ private static Method[] getCustomMethods(Robbi robbi) {
+ List methods = new ArrayList<>();
+ // if robbi is custom class
+ if (Robbi.class != robbi.getClass()) {
+ methods.addAll(Arrays.asList(robbi.getClass().getDeclaredMethods()));
+ }
+ return methods.toArray(Method[]::new);
+ }
+
+ /**
+ * Loads a new Robbi by the name of the class
+ *
+ * @param name the name of the class
+ * @return an Optional of the given robbi class
+ */
+ private static Optional loadNewRobbi(String name) {
+ Optional robbi;
+ try {
+ // if an old classloader exists, close it
+ if (classLoader != null)
+ classLoader.close();
// cant be closed here because then the simulation thread can't access lazily loaded classes loaded with this classloader
- // maybe think about a factory solution: https://stackoverflow.com/a/13946807
- // see this whole discussion about when to close a classloader: https://stackoverflow.com/q/13944868
- classLoader = URLClassLoader.newInstance(new URL[] { new File(PATH_TO_PROGRAMS).toURI().toURL() });
-
- Constructor> c = classLoader.loadClass(name).getConstructor();
- Robbi r = (Robbi) c.newInstance();
- logger.debug("Loaded class of '{}'", name);
- robbi = Optional.of(r);
- } catch (InstantiationException | IllegalAccessException | InvocationTargetException | ClassNotFoundException
- | NoSuchMethodException | SecurityException | IOException e) {
- logger.error("Could not load class of '{}'. Message: {}", name, e.getMessage());
- robbi = Optional.empty();
- }
- return robbi;
- }
-
- /**
- * Loads a new Robbi Instance from the classfile.
- *
- * @param name the name of the Robbi-Class
- * @return An Optional with the Robbi instance or an empty optional if the
- * loading failed.
- */
- public static Optional getNewRobbi(String name) {
- Optional robbi = loadNewRobbi(name);
- if (robbi.isPresent()) {
- Robbi r = robbi.get();
- Diagnostics diag = new Diagnostics();
- if (!hasValidAnnotations(r, diag)) {
- logger.debug("{} has no valid annotations.", name);
- } else {
- if (overwritesMainMethod(r)) {
- return Optional.of(r);
- } else {
- logger.error("The custom Robbi class does not overwrite the main-Method");
- }
- }
- } else
- logger.error("Failed to load new Robbi instance...");
- return Optional.empty();
- }
-
- /**
- * Removes the program from the programsList in order to make sure it can be
- * reopened later
- *
- * @param name the name of the program which is closed
- */
- public static void close(String name) {
- programs.remove(name);
- logger.debug("Closing program '{}'", name);
- }
+ // maybe think about a factory solution: https://stackoverflow.com/a/13946807
+ // see this whole discussion about when to close a classloader: https://stackoverflow.com/q/13944868
+ classLoader = URLClassLoader.newInstance(new URL[]{new File(PATH_TO_PROGRAMS).toURI().toURL()});
+
+ Constructor> c = classLoader.loadClass(name).getConstructor();
+ Robbi r = (Robbi) c.newInstance();
+ logger.debug("Loaded class of '{}'", name);
+ robbi = Optional.of(r);
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException | ClassNotFoundException
+ | NoSuchMethodException | SecurityException | IOException e) {
+ logger.error("Could not load class of '{}'. Message: {}", name, e.getMessage());
+ robbi = Optional.empty();
+ }
+ return robbi;
+ }
+
+ /**
+ * Loads a new Robbi Instance from the classfile.
+ *
+ * @param name the name of the Robbi-Class
+ * @return An Optional with the Robbi instance or an empty optional if the
+ * loading failed.
+ */
+ public static Optional getNewRobbi(String name) {
+ Optional robbi = loadNewRobbi(name);
+ if (robbi.isPresent()) {
+ Robbi r = robbi.get();
+ Diagnostics diag = new Diagnostics();
+ if (!hasValidAnnotations(r, diag)) {
+ logger.debug("{} has no valid annotations.", name);
+ } else {
+ if (overwritesMainMethod(r)) {
+ return Optional.of(r);
+ } else {
+ logger.error("The custom Robbi class does not overwrite the main-Method");
+ }
+ }
+ } else
+ logger.error("Failed to load new Robbi instance...");
+ return Optional.empty();
+ }
+
+ /**
+ * Removes the program from the programsList in order to make sure it can be
+ * reopened later
+ *
+ * @param name the name of the program which is closed
+ */
+ public static void close(String name) {
+ programs.remove(name);
+ logger.debug("Closing program '{}'", name);
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/Simulation.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/Simulation.java
index c8a8c11..05d48a2 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/Simulation.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/Simulation.java
@@ -1,15 +1,11 @@
package com.JayPi4c.RobbiSimulator.controller.simulation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
import com.JayPi4c.RobbiSimulator.model.RobbiException;
import com.JayPi4c.RobbiSimulator.model.Territory;
import com.JayPi4c.RobbiSimulator.utils.AlertHelper;
import com.JayPi4c.RobbiSimulator.utils.Observable;
import com.JayPi4c.RobbiSimulator.utils.Observer;
import com.JayPi4c.RobbiSimulator.utils.SoundManager;
-
import javafx.application.Platform;
import javafx.scene.control.Alert.AlertType;
import javafx.stage.Window;
@@ -17,109 +13,111 @@
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
/**
- * This Simulation class is a separate thread that runs the code of robbis
+ * This Simulation class is a separate thread that runs the code of robbi's
* main-Method. It can be paused, resumed and stopped by the user at any time.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
public class Simulation extends Thread implements Observer {
- private Territory territory;
- private SimulationController simController;
- private Window parent;
+ private final Territory territory;
+ private final SimulationController simController;
+ private final Window parent;
- @Getter
- @Setter
- private volatile boolean stopped;
- @Getter
- @Setter
- private volatile boolean paused;
- @Getter
- private final Object lock = new Object();
+ @Getter
+ @Setter
+ private volatile boolean stopped;
+ @Getter
+ @Setter
+ private volatile boolean paused;
+ @Getter
+ private final Object lock = new Object();
- /**
- * Constructor to create a new Simulation, which can execute robbis main-Method.
- *
- * @param territory The territory in which the simulation is happening
- * @param simController The SimulationController, which started this simulation
- * @param parent The parent window to show alerts relative to the it
- */
- public Simulation(Territory territory, SimulationController simController, Window parent) {
- this.territory = territory;
- this.simController = simController;
- this.parent = parent;
- stopped = false;
- paused = false;
- }
+ /**
+ * Constructor to create a new Simulation, which can execute robbi's main-Method.
+ *
+ * @param territory The territory in which the simulation is happening
+ * @param simController The SimulationController, which started this simulation
+ * @param parent The parent window to show alerts relative to it
+ */
+ public Simulation(Territory territory, SimulationController simController, Window parent) {
+ this.territory = territory;
+ this.simController = simController;
+ this.parent = parent;
+ stopped = false;
+ paused = false;
+ }
- /**
- * Starts the simulation and triggers the robbis main-Method. It informs the
- * user if the execution finished in an unexpected way. In the end it does some
- * finalization.
- */
- @Override
- public void run() {
- logger.info("Simulation started");
- territory.addObserver(this);
- try {
- Method main = territory.getRobbi().getClass().getDeclaredMethod("main");
- main.setAccessible(true);
- main.invoke(territory.getRobbi());
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
- | SecurityException e) {
- if (e.getCause() instanceof StopException) {
- logger.debug("Simulation stopped");
- } else if (e.getCause() instanceof RobbiException re) {
- logger.debug("Simulation stopped with exception: {}", re.getMessage());
- SoundManager.playWarnSound();
- // TODO: change to Snackbar?
- Platform.runLater(
- () -> AlertHelper.showAlertAndWait(AlertType.ERROR, re.getLocalizedMessage(), parent));
- } else
- e.printStackTrace();
- } finally {
- stopped = true;
- territory.removeObserver(this);
- simController.finish();
- logger.info("Simulation done.");
- }
+ /**
+ * Starts the simulation and triggers the robbi's main-Method. It informs the
+ * user if the execution finished in an unexpected way. In the end it does some
+ * finalization.
+ */
+ @Override
+ public void run() {
+ logger.info("Simulation started");
+ territory.addObserver(this);
+ try {
+ Method main = territory.getRobbi().getClass().getDeclaredMethod("main");
+ main.setAccessible(true);
+ main.invoke(territory.getRobbi());
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
+ | SecurityException e) {
+ if (e.getCause() instanceof StopException) {
+ logger.debug("Simulation stopped");
+ } else if (e.getCause() instanceof RobbiException re) {
+ logger.debug("Simulation stopped with exception: {}", re.getMessage());
+ SoundManager.playWarnSound();
+ // TODO: change to Snackbar?
+ Platform.runLater(
+ () -> AlertHelper.showAlertAndWait(AlertType.ERROR, re.getLocalizedMessage(), parent));
+ } else
+ logger.error("Simulation stopped with unwanted exception", e);
+ } finally {
+ stopped = true;
+ territory.removeObserver(this);
+ simController.finish();
+ logger.info("Simulation done.");
+ }
- }
+ }
- /**
- * If the territory has been updated by a non-FXApplicationThread, this thread
- * is sleeping for the time provided by the SimulationController. Furthermore,
- * it waits while the simulation is stopped and throws an StopException if the
- * Simulation has been terminated by the user.
- *
- * @param observable The observable, which caused the update to trigger
- */
- @Override
- public void update(Observable observable) {
- if (Platform.isFxApplicationThread()) // if observable is called by gui, ignore it
- return;
- try {
- sleep(simController.getSpeed());
- } catch (InterruptedException e) {
- logger.debug("Stopping simulation during sleep");
- Thread.currentThread().interrupt();
- }
- if (this.stopped)
- throw new StopException();
- while (this.paused)
- synchronized (lock) {
- try {
- lock.wait();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- if (stopped)
- throw new StopException();
+ /**
+ * If the territory has been updated by a non-FXApplicationThread, this thread
+ * is sleeping for the time provided by the SimulationController. Furthermore,
+ * it waits while the simulation is stopped and throws an StopException if the
+ * Simulation has been terminated by the user.
+ *
+ * @param observable The observable, which caused the update to trigger
+ */
+ @Override
+ public void update(Observable observable) {
+ if (Platform.isFxApplicationThread()) // if observable is called by gui, ignore it
+ return;
+ try {
+ sleep(simController.getSpeed());
+ } catch (InterruptedException e) {
+ logger.debug("Stopping simulation during sleep");
+ Thread.currentThread().interrupt();
+ }
+ if (this.stopped)
+ throw new StopException();
+ while (this.paused)
+ synchronized (lock) {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ if (stopped)
+ throw new StopException();
- }
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/SimulationController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/SimulationController.java
index 0e32940..6cb1546 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/SimulationController.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/SimulationController.java
@@ -1,14 +1,11 @@
package com.JayPi4c.RobbiSimulator.controller.simulation;
-import java.util.Optional;
-
import com.JayPi4c.RobbiSimulator.controller.program.ProgramController;
import com.JayPi4c.RobbiSimulator.model.Robbi;
import com.JayPi4c.RobbiSimulator.model.Territory;
import com.JayPi4c.RobbiSimulator.model.TerritoryState;
import com.JayPi4c.RobbiSimulator.view.MainStage;
import com.JayPi4c.RobbiSimulator.view.Toolbar;
-
import javafx.application.Platform;
import javafx.scene.control.Button;
import javafx.scene.control.MenuItem;
@@ -16,223 +13,224 @@
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
+import java.util.Optional;
+
/**
* Controller to handle all actions belonging to the simulation.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
public class SimulationController {
- private static final int MIN_SPEED = 100;
- private static final int MAX_SPEED = 2500;
-
- private Simulation simulation;
-
- private MainStage stage;
- private Territory territory;
-
- @Getter
- private volatile int speed;
-
- private MenuItem resetMenuItem;
- private Button resetToolbar;
-
- private MenuItem pauseMenuItem;
- private ToggleButton pauseToolbar;
- private MenuItem startMenuItem;
- private ToggleButton startToolbar;
- private MenuItem stopMenuItem;
- private ToggleButton stopToolbar;
-
- private TerritoryState territoryState;
-
- /**
- * Constructor to create a new SimulationController, which adds all actions to
- * the corresponding gui elements.
- *
- * @param stage The stage, this controller is for
- * @param territory the territory in which the simulation takes place
- */
- public SimulationController(MainStage stage, Territory territory) {
- this.stage = stage;
- this.territory = territory;
- Toolbar toolbar = stage.getToolbar();
- speed = (int) toolbar.getSpeedSliderToolbar().getValue();
-
- resetToolbar = toolbar.getResetButtonToolbar();
- resetToolbar.setOnAction(e -> reset());
- resetMenuItem = this.stage.getMenubar().getResetMenuItem();
- resetMenuItem.onActionProperty().bind(resetToolbar.onActionProperty());
-
- startToolbar = toolbar.getStartToggleButtonToolbar();
- startToolbar.setOnAction(e -> {
- if (!isSimulationRunning())
- start();
- else
- resume();
- });
- startMenuItem = stage.getMenubar().getStartMenuItem();
- startMenuItem.onActionProperty().bind(startToolbar.onActionProperty());
- startMenuItem.disableProperty().bind(startToolbar.disableProperty());
-
- pauseToolbar = toolbar.getPauseToggleButtonToolbar();
- pauseToolbar.setOnAction(e -> pause());
- pauseMenuItem = this.stage.getMenubar().getPauseMenuItem();
- pauseMenuItem.onActionProperty().bind(pauseToolbar.onActionProperty());
- pauseMenuItem.disableProperty().bind(pauseToolbar.disableProperty());
-
- stopToolbar = toolbar.getStopToggleButtonToolbar();
- stopToolbar.setOnAction(e -> stop());
- stopMenuItem = this.stage.getMenubar().getStopMenuItem();
- stopMenuItem.onActionProperty().bind(stopToolbar.onActionProperty());
- stopMenuItem.disableProperty().bind(stopToolbar.disableProperty());
-
- toolbar.getSpeedSliderToolbar().valueProperty().addListener((ov, oldVal, newVal) -> setSpeed((Double) newVal));
- setSpeed(toolbar.getSpeedSliderToolbar().getValue());
- disableButtonStates(false, true, true);
-
- }
-
- /**
- * Helper to start e new simulation.
- */
- private void start() {
- logger.debug("Starting new simulation");
- Optional r = ProgramController.getNewRobbi(stage.getProgram().getName());
- if (r.isPresent())
- territory.setRobbi(r.get());
- else
- logger.debug("Could not initialize Robbi");
- territoryState = territory.save();
- simulation = new Simulation(territory, this, stage);
- simulation.setDaemon(true); // program should exit even if simulation is running
- simulation.start();
- disableButtonStates(true, false, false);
- }
-
- /**
- * Helper to pause the current simulation.
- */
- private void pause() {
- logger.debug("Pausing simulation");
- simulation.setPaused(true);
- disableButtonStates(false, true, false);
- }
-
- /**
- * Helper to resume the current simulation.
- */
- private void resume() {
- logger.debug("Resuming simulation");
- simulation.setPaused(false);
- synchronized (simulation.getLock()) {
- simulation.getLock().notifyAll();
- }
- disableButtonStates(true, false, false);
- }
-
- /**
- * Helper to stop the current simulation.
- */
- private void stop() {
- logger.debug("Stopping simulation");
- simulation.setStopped(true);
- simulation.setPaused(false);
- simulation.interrupt();
- synchronized (simulation.getLock()) {
- simulation.getLock().notifyAll();
- }
- }
-
- /**
- * Helper to reset the territory to the state at the beginning of the
- * simulation.
- */
- private void reset() {
- logger.debug("Resetting the simulation");
- if (isSimulationRunning())
- stop();
-
- if (territoryState != null)
- territory.restore(territoryState);
- }
-
- /**
- * Helper to check if the simulation is currently running
- *
- * @return true if the simulation is not null or not stopped
- */
- private boolean isSimulationRunning() {
- return !(simulation == null || simulation.isStopped());
- }
-
- /**
- * Stops the simulation if one exists.
- */
- public void stopSimulation() {
- if (simulation != null) {
- stop();
- }
- }
-
- /**
- * Helper to finish up a simulation if it is finished or has been stopped by the
- * user.
- */
- public void finish() {
- Platform.runLater(() -> {
- disableButtonStates(false, true, true);
- startToolbar.setSelected(false);
- });
- }
-
- /**
- * Helper to set the buttonstates according the the given parameters.
- *
- * @param start true, to disable start simulation button
- * @param pause true, to disable pause simulation button
- * @param stop true, to disable stop simulation button
- */
- private void disableButtonStates(boolean start, boolean pause, boolean stop) {
- if (!Platform.isFxApplicationThread()) {
- Platform.runLater(() -> {
- startToolbar.setDisable(start);
- pauseToolbar.setDisable(pause);
- stopToolbar.setDisable(stop);
- });
- } else {
- startToolbar.setDisable(start);
- pauseToolbar.setDisable(pause);
- stopToolbar.setDisable(stop);
- }
- }
-
- /**
- * Updates the speed attribute to the given parameter.
- *
- * @param speed the new speed value
- */
- public void setSpeed(double speed) {
- this.speed = (int) map(speed, Toolbar.MIN_SPEED_VALUE, Toolbar.MAX_SPEED_VALUE, MAX_SPEED, MIN_SPEED);
- }
-
- /**
- * Maps the given value, which ranges between istart and istop on a value which
- * ranges between ostart and ostop.
- *
- * @see Stackoverflow
- * @param value value to map
- * @param istart input start
- * @param istop input stop
- * @param ostart output start
- * @param ostop output stop
- * @return the mapped value
- */
- private final double map(double value, double istart, double istop, double ostart, double ostop) {
- return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
- }
+ private static final int MIN_SPEED = 100;
+ private static final int MAX_SPEED = 2500;
+
+ private Simulation simulation;
+
+ private final MainStage stage;
+ private final Territory territory;
+
+ @Getter
+ private volatile int speed;
+
+ private final MenuItem resetMenuItem;
+ private final Button resetToolbar;
+
+ private final MenuItem pauseMenuItem;
+ private final ToggleButton pauseToolbar;
+ private final MenuItem startMenuItem;
+ private final ToggleButton startToolbar;
+ private final MenuItem stopMenuItem;
+ private final ToggleButton stopToolbar;
+
+ private TerritoryState territoryState;
+
+ /**
+ * Constructor to create a new SimulationController, which adds all actions to
+ * the corresponding gui elements.
+ *
+ * @param stage The stage, this controller is for
+ * @param territory the territory in which the simulation takes place
+ */
+ public SimulationController(MainStage stage, Territory territory) {
+ this.stage = stage;
+ this.territory = territory;
+ Toolbar toolbar = stage.getToolbar();
+ speed = (int) toolbar.getSpeedSliderToolbar().getValue();
+
+ resetToolbar = toolbar.getResetButtonToolbar();
+ resetToolbar.setOnAction(e -> reset());
+ resetMenuItem = this.stage.getMenubar().getResetMenuItem();
+ resetMenuItem.onActionProperty().bind(resetToolbar.onActionProperty());
+
+ startToolbar = toolbar.getStartToggleButtonToolbar();
+ startToolbar.setOnAction(e -> {
+ if (!isSimulationRunning())
+ start();
+ else
+ resume();
+ });
+ startMenuItem = stage.getMenubar().getStartMenuItem();
+ startMenuItem.onActionProperty().bind(startToolbar.onActionProperty());
+ startMenuItem.disableProperty().bind(startToolbar.disableProperty());
+
+ pauseToolbar = toolbar.getPauseToggleButtonToolbar();
+ pauseToolbar.setOnAction(e -> pause());
+ pauseMenuItem = this.stage.getMenubar().getPauseMenuItem();
+ pauseMenuItem.onActionProperty().bind(pauseToolbar.onActionProperty());
+ pauseMenuItem.disableProperty().bind(pauseToolbar.disableProperty());
+
+ stopToolbar = toolbar.getStopToggleButtonToolbar();
+ stopToolbar.setOnAction(e -> stop());
+ stopMenuItem = this.stage.getMenubar().getStopMenuItem();
+ stopMenuItem.onActionProperty().bind(stopToolbar.onActionProperty());
+ stopMenuItem.disableProperty().bind(stopToolbar.disableProperty());
+
+ toolbar.getSpeedSliderToolbar().valueProperty().addListener((ov, oldVal, newVal) -> setSpeed((Double) newVal));
+ setSpeed(toolbar.getSpeedSliderToolbar().getValue());
+ disableButtonStates(false, true, true);
+
+ }
+
+ /**
+ * Helper to start e new simulation.
+ */
+ private void start() {
+ logger.debug("Starting new simulation");
+ Optional r = ProgramController.getNewRobbi(stage.getProgram().getName());
+ if (r.isPresent())
+ territory.setRobbi(r.get());
+ else
+ logger.debug("Could not initialize Robbi");
+ territoryState = territory.save();
+ simulation = new Simulation(territory, this, stage);
+ simulation.setDaemon(true); // program should exit even if simulation is running
+ simulation.start();
+ disableButtonStates(true, false, false);
+ }
+
+ /**
+ * Helper to pause the current simulation.
+ */
+ private void pause() {
+ logger.debug("Pausing simulation");
+ simulation.setPaused(true);
+ disableButtonStates(false, true, false);
+ }
+
+ /**
+ * Helper to resume the current simulation.
+ */
+ private void resume() {
+ logger.debug("Resuming simulation");
+ simulation.setPaused(false);
+ synchronized (simulation.getLock()) {
+ simulation.getLock().notifyAll();
+ }
+ disableButtonStates(true, false, false);
+ }
+
+ /**
+ * Helper to stop the current simulation.
+ */
+ private void stop() {
+ logger.debug("Stopping simulation");
+ simulation.setStopped(true);
+ simulation.setPaused(false);
+ simulation.interrupt();
+ synchronized (simulation.getLock()) {
+ simulation.getLock().notifyAll();
+ }
+ }
+
+ /**
+ * Helper to reset the territory to the state at the beginning of the
+ * simulation.
+ */
+ private void reset() {
+ logger.debug("Resetting the simulation");
+ if (isSimulationRunning())
+ stop();
+
+ if (territoryState != null)
+ territory.restore(territoryState);
+ }
+
+ /**
+ * Helper to check if the simulation is currently running
+ *
+ * @return true if the simulation is not null or not stopped
+ */
+ private boolean isSimulationRunning() {
+ return !(simulation == null || simulation.isStopped());
+ }
+
+ /**
+ * Stops the simulation if one exists.
+ */
+ public void stopSimulation() {
+ if (simulation != null) {
+ stop();
+ }
+ }
+
+ /**
+ * Helper to finish up a simulation if it is finished or has been stopped by the
+ * user.
+ */
+ public void finish() {
+ Platform.runLater(() -> {
+ disableButtonStates(false, true, true);
+ startToolbar.setSelected(false);
+ });
+ }
+
+ /**
+ * Helper to set the buttonstates according the the given parameters.
+ *
+ * @param start true, to disable start simulation button
+ * @param pause true, to disable pause simulation button
+ * @param stop true, to disable stop simulation button
+ */
+ private void disableButtonStates(boolean start, boolean pause, boolean stop) {
+ if (!Platform.isFxApplicationThread()) {
+ Platform.runLater(() -> {
+ startToolbar.setDisable(start);
+ pauseToolbar.setDisable(pause);
+ stopToolbar.setDisable(stop);
+ });
+ } else {
+ startToolbar.setDisable(start);
+ pauseToolbar.setDisable(pause);
+ stopToolbar.setDisable(stop);
+ }
+ }
+
+ /**
+ * Updates the speed attribute to the given parameter.
+ *
+ * @param speed the new speed value
+ */
+ public void setSpeed(double speed) {
+ this.speed = (int) map(speed, Toolbar.MIN_SPEED_VALUE, Toolbar.MAX_SPEED_VALUE, MAX_SPEED, MIN_SPEED);
+ }
+
+ /**
+ * Maps the given value, which ranges between inStart and inStop, on a value which
+ * ranges between outStart and outStop.
+ *
+ * @param value value to map
+ * @param inStart input start
+ * @param inStop input stop
+ * @param outStart output start
+ * @param outStop output stop
+ * @return the mapped value
+ * @see Stackoverflow
+ */
+ private double map(double value, double inStart, double inStop, double outStart, double outStop) {
+ return outStart + (outStop - outStart) * ((value - inStart) / (inStop - inStart));
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/StopException.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/StopException.java
index 4526466..af53ce6 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/StopException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/simulation/StopException.java
@@ -4,12 +4,9 @@
* This Exception indicates, that the simulation has been interrupted. It will
* be thrown, if the user hits the stop button while the main Method of robbi is
* still running.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class StopException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Answer.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Answer.java
index 92e0f8f..ddadb63 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Answer.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Answer.java
@@ -1,14 +1,18 @@
package com.JayPi4c.RobbiSimulator.controller.tutor;
+import java.io.Serial;
import java.io.Serializable;
/**
* Wrapper to hold an answer instance.
- *
- * @author Jonas Pohl
+ *
* @param code the code which is stored in the editor
* @param territory the territory encoded as XML string
+ * @author Jonas Pohl
*/
public record Answer(String code, String territory) implements Serializable {
+ @Serial
+ private static final long serialVersionUID = 1L;
+
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/ITutor.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/ITutor.java
index 398e77c..0e705a5 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/ITutor.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/ITutor.java
@@ -5,31 +5,30 @@
/**
* Interface for RMI communication
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public interface ITutor extends Remote {
- /**
- * Sends a request of code and territory to the tutor and returns the id of the
- * request at the tutors instance.
- *
- * @param code the requests code
- * @param territory the requests territory
- * @return the requests id
- * @throws RemoteException thrown on connection errors
- */
- public int sendRequest(String code, String territory) throws RemoteException;
+ /**
+ * Sends a request of code and territory to the tutor and returns the id of the
+ * request at the tutors instance.
+ *
+ * @param code the requests code
+ * @param territory the requests territory
+ * @return the requests id
+ * @throws RemoteException thrown on connection errors
+ */
+ int sendRequest(String code, String territory) throws RemoteException;
- /**
- * Fetches the answer for the given id. The answer will be null, if no answer is
- * set.
- *
- * @param id the id for the fetched answer
- * @return the answer for the id or null, if no answer is set
- * @throws RemoteException thrown on connection errors
- */
- public Answer getAnswer(int id) throws RemoteException;
+ /**
+ * Fetches the answer for the given id. The answer will be null, if no answer is
+ * set.
+ *
+ * @param id the id for the fetched answer
+ * @return the answer for the id or null, if no answer is set
+ * @throws RemoteException thrown on connection errors
+ */
+ Answer getAnswer(int id) throws RemoteException;
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Request.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Request.java
index a013a5c..2db54cb 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Request.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Request.java
@@ -2,9 +2,8 @@
/**
* Wrapper to hold a request instance.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public record Request(int id, String code, String territory) {
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/StudentController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/StudentController.java
index e2fa814..6823343 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/StudentController.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/StudentController.java
@@ -1,102 +1,99 @@
package com.JayPi4c.RobbiSimulator.controller.tutor;
-import java.io.ByteArrayInputStream;
-import java.rmi.NotBoundException;
-import java.rmi.RemoteException;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-
import com.JayPi4c.RobbiSimulator.controller.program.Program;
import com.JayPi4c.RobbiSimulator.controller.program.ProgramController;
import com.JayPi4c.RobbiSimulator.utils.AlertHelper;
import com.JayPi4c.RobbiSimulator.utils.I18nUtils;
import com.JayPi4c.RobbiSimulator.utils.PropertiesLoader;
import com.JayPi4c.RobbiSimulator.view.MainStage;
-
import javafx.scene.control.Alert.AlertType;
import lombok.extern.slf4j.Slf4j;
+import java.io.ByteArrayInputStream;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+
/**
* Controller to handle actions of a student.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
public class StudentController {
- private int requestID;
-
- private MainStage stage;
+ // language keys
+ private static final String MENU_TUTOR_RECEIVEANSWER_INFORMATION = "Menu.tutor.receiveAnswer.information";
+ private static final String MENU_TUTOR_RECEIVEANSWER_ERROR = "Menu.tutor.receiveAnswer.error";
+ private static final String MENU_TUTOR_SEND_REQUEST_INFORMATION = "Menu.tutor.sendRequest.information";
+ private static final String MENU_TUTOR_SENDREQUEST_ERROR = "Menu.tutor.sendRequest.error";
+ private int requestID;
+ private final MainStage stage;
- // language keys
- private static final String MENU_TUTOR_RECEIVEANSWER_INFORMATION = "Menu.tutor.receiveAnswer.information";
- private static final String MENU_TUTOR_RECEIVEANSWER_ERROR = "Menu.tutor.receiveAnswer.error";
- private static final String MENU_TUTOR_SEND_REQUEST_INFORMATION = "Menu.tutor.sendRequest.information";
- private static final String MENU_TUTOR_SENDREQUEST_ERROR = "Menu.tutor.sendRequest.error";
+ /**
+ * Constructor to create a new StudentController
+ *
+ * @param stage the stage, the controller is for
+ */
+ public StudentController(MainStage stage) {
+ this.stage = stage;
+ stage.getMenubar().getSendRequestMenuItem().setOnAction(e -> sendRequest());
+ stage.getMenubar().getReceiveAnswerMenuItem().setOnAction(e -> receiveAnswer());
+ stage.getMenubar().getSendRequestMenuItem().setDisable(false);
+ stage.getMenubar().getReceiveAnswerMenuItem().setDisable(true);
+ }
- /**
- * Constructor to create a new StudentController
- *
- * @param stage the stage, the controller is for
- */
- public StudentController(MainStage stage) {
- this.stage = stage;
- stage.getMenubar().getSendRequestMenuItem().setOnAction(e -> sendRequest());
- stage.getMenubar().getReceiveAnswerMenuItem().setOnAction(e -> receiveAnswer());
- stage.getMenubar().getSendRequestMenuItem().setDisable(false);
- stage.getMenubar().getReceiveAnswerMenuItem().setDisable(true);
- }
+ /**
+ * Helper to handle receiveAnswer actions
+ */
+ private void receiveAnswer() {
+ try {
+ Registry registry = LocateRegistry.getRegistry(PropertiesLoader.getTutorhost(),
+ PropertiesLoader.getTutorport());
+ ITutor tutor = (ITutor) registry.lookup(TutorController.TUTOR_CODE);
+ Answer answer = tutor.getAnswer(requestID);
+ if (answer == null) {
+ logger.debug("Answer is not ready yet!");
+ stage.getNotificationController().showMessage(3000, MENU_TUTOR_RECEIVEANSWER_INFORMATION);
+ return;
+ }
+ stage.getProgram().setEditorContent(answer.code());
+ stage.getProgram().save();
+ ProgramController.compile(stage.getProgram(), false, stage);
+ stage.getTerritory().fromXML(new ByteArrayInputStream(answer.territory().getBytes()));
+ stage.getMenubar().getSendRequestMenuItem().setDisable(false);
+ stage.getMenubar().getReceiveAnswerMenuItem().setDisable(true);
+ } catch (RemoteException | NotBoundException e) {
+ logger.debug("Failed to fetch answer from tutor.");
+ AlertHelper.showAlertAndWait(AlertType.ERROR, I18nUtils.i18n(MENU_TUTOR_RECEIVEANSWER_ERROR), stage);
+ }
+ }
- /**
- * Helper to handle receiveAnswer actions
- */
- private void receiveAnswer() {
- try {
- Registry registry = LocateRegistry.getRegistry(PropertiesLoader.getTutorhost(),
- PropertiesLoader.getTutorport());
- ITutor tutor = (ITutor) registry.lookup(TutorController.TUTOR_CODE);
- Answer answer = tutor.getAnswer(requestID);
- if (answer == null) {
- logger.debug("Answer is not ready yet!");
- stage.getSnackbarController().showMessage(MENU_TUTOR_RECEIVEANSWER_INFORMATION);
- return;
- }
- stage.getProgram().setEditorContent(answer.code());
- stage.getProgram().save();
- ProgramController.compile(stage.getProgram(), false, stage);
- stage.getTerritory().fromXML(new ByteArrayInputStream(answer.territory().getBytes()));
- stage.getMenubar().getSendRequestMenuItem().setDisable(false);
- stage.getMenubar().getReceiveAnswerMenuItem().setDisable(true);
- } catch (RemoteException | NotBoundException e) {
- logger.debug("Failed to fetch answer from tutor.");
- AlertHelper.showAlertAndWait(AlertType.ERROR, I18nUtils.i18n(MENU_TUTOR_RECEIVEANSWER_ERROR), stage);
- }
- }
+ /**
+ * Helper to handle sendRequest actions
+ */
+ private void sendRequest() {
+ try {
+ Registry registry = LocateRegistry.getRegistry(PropertiesLoader.getTutorhost(),
+ PropertiesLoader.getTutorport());
+ ITutor tutor = (ITutor) registry.lookup(TutorController.TUTOR_CODE);
+ Program program = stage.getProgram();
+ program.setEdited(true);
+ program.save(stage.getTextArea().getEditor().getDocument().getText());
+ stage.getLanguageController().updateTitle();
+ requestID = tutor.sendRequest(program.getEditorContent(), stage.getTerritory().toXML().toString());
+ logger.debug("The request has ID {}.", requestID);
+ stage.getMenubar().getSendRequestMenuItem().setDisable(true);
+ stage.getMenubar().getReceiveAnswerMenuItem().setDisable(false);
- /**
- * Helper to handle sendRequest actions
- */
- private void sendRequest() {
- try {
- Registry registry = LocateRegistry.getRegistry(PropertiesLoader.getTutorhost(),
- PropertiesLoader.getTutorport());
- ITutor tutor = (ITutor) registry.lookup(TutorController.TUTOR_CODE);
- Program program = stage.getProgram();
- program.setEdited(true);
- program.save(stage.getTextArea().getEditor().getDocument().getText());
- stage.getLanguageController().updateTitle();
- requestID = tutor.sendRequest(program.getEditorContent(), stage.getTerritory().toXML().toString());
- logger.debug("The request has ID {}.", requestID);
- stage.getMenubar().getSendRequestMenuItem().setDisable(true);
- stage.getMenubar().getReceiveAnswerMenuItem().setDisable(false);
+ stage.getNotificationController().showMessage(3000, MENU_TUTOR_SEND_REQUEST_INFORMATION);
- stage.getSnackbarController().showMessage(MENU_TUTOR_SEND_REQUEST_INFORMATION);
+ } catch (RemoteException | NotBoundException e) {
+ logger.debug("Failed to send request to tutor.");
+ AlertHelper.showAlertAndWait(AlertType.ERROR, I18nUtils.i18n(MENU_TUTOR_SENDREQUEST_ERROR), stage);
+ }
+ }
- } catch (RemoteException | NotBoundException e) {
- logger.debug("Failed to send request to tutor.");
- AlertHelper.showAlertAndWait(AlertType.ERROR, I18nUtils.i18n(MENU_TUTOR_SENDREQUEST_ERROR), stage);
- }
- }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Tutor.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Tutor.java
index 7b78137..6bd9c26 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Tutor.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/Tutor.java
@@ -1,83 +1,80 @@
package com.JayPi4c.RobbiSimulator.controller.tutor;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Queue;
-
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
+import java.io.Serial;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.*;
+
/**
* ITutor implementation to handle the RMI invocations.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
@EqualsAndHashCode(callSuper = true)
public class Tutor extends UnicastRemoteObject implements ITutor {
- private static final long serialVersionUID = 4722167139215525516L;
+ @Serial
+ private static final long serialVersionUID = 4722167139215525516L;
- private transient Queue requests;
- /**
- * ID of the latest request. Will increment after a request arrived.
- */
- private int currentID = 0;
- /**
- * Map to hold answers accessible by their id
- */
- private Map answers;
+ private transient final Queue requests;
+ /**
+ * ID of the latest request. Will increment after a request arrived.
+ */
+ private int currentID = 0;
+ /**
+ * Map to hold answers accessible by their id
+ */
+ private final Map answers;
- /**
- * Create a new tutor-instance
- *
- * @throws RemoteException thrown on connection errors
- */
- public Tutor() throws RemoteException {
- super();
- requests = new LinkedList<>();
- answers = new HashMap<>();
- }
+ /**
+ * Create a new tutor-instance
+ *
+ * @throws RemoteException thrown on connection errors
+ */
+ public Tutor() throws RemoteException {
+ super();
+ requests = new LinkedList<>();
+ answers = new HashMap<>();
+ }
- @Override
- public synchronized int sendRequest(String code, String territory) throws RemoteException {
- requests.add(new Request(currentID, code, territory));
- logger.debug("Added new request with id {}.", currentID);
- return currentID++;
- }
+ @Override
+ public synchronized int sendRequest(String code, String territory) throws RemoteException {
+ requests.add(new Request(currentID, code, territory));
+ logger.debug("Added new request with id {}.", currentID);
+ return currentID++;
+ }
- @Override
- public synchronized Answer getAnswer(int id) throws RemoteException {
- if (answers.containsKey(id)) {
- logger.debug("Returning answer with id {}.", id);
- return answers.remove(id);
- }
- logger.debug("Could not find answer with id {}.", id);
- return null;
- }
+ @Override
+ public synchronized Answer getAnswer(int id) throws RemoteException {
+ if (answers.containsKey(id)) {
+ logger.debug("Returning answer with id {}.", id);
+ return answers.remove(id);
+ }
+ logger.debug("Could not find answer with id {}.", id);
+ return null;
+ }
- /**
- * Returns an optional with a new request if one is available.
- *
- * @return Optional of the oldest request or an empty Optional.
- */
- public synchronized Optional getNewRequest() {
- return Optional.ofNullable(requests.poll());
- }
+ /**
+ * Returns an optional with a new request if one is available.
+ *
+ * @return Optional of the oldest request or an empty Optional.
+ */
+ public synchronized Optional getNewRequest() {
+ return Optional.ofNullable(requests.poll());
+ }
- /**
- * Adds an answer with the corresponding id in the list of done answers.
- *
- * @param id the id for the answer
- * @param answer the actual answer
- */
- public synchronized void setAnswer(int id, Answer answer) {
- answers.put(id, answer);
- }
+ /**
+ * Adds an answer with the corresponding id in the list of done answers.
+ *
+ * @param id the id for the answer
+ * @param answer the actual answer
+ */
+ public synchronized void setAnswer(int id, Answer answer) {
+ answers.put(id, answer);
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/TutorController.java b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/TutorController.java
index a5cbd3b..789f0de 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/TutorController.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/controller/tutor/TutorController.java
@@ -1,5 +1,10 @@
package com.JayPi4c.RobbiSimulator.controller.tutor;
+import com.JayPi4c.RobbiSimulator.controller.program.ProgramController;
+import com.JayPi4c.RobbiSimulator.utils.PropertiesLoader;
+import com.JayPi4c.RobbiSimulator.view.MainStage;
+import lombok.extern.slf4j.Slf4j;
+
import java.io.ByteArrayInputStream;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
@@ -8,119 +13,107 @@
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
-import com.JayPi4c.RobbiSimulator.controller.program.ProgramController;
-import com.JayPi4c.RobbiSimulator.utils.PropertiesLoader;
-import com.JayPi4c.RobbiSimulator.view.MainStage;
-
-import lombok.extern.slf4j.Slf4j;
-
/**
* Controller to handle actions of a tutor.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
public class TutorController {
- private static Tutor tutor;
- private static Registry registry;
-
- private MainStage stage;
-
- private static final int NO_ID = -1;
- private int currentID = NO_ID;
-
- /**
- * Code to bind a tutor instance to the RMI instance.
- */
- public static final String TUTOR_CODE = "Tutor";
-
- // language keys
- private static final String MENU_TUTOR_LOADREQUEST_SUCCESS = "Menu.tutor.loadRequest.success";
- private static final String MENU_TUTOR_LOADREQUEST_WARNING = "Menu.tutor.loadRequest.warning";
- private static final String MENU_TUTOR_SAVEANSWER_INFORMATION = "Menu.tutor.saveAnswer.information";
-
- /**
- * Constructor to create a new TutorController.
- *
- * @param mainStage the stage, the controller is for
- */
- public TutorController(MainStage mainStage) {
- this.stage = mainStage;
- mainStage.getMenubar().getLoadRequestMenuItem().setOnAction(e -> loadRequest());
- mainStage.getMenubar().getSaveAnswerMenuItem().setOnAction(e -> saveAnswer());
- mainStage.getMenubar().getLoadRequestMenuItem().setDisable(false);
- mainStage.getMenubar().getSaveAnswerMenuItem().setDisable(true);
- }
-
- /**
- * Helper to handle loadRequest actions
- *
- */
- private void loadRequest() {
- tutor.getNewRequest().ifPresentOrElse(request -> {
- logger.debug("Loading request with id {}.", request.id());
- stage.getProgram().setEditorContent(request.code());
- stage.getProgram().save();
- ProgramController.compile(stage.getProgram(), false, stage);
- stage.getTerritory().fromXML(new ByteArrayInputStream(request.territory().getBytes()));
- currentID = request.id();
- stage.getMenubar().getLoadRequestMenuItem().setDisable(true);
- stage.getMenubar().getSaveAnswerMenuItem().setDisable(false);
- stage.getSnackbarController().showMessage(MENU_TUTOR_LOADREQUEST_SUCCESS, request.id());
- }, () -> {
- logger.debug("no request available");
- stage.getSnackbarController().showMessage(MENU_TUTOR_LOADREQUEST_WARNING);
- });
- }
-
- /**
- * Helper to handle save Answer actions
- */
- private void saveAnswer() {
- logger.debug("Saving answer for id {}.", currentID);
- stage.getProgram().save(stage.getTextArea().getEditor().getDocument().getText());
- tutor.setAnswer(currentID,
- new Answer(stage.getProgram().getEditorContent(), stage.getTerritory().toXML().toString()));
- currentID = NO_ID;
- stage.getMenubar().getLoadRequestMenuItem().setDisable(false);
- stage.getMenubar().getSaveAnswerMenuItem().setDisable(true);
- stage.getSnackbarController().showMessage(MENU_TUTOR_SAVEANSWER_INFORMATION);
- }
-
- /**
- * Creates a new RMI registry and gets ready to accept connections.
- *
- * @return true if the initialization finished successfully, false otherwise
- */
- public static boolean initialize() {
- try {
- tutor = new Tutor();
-
- registry = LocateRegistry.createRegistry(PropertiesLoader.getTutorport());
-
- registry.bind(TUTOR_CODE, tutor);
- } catch (RemoteException | AlreadyBoundException re) {
- return false;
- }
- return true;
- }
-
- /**
- * Unbinds all previously binded instances.
- *
- * @return true if the unbinding was successful, false otherwise
- */
- public static boolean shutdown() {
- try {
- registry.unbind(TUTOR_CODE);
- UnicastRemoteObject.unexportObject(tutor, true);
- UnicastRemoteObject.unexportObject(registry, true);
- } catch (RemoteException | NotBoundException e) {
- return false;
- }
- return true;
- }
+ /**
+ * Code to bind a tutor instance to the RMI instance.
+ */
+ public static final String TUTOR_CODE = "Tutor";
+ private static final int NO_ID = -1;
+ // language keys
+ private static final String MENU_TUTOR_LOADREQUEST_SUCCESS = "Menu.tutor.loadRequest.success";
+ private static final String MENU_TUTOR_LOADREQUEST_WARNING = "Menu.tutor.loadRequest.warning";
+ private static final String MENU_TUTOR_SAVEANSWER_INFORMATION = "Menu.tutor.saveAnswer.information";
+ private static Tutor tutor;
+ private static Registry registry;
+ private final MainStage stage;
+ private int currentID = NO_ID;
+
+ /**
+ * Constructor to create a new TutorController.
+ *
+ * @param mainStage the stage, the controller is for
+ */
+ public TutorController(MainStage mainStage) {
+ this.stage = mainStage;
+ mainStage.getMenubar().getLoadRequestMenuItem().setOnAction(e -> loadRequest());
+ mainStage.getMenubar().getSaveAnswerMenuItem().setOnAction(e -> saveAnswer());
+ mainStage.getMenubar().getLoadRequestMenuItem().setDisable(false);
+ mainStage.getMenubar().getSaveAnswerMenuItem().setDisable(true);
+ }
+
+ /**
+ * Creates a new RMI registry and gets ready to accept connections.
+ *
+ * @return true if the initialization finished successfully, false otherwise
+ */
+ public static boolean initialize() {
+ try {
+ tutor = new Tutor();
+
+ registry = LocateRegistry.createRegistry(PropertiesLoader.getTutorport());
+
+ registry.bind(TUTOR_CODE, tutor);
+ } catch (RemoteException | AlreadyBoundException re) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Unbinds all previously bound instances.
+ *
+ * @return true if the unbinding was successful, false otherwise
+ */
+ public static boolean shutdown() {
+ try {
+ registry.unbind(TUTOR_CODE);
+ UnicastRemoteObject.unexportObject(tutor, true);
+ UnicastRemoteObject.unexportObject(registry, true);
+ } catch (RemoteException | NotBoundException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Helper to handle loadRequest actions
+ */
+ private void loadRequest() {
+ tutor.getNewRequest().ifPresentOrElse(request -> {
+ logger.debug("Loading request with id {}.", request.id());
+ stage.getProgram().setEditorContent(request.code());
+ stage.getProgram().save();
+ ProgramController.compile(stage.getProgram(), false, stage);
+ stage.getTerritory().fromXML(new ByteArrayInputStream(request.territory().getBytes()));
+ currentID = request.id();
+ stage.getMenubar().getLoadRequestMenuItem().setDisable(true);
+ stage.getMenubar().getSaveAnswerMenuItem().setDisable(false);
+ stage.getNotificationController().showMessage(3000, MENU_TUTOR_LOADREQUEST_SUCCESS, request.id());
+ }, () -> {
+ logger.debug("no request available");
+ stage.getNotificationController().showMessage(3000, MENU_TUTOR_LOADREQUEST_WARNING);
+ });
+ }
+
+ /**
+ * Helper to handle save Answer actions
+ */
+ private void saveAnswer() {
+ logger.debug("Saving answer for id {}.", currentID);
+ stage.getProgram().save(stage.getTextArea().getEditor().getDocument().getText());
+ tutor.setAnswer(currentID,
+ new Answer(stage.getProgram().getEditorContent(), stage.getTerritory().toXML().toString()));
+ currentID = NO_ID;
+ stage.getMenubar().getLoadRequestMenuItem().setDisable(false);
+ stage.getMenubar().getSaveAnswerMenuItem().setDisable(true);
+ stage.getNotificationController().showMessage(3000, MENU_TUTOR_SAVEANSWER_INFORMATION);
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Accu.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Accu.java
index 31448bc..b1e6d48 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Accu.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Accu.java
@@ -2,15 +2,17 @@
import jakarta.xml.bind.annotation.XmlRootElement;
+import java.io.Serial;
+
/**
* Class representing the accu-item.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@XmlRootElement
public class Accu implements Item {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/BagIsEmptyException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/BagIsEmptyException.java
index 2166e32..482bac1 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/BagIsEmptyException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/BagIsEmptyException.java
@@ -1,21 +1,23 @@
package com.JayPi4c.RobbiSimulator.model;
+import java.io.Serial;
+
/**
* Exception to be thrown if an item is placed down while there is no item in
* the bag.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class BagIsEmptyException extends RobbiException {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new BagIsEmptyException with a localized message.
- */
- public BagIsEmptyException() {
- super("Exception.BagIsEmpty");
- }
+ /**
+ * Constructor for a new BagIsEmptyException with a localized message.
+ */
+ public BagIsEmptyException() {
+ super("Exception.BagIsEmpty");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/BagIsFullException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/BagIsFullException.java
index bd7d16b..96e1a4c 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/BagIsFullException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/BagIsFullException.java
@@ -1,20 +1,22 @@
package com.JayPi4c.RobbiSimulator.model;
+import java.io.Serial;
+
/**
* Exception to be thrown if an item is picked up while the bag is already full.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class BagIsFullException extends RobbiException {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new BagIsFullException with a localized message.
- */
- public BagIsFullException() {
- super("Exception.BagIsFull");
- }
+ /**
+ * Constructor for a new BagIsFullException with a localized message.
+ */
+ public BagIsFullException() {
+ super("Exception.BagIsFull");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/DIRECTION.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/DIRECTION.java
index de3451c..26bd2c9 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/DIRECTION.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/DIRECTION.java
@@ -1,48 +1,45 @@
package com.JayPi4c.RobbiSimulator.model;
/**
- * Enumeration to hold all cardinal-points to store robbis current facing.
- *
- * @author Jonas Pohl
+ * Enumeration to hold all cardinal-points to store robbi's current facing.
*
+ * @author Jonas Pohl
*/
public enum DIRECTION {
- /**
- * Direction if robbi is looking up.
- */
- NORTH,
- /**
- * Direction if robbi is looking left.
- */
- WEST,
- /**
- * Direction if robbi is looking down.
- */
- SOUTH,
- /**
- * Direction if robbi is looking right.
- */
- EAST;
-
- private static DIRECTION[] vals = values();
+ /**
+ * Direction if robbi is looking up.
+ */
+ NORTH,
+ /**
+ * Direction if robbi is looking left.
+ */
+ WEST,
+ /**
+ * Direction if robbi is looking down.
+ */
+ SOUTH,
+ /**
+ * Direction if robbi is looking right.
+ */
+ EAST;
- /**
- * moves through the direction counter-clockwise
- *
- * @return the next direction after a counter-clockwise 90 degrees turn.
- */
- public DIRECTION next() {
- return vals[(this.ordinal() + 1) % vals.length];
- }
+ /**
+ * moves through the direction counter-clockwise
+ *
+ * @return the next direction after a counter-clockwise 90 degrees turn.
+ */
+ public DIRECTION next() {
+ return values()[(this.ordinal() + 1) % values().length];
+ }
- /**
- * Moves through the direction clockwise.
- *
- * @return the next direction after a clockwise 90 degrees turn.
- */
- public DIRECTION previous() {
- return vals[(this.ordinal() + vals.length - 1) % vals.length];
- }
+ /**
+ * Moves through the direction clockwise.
+ *
+ * @return the next direction after a clockwise 90 degrees turn.
+ */
+ public DIRECTION previous() {
+ return values()[(this.ordinal() + values().length - 1) % values().length];
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Dimension.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Dimension.java
index 6b22cb8..4a320eb 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Dimension.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Dimension.java
@@ -2,9 +2,8 @@
/**
* Record to hold information about the new dimension of the simulation gird.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public record Dimension(int cols, int rows) {
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Hollow.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Hollow.java
index 8234253..e638e89 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Hollow.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Hollow.java
@@ -2,38 +2,40 @@
import jakarta.xml.bind.annotation.XmlRootElement;
+import java.io.Serial;
+
/**
* Class representing a Hollow tile.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@XmlRootElement
public class Hollow extends Tile {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Getter for the item placed on the tile.
- *
- * @return the item placed on this tile. No item can be placed here, therefore
- * the item returned is null
- */
- @Override
- public Item getItem() {
- return null;
- }
+ /**
+ * Getter for the item placed on the tile.
+ *
+ * @return the item placed on this tile. No item can be placed here, therefore
+ * the item returned is null
+ */
+ @Override
+ public Item getItem() {
+ return null;
+ }
- /**
- * Setter to place an item in the hollow. Since the gamelogic forbids this
- * action, the item given to the hollow will not be saved and dropped instead.
- *
- * @param item item to be placed in the hollow.
- */
- @Override
- public void setItem(Item item) {
- // Robbi can't reach a hollow tile. Items will be dropped if it is placed into a
- // hollow
- }
+ /**
+ * Setter to place an item in the hollow. Since the game logic forbids this
+ * action, the item given to the hollow will not be saved and dropped instead.
+ *
+ * @param item item to be placed in the hollow.
+ */
+ @Override
+ public void setItem(Item item) {
+ // Robbi can't reach a hollow tile. Items will be dropped if it is placed into a
+ // hollow
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/HollowAheadException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/HollowAheadException.java
index 0b37fb4..c9e3276 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/HollowAheadException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/HollowAheadException.java
@@ -1,19 +1,21 @@
package com.JayPi4c.RobbiSimulator.model;
+import java.io.Serial;
+
/**
- * Exception to be thrown if robbi tries to move into a hollow-
- *
- * @author Jonas Pohl
+ * Exception to be thrown if robbi tries to move into a hollow.
*
+ * @author Jonas Pohl
*/
public class HollowAheadException extends RobbiException {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new HollowAheadException with a localized message.
- */
- public HollowAheadException() {
- super("Exception.HollowAhead");
- }
+ /**
+ * Constructor for a new HollowAheadException with a localized message.
+ */
+ public HollowAheadException() {
+ super("Exception.HollowAhead");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/InvalidTerritoryException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/InvalidTerritoryException.java
index 1a3814e..b921764 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/InvalidTerritoryException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/InvalidTerritoryException.java
@@ -1,20 +1,22 @@
package com.JayPi4c.RobbiSimulator.model;
+import java.io.Serial;
+
/**
* Exception to be thrown if the user tries to load an invalid territory.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class InvalidTerritoryException extends Exception {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new InvalidTerritoryException with a message.
- */
- public InvalidTerritoryException() {
- super("The loaded territory is invalid.");
- }
+ /**
+ * Constructor for a new InvalidTerritoryException with a message.
+ */
+ public InvalidTerritoryException() {
+ super("The loaded territory is invalid.");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Item.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Item.java
index e564244..91167e0 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Item.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Item.java
@@ -4,9 +4,8 @@
/**
* Interface for all item classes.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public interface Item extends Serializable {
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/NoItemException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/NoItemException.java
index 2770ef5..cfcb742 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/NoItemException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/NoItemException.java
@@ -1,21 +1,23 @@
package com.JayPi4c.RobbiSimulator.model;
+import java.io.Serial;
+
/**
* Exception to be thrown if robbi tries to pick up an item from a tile, which
- * has no item provied.
- *
- * @author Jonas Pohl
+ * has no item provided.
*
+ * @author Jonas Pohl
*/
public class NoItemException extends RobbiException {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new NoItemException with a localized message.
- */
- public NoItemException() {
- super("Exception.NoItem");
- }
+ /**
+ * Constructor for a new NoItemException with a localized message.
+ */
+ public NoItemException() {
+ super("Exception.NoItem");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/NoPileOfScrapAheadException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/NoPileOfScrapAheadException.java
index e62ca3f..3a805cc 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/NoPileOfScrapAheadException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/NoPileOfScrapAheadException.java
@@ -1,21 +1,23 @@
package com.JayPi4c.RobbiSimulator.model;
+import java.io.Serial;
+
/**
* Exception to be thrown if robbi attempts to push a pile of scrap while there
* is no pile of scrap ahead of robbi.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class NoPileOfScrapAheadException extends RobbiException {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new NoPileOfScrapAheadException with localized message.
- */
- public NoPileOfScrapAheadException() {
- super("Exception.NoPileOfScrapAhead");
- }
+ /**
+ * Constructor for a new NoPileOfScrapAheadException with localized message.
+ */
+ public NoPileOfScrapAheadException() {
+ super("Exception.NoPileOfScrapAhead");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Nut.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Nut.java
index 13b1afe..1dfb0db 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Nut.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Nut.java
@@ -2,15 +2,17 @@
import jakarta.xml.bind.annotation.XmlRootElement;
+import java.io.Serial;
+
/**
* Class representing the nut-item.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@XmlRootElement
public class Nut implements Item {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/PileOfScrap.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/PileOfScrap.java
index 3022a4f..266d294 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/PileOfScrap.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/PileOfScrap.java
@@ -2,37 +2,39 @@
import jakarta.xml.bind.annotation.XmlRootElement;
+import java.io.Serial;
+
/**
* Class representing a PileOfScrap Tile.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@XmlRootElement
public class PileOfScrap extends Tile {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Setter to place an item on a PileOfScrap. Since the item placed on a pile of
- * scrap, the item just vanishes.
- *
- * @param item the item to vanish
- */
- @Override
- public void setItem(Item item) {
- // Item vanishes
- }
+ /**
+ * Setter to place an item on a PileOfScrap. Since the item placed on a pile of
+ * scrap, the item just vanishes.
+ *
+ * @param item the item to vanish
+ */
+ @Override
+ public void setItem(Item item) {
+ // Item vanishes
+ }
- /**
- * Getter for the item placed on the tile.
- *
- * @return the item placed on this tile. All items placed on a pile of scrap
- * vanish, therefore the item returned will be null.
- */
- @Override
- public Item getItem() {
- return null;
- }
+ /**
+ * Getter for the item placed on the tile.
+ *
+ * @return the item placed on this tile. All items placed on a pile of scrap
+ * vanish, therefore the item returned will be null.
+ */
+ @Override
+ public Item getItem() {
+ return null;
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Robbi.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Robbi.java
index d7b13c8..eaa8666 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Robbi.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Robbi.java
@@ -1,324 +1,319 @@
package com.JayPi4c.RobbiSimulator.model;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.Synchronized;
+import lombok.*;
import lombok.extern.slf4j.Slf4j;
/**
- *
* This is the actor class of the simulator. All public functions in this class
- * will be available in the simulators editor.
- *
+ * will be available in the simulator's editor.
+ *
* @author Jonas Pohl
*/
@Slf4j
@NoArgsConstructor
public class Robbi {
- /**
- * Attribute to store the territory in which robbi is living
- */
- @Setter(value = AccessLevel.PACKAGE)
- private Territory territory;
- /**
- * Attribute to store robbis x position in the territory
- */
- @Getter(value = AccessLevel.PACKAGE)
- private volatile int x;
- /**
- * Attribute to store robbis y position in the territory
- */
- @Getter(value = AccessLevel.PACKAGE)
- private volatile int y;
- /**
- * Attribute to store robbis item
- */
- @Getter(value = AccessLevel.PACKAGE, onMethod_ = { @Synchronized("territory") })
- @Setter(value = AccessLevel.PACKAGE, onMethod_ = { @Synchronized("territory") })
- private Item item = null;
+ /**
+ * Attribute to store the territory in which robbi is living
+ */
+ @Setter(value = AccessLevel.PACKAGE)
+ private Territory territory;
+ /**
+ * Attribute to store robbi's x position in the territory
+ */
+ @Getter(value = AccessLevel.PACKAGE)
+ private volatile int x;
+ /**
+ * Attribute to store robbi's y position in the territory
+ */
+ @Getter(value = AccessLevel.PACKAGE)
+ private volatile int y;
+ /**
+ * Attribute to store robbi's item
+ */
+ @Getter(value = AccessLevel.PACKAGE, onMethod_ = {@Synchronized("territory")})
+ @Setter(value = AccessLevel.PACKAGE, onMethod_ = {@Synchronized("territory")})
+ private Item item = null;
- /**
- * Attribute to store robbis facing
- */
- @Getter(value = AccessLevel.PACKAGE)
- private volatile DIRECTION facing;
+ /**
+ * Attribute to store robbi's facing
+ */
+ @Getter(value = AccessLevel.PACKAGE)
+ private volatile DIRECTION facing;
- /**
- * The main-Method which will be overwritten by every custom Robbi
- * implementation. When starting a simulation, this method will be called.
- */
- void main() {
- // will be overritten
- logger.error("Please overrite the main-method");
- }
+ /**
+ * The main-Method which will be overwritten by every custom Robbi
+ * implementation. When starting a simulation, this method will be called.
+ */
+ void main() {
+ // will be overwritten
+ logger.error("Please overwrite the main-method");
+ }
- /**
- * Constructor to create a new robbi with the given territory.
- *
- * @param t the territory in which robbi is placed.
- */
- Robbi(Territory t) {
- this.territory = t;
- this.x = 0;
- this.y = 0;
- this.facing = DIRECTION.EAST;
- }
+ /**
+ * Constructor to create a new robbi with the given territory.
+ *
+ * @param t the territory in which robbi is placed.
+ */
+ Robbi(Territory t) {
+ this.territory = t;
+ this.x = 0;
+ this.y = 0;
+ this.facing = DIRECTION.EAST;
+ }
- // ============= HELPER ================
+ // ============= HELPER ================
- /**
- * Sets the position of robbi.
- *
- * @param x new x position
- * @param y new y position
- */
- void setPosition(int x, int y) {
- synchronized (territory) {
- if (x < 0 || y < 0 || x >= territory.getNumCols() || y >= territory.getNumRows())
- throw new IllegalArgumentException("Robbi kann nicht außerhalb des Territoriums platziert werden.");
- if (territory.getTile(x, y) instanceof Hollow)
- throw new TileBlockedException();
- this.x = x;
- this.y = y;
- }
- }
+ /**
+ * Sets the position of robbi.
+ *
+ * @param x new x position
+ * @param y new y position
+ */
+ void setPosition(int x, int y) {
+ synchronized (territory) {
+ if (x < 0 || y < 0 || x >= territory.getNumCols() || y >= territory.getNumRows())
+ throw new IllegalArgumentException("Robbi kann nicht außerhalb des Territoriums platziert werden.");
+ if (territory.getTile(x, y) instanceof Hollow)
+ throw new TileBlockedException();
+ this.x = x;
+ this.y = y;
+ }
+ }
- /**
- * Updates the facing of robbi to the given facing.
- *
- * @param facing robbis new facing
- */
- void setFacing(DIRECTION facing) {
- synchronized (territory) {
- this.facing = facing;
- }
- }
+ /**
+ * Updates the facing of robbi to the given facing.
+ *
+ * @param facing robbi's new facing
+ */
+ void setFacing(DIRECTION facing) {
+ synchronized (territory) {
+ this.facing = facing;
+ }
+ }
- // ==================== PUBLIC FUNCTIONS ==========
+ // ==================== PUBLIC FUNCTIONS ==========
- /**
- * If possible move Robbi one tile towards the direction it is facing.
- */
- public final void vor() {
- synchronized (territory) {
- Tile t;
- switch (facing) {
- case NORTH:
- t = territory.getTile(x, y - 1);
- if (t instanceof Hollow)
- throw new HollowAheadException();
- else {
- y = y - 1;
- y += territory.getNumRows();
- y %= territory.getNumRows();
- }
- break;
- case SOUTH:
- t = territory.getTile(x, y + 1);
- if (t instanceof Hollow)
- throw new HollowAheadException();
- else {
- y = y + 1;
- y += territory.getNumRows();
- y %= territory.getNumRows();
- }
- break;
- case EAST:
- t = territory.getTile(x + 1, y);
- if (t instanceof Hollow)
- throw new HollowAheadException();
- else {
- x = x + 1;
- x += territory.getNumCols();
- x %= territory.getNumCols();
- }
- break;
- case WEST:
- t = territory.getTile(x - 1, y);
- if (t instanceof Hollow)
- throw new HollowAheadException();
- else {
- x = x - 1;
- x += territory.getNumCols();
- x %= territory.getNumCols();
- }
- break;
- default:
- break;
- }
- }
- territory.setChanged();
- territory.notifyAllObservers();
- }
+ /**
+ * If possible move Robbi one tile towards the direction it is facing.
+ */
+ public final void vor() {
+ synchronized (territory) {
+ Tile t;
+ switch (facing) {
+ case NORTH:
+ t = territory.getTile(x, y - 1);
+ if (t instanceof Hollow)
+ throw new HollowAheadException();
+ else {
+ y = y - 1;
+ y += territory.getNumRows();
+ y %= territory.getNumRows();
+ }
+ break;
+ case SOUTH:
+ t = territory.getTile(x, y + 1);
+ if (t instanceof Hollow)
+ throw new HollowAheadException();
+ else {
+ y = y + 1;
+ y += territory.getNumRows();
+ y %= territory.getNumRows();
+ }
+ break;
+ case EAST:
+ t = territory.getTile(x + 1, y);
+ if (t instanceof Hollow)
+ throw new HollowAheadException();
+ else {
+ x = x + 1;
+ x += territory.getNumCols();
+ x %= territory.getNumCols();
+ }
+ break;
+ case WEST:
+ t = territory.getTile(x - 1, y);
+ if (t instanceof Hollow)
+ throw new HollowAheadException();
+ else {
+ x = x - 1;
+ x += territory.getNumCols();
+ x %= territory.getNumCols();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ territory.setChanged();
+ territory.notifyAllObservers();
+ }
- /**
- * Turn Robbi counterclockwise.
- */
- public final void linksUm() {
- synchronized (territory) {
- facing = facing.next();
- }
- territory.setChanged();
- territory.notifyAllObservers();
- }
+ /**
+ * Turn Robbi counterclockwise.
+ */
+ public final void linksUm() {
+ synchronized (territory) {
+ facing = facing.next();
+ }
+ territory.setChanged();
+ territory.notifyAllObservers();
+ }
- /**
- * If possible drop the item that is stored in the bag.
- */
- public final void legeAb() {
- synchronized (territory) {
- if (item == null)
- throw new BagIsEmptyException();
- if (territory.placeItem(item, x, y))
- item = null;
- else
- throw new TileIsFullException();
- }
- territory.setChanged();
- territory.notifyAllObservers();
- }
+ /**
+ * If possible drop the item that is stored in the bag.
+ */
+ public final void legeAb() {
+ synchronized (territory) {
+ if (item == null)
+ throw new BagIsEmptyException();
+ if (territory.placeItem(item, x, y))
+ item = null;
+ else
+ throw new TileIsFullException();
+ }
+ territory.setChanged();
+ territory.notifyAllObservers();
+ }
- /**
- * if possible take the item that occupies the tile Robbi is on.
- */
- public final void nehmeAuf() {
- synchronized (territory) {
- Item i = territory.getItem(x, y);
- if (i == null)
- throw new NoItemException();
- if (this.item != null) {
- throw new BagIsFullException();
- }
- this.item = territory.removeItem(x, y);
- }
- territory.setChanged();
- territory.notifyAllObservers();
- }
+ /**
+ * if possible take the item that occupies the tile Robbi is on.
+ */
+ public final void nehmeAuf() {
+ synchronized (territory) {
+ Item i = territory.getItem(x, y);
+ if (i == null)
+ throw new NoItemException();
+ if (this.item != null) {
+ throw new BagIsFullException();
+ }
+ this.item = territory.removeItem(x, y);
+ }
+ territory.setChanged();
+ territory.notifyAllObservers();
+ }
- /**
- * If a pile of scrap is ahead of Robbi and afterwards a nonblocking tile, Robbi
- * pushes the pile of scrap one tile the direction he is facing.
- */
- public final void schiebeSchrotthaufen() {
- synchronized (territory) {
- territory.deactivateNotification();
- if (!vornSchrotthaufen()) {
- territory.activateNotification();
- throw new NoPileOfScrapAheadException();
- }
- int dx = switch (facing) {
- case EAST -> x + 2;
- case WEST -> x - 2;
- default -> x;
- };
- int dy = switch (facing) {
- case NORTH -> y - 2;
- case SOUTH -> y + 2;
- default -> y;
- };
+ /**
+ * If a pile of scrap is ahead of Robbi and afterward a nonblocking tile, Robbi
+ * pushes the pile of scrap one tile the direction he is facing.
+ */
+ public final void schiebeSchrotthaufen() {
+ synchronized (territory) {
+ territory.deactivateNotification();
+ if (!vornSchrotthaufen()) {
+ territory.activateNotification();
+ throw new NoPileOfScrapAheadException();
+ }
+ int dx = switch (facing) {
+ case EAST -> x + 2;
+ case WEST -> x - 2;
+ default -> x;
+ };
+ int dy = switch (facing) {
+ case NORTH -> y - 2;
+ case SOUTH -> y + 2;
+ default -> y;
+ };
- Tile t = territory.getTile(dx, dy);
- if (t instanceof Stockpile || t instanceof PileOfScrap) {
- territory.activateNotification();
- throw new TileBlockedException();
- } else {
- if (territory.getTile(dx, dy) instanceof Hollow)
- territory.clearTile(dx, dy);
- else
- territory.placePileOfScrap(dx, dy);
- int px = switch (facing) {
- case EAST -> x + 1;
- case WEST -> x - 1;
- default -> x;
- };
- int py = switch (facing) {
- case NORTH -> y - 1;
- case SOUTH -> y + 1;
- default -> y;
- };
- territory.clearTile(px, py);
- }
- vor();
- }
- territory.activateNotification();
- }
+ Tile t = territory.getTile(dx, dy);
+ if (t instanceof Stockpile || t instanceof PileOfScrap) {
+ territory.activateNotification();
+ throw new TileBlockedException();
+ } else {
+ if (territory.getTile(dx, dy) instanceof Hollow)
+ territory.clearTile(dx, dy);
+ else
+ territory.placePileOfScrap(dx, dy);
+ int px = switch (facing) {
+ case EAST -> x + 1;
+ case WEST -> x - 1;
+ default -> x;
+ };
+ int py = switch (facing) {
+ case NORTH -> y - 1;
+ case SOUTH -> y + 1;
+ default -> y;
+ };
+ territory.clearTile(px, py);
+ }
+ vor();
+ }
+ territory.activateNotification();
+ }
- /**
- * checks if an Item is on the tile Robbi is on.
- *
- * @return true if an item is on robbis tile, false otherwise
- */
- public final boolean gegenstandDa() {
- synchronized (territory) {
- return territory.getItem(x, y) != null;
- }
- }
+ /**
+ * checks if an Item is on the tile Robbi is on.
+ *
+ * @return true if an item is on robbi's tile, false otherwise
+ */
+ public final boolean gegenstandDa() {
+ synchronized (territory) {
+ return territory.getItem(x, y) != null;
+ }
+ }
- /**
- * Checks if the tile on which Robbi stands is a stockpile
- *
- * @return true if the current tile is an instanceof Stockpile, false otherwise
- */
- public final boolean istLagerplatz() {
- synchronized (territory) {
- return territory.getTile(x, y) instanceof Stockpile;
- }
- }
+ /**
+ * Checks if the tile on which Robbi stands is a stockpile
+ *
+ * @return true if the current tile is an instanceof Stockpile, false otherwise
+ */
+ public final boolean istLagerplatz() {
+ synchronized (territory) {
+ return territory.getTile(x, y) instanceof Stockpile;
+ }
+ }
- /**
- * checks if a hollow is ahead of Robbi.
- *
- * @return true if an hollow is ahead, false otherwise
- */
- public final boolean vornKuhle() {
- synchronized (territory) {
- int dx = switch (facing) {
- case EAST -> x + 1;
- case WEST -> x - 1;
- default -> x;
- };
- int dy = switch (facing) {
- case NORTH -> y - 1;
- case SOUTH -> y + 1;
- default -> y;
- };
- return territory.getTile(dx, dy) instanceof Hollow;
- }
- }
+ /**
+ * checks if a hollow is ahead of Robbi.
+ *
+ * @return true if a hollow is ahead, false otherwise
+ */
+ public final boolean vornKuhle() {
+ synchronized (territory) {
+ int dx = switch (facing) {
+ case EAST -> x + 1;
+ case WEST -> x - 1;
+ default -> x;
+ };
+ int dy = switch (facing) {
+ case NORTH -> y - 1;
+ case SOUTH -> y + 1;
+ default -> y;
+ };
+ return territory.getTile(dx, dy) instanceof Hollow;
+ }
+ }
- /**
- * checks if a pile of scrap is ahead of Robbi.
- *
- * @return true if a pile of scrap is ahead of robbi, false otherwise
- */
- public final boolean vornSchrotthaufen() {
- synchronized (territory) {
- int dx = switch (facing) {
- case EAST -> x + 1;
- case WEST -> x - 1;
- default -> x;
- };
- int dy = switch (facing) {
- case NORTH -> y - 1;
- case SOUTH -> y + 1;
- default -> y;
- };
- return territory.getTile(dx, dy) instanceof PileOfScrap;
- }
- }
+ /**
+ * checks if a pile of scrap is ahead of Robbi.
+ *
+ * @return true if a pile of scrap is ahead of robbi, false otherwise
+ */
+ public final boolean vornSchrotthaufen() {
+ synchronized (territory) {
+ int dx = switch (facing) {
+ case EAST -> x + 1;
+ case WEST -> x - 1;
+ default -> x;
+ };
+ int dy = switch (facing) {
+ case NORTH -> y - 1;
+ case SOUTH -> y + 1;
+ default -> y;
+ };
+ return territory.getTile(dx, dy) instanceof PileOfScrap;
+ }
+ }
- /**
- * checks if an item is in Robbis bag.
- *
- * @return true if an item is in the bag, false otherwise
- */
- public final boolean istTascheVoll() {
- synchronized (territory) {
- return item != null;
- }
- }
+ /**
+ * checks if an item is in Robbi's bag.
+ *
+ * @return true if an item is in the bag, false otherwise
+ */
+ public final boolean istTascheVoll() {
+ synchronized (territory) {
+ return item != null;
+ }
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/RobbiException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/RobbiException.java
index 7cf5bac..5a81d04 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/RobbiException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/RobbiException.java
@@ -2,29 +2,31 @@
import com.JayPi4c.RobbiSimulator.utils.I18nUtils;
+import java.io.Serial;
+
/**
* Abstract Exception class for almost all exceptions thrown in this
* application.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public abstract class RobbiException extends RuntimeException {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new RobbiException with the given message key.
- *
- * @param key a key for a message to provide further details of the exception
- */
- protected RobbiException(String key) {
- super(key);
- }
+ /**
+ * Constructor for a new RobbiException with the given message key.
+ *
+ * @param key a key for a message to provide further details of the exception
+ */
+ protected RobbiException(String key) {
+ super(key);
+ }
- @Override
- public String getLocalizedMessage() {
- return I18nUtils.i18n(getMessage());
- }
+ @Override
+ public String getLocalizedMessage() {
+ return I18nUtils.i18n(getMessage());
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/RobbiState.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/RobbiState.java
index 5685ebf..cfa7c77 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/RobbiState.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/RobbiState.java
@@ -11,9 +11,8 @@
/**
* Robbi State to store all state relevant attributes in order to apply the
* Memento-Pattern.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@XmlRootElement
@Getter
@@ -21,16 +20,16 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RobbiState {
- @XmlElement
- private int x;
+ @XmlElement
+ private int x;
- @XmlElement
- private int y;
+ @XmlElement
+ private int y;
- @XmlElement
- private DIRECTION facing;
+ @XmlElement
+ private DIRECTION facing;
- @XmlAnyElement
- private Item item;
+ @XmlAnyElement
+ private Item item;
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Screw.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Screw.java
index 77f3e92..31cb71c 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Screw.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Screw.java
@@ -2,15 +2,17 @@
import jakarta.xml.bind.annotation.XmlRootElement;
+import java.io.Serial;
+
/**
* Class representing the screw-item.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@XmlRootElement
public class Screw implements Item {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Stockpile.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Stockpile.java
index d35a58c..3b525d5 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Stockpile.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Stockpile.java
@@ -1,79 +1,80 @@
package com.JayPi4c.RobbiSimulator.model;
-import java.util.ArrayList;
-import java.util.List;
-
import jakarta.xml.bind.annotation.XmlAnyElement;
import jakarta.xml.bind.annotation.XmlElementWrapper;
import jakarta.xml.bind.annotation.XmlRootElement;
+import java.io.Serial;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Class representing a Stockpile tile.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@XmlRootElement
public class Stockpile extends Tile {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Attribute to store all items placed on the tile
- */
- @XmlElementWrapper
- @XmlAnyElement(lax = true)
- private ArrayList- items;
- // TODO Queue more efficient?
- // check if queue would be better, allowing an easier iteration over the
- // elements.
+ /**
+ * Attribute to store all items placed on the tile
+ */
+ @XmlElementWrapper
+ @XmlAnyElement(lax = true)
+ private final List
- items;
+ // TODO Queue more efficient?
+ // check if queue would be better, allowing an easier iteration over the
+ // elements.
- /**
- * Constructor to create a new Stockpile and initialize the list of items on the
- * stockpile.
- */
- public Stockpile() {
- items = new ArrayList<>();
- }
+ /**
+ * Constructor to create a new Stockpile and initialize the list of items on the
+ * stockpile.
+ */
+ public Stockpile() {
+ items = new ArrayList<>();
+ }
- /**
- * Adds the given item to the list of items on the stockpile.
- *
- * @param item the item to add to the stockpile
- */
- @Override
- public void setItem(Item item) {
- items.add(item);
- }
+ /**
+ * Adds the given item to the list of items on the stockpile.
+ *
+ * @param item the item to add to the stockpile
+ */
+ @Override
+ public void setItem(Item item) {
+ items.add(item);
+ }
- /**
- * Iterates through the list of items in the stockpile and returns one.
- *
- * @return the last item added to the stockpile, null if no item is placed on
- * the stockpile
- */
- @Override
- public Item getItem() {
- return (items.isEmpty()) ? null : items.get(items.size() - 1);
- }
+ /**
+ * Iterates through the list of items in the stockpile and returns one.
+ *
+ * @return the last item added to the stockpile, null if no item is placed on
+ * the stockpile
+ */
+ @Override
+ public Item getItem() {
+ return (items.isEmpty()) ? null : items.getLast();
+ }
- /**
- * Removes and returns the last item from the stockpile.
- *
- * @return the last item added to the stockpile, null if no item was added yet
- */
- @Override
- public Item pickItem() {
- return items.remove(items.size() - 1);
- }
+ /**
+ * Removes and returns the last item from the stockpile.
+ *
+ * @return the last item added to the stockpile, null if no item was added yet
+ */
+ @Override
+ public Item pickItem() {
+ return items.removeLast();
+ }
- /**
- * Returns the full list of items placed on the stockpile.
- *
- * @return the arrayList containing all items on this stockpile
- */
- public List
- getAllItems() {
- return items;
- }
+ /**
+ * Returns the full list of items placed on the stockpile.
+ *
+ * @return the arrayList containing all items on this stockpile
+ */
+ public List
- getAllItems() {
+ return items;
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Territory.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Territory.java
index 01b9494..58625ff 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Territory.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Territory.java
@@ -1,26 +1,13 @@
package com.JayPi4c.RobbiSimulator.model;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Serializable;
-import java.util.Optional;
-
-import javax.xml.XMLConstants;
-import javax.xml.stream.FactoryConfigurationError;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.stream.XMLStreamWriter;
-
import com.JayPi4c.RobbiSimulator.utils.Observable;
-
import lombok.extern.slf4j.Slf4j;
+import javax.xml.XMLConstants;
+import javax.xml.stream.*;
+import java.io.*;
+import java.util.Optional;
+
/**
* This class contains all datastructures and utility functions to control the
* territory.
@@ -30,6 +17,7 @@
@Slf4j
public class Territory extends Observable implements Serializable {
+ @Serial
private static final long serialVersionUID = 1L;
private transient Robbi robbi;
@@ -175,16 +163,16 @@ public synchronized Robbi getRobbi() {
}
/**
- * Getter for robbis current direction.
+ * Getter for robbi's current direction.
*
- * @return robbis current direction
+ * @return robbi's current direction
*/
public synchronized DIRECTION getRobbiDirection() {
return robbi.getFacing();
}
/**
- * Getter for robbis current item.
+ * Getter for robbi's current item.
*
* @return the item robbi is currently holding. null, if robbi does not have
* one.
@@ -200,7 +188,7 @@ public synchronized Item getRobbiItem() {
* @param bound the bound to limit i to
* @return the normalized value of i
*/
- private int normalizeCoord(int i, int bound) {
+ private int normalizeCoordinate(int i, int bound) {
i %= bound;
i += bound;
i %= bound;
@@ -229,7 +217,7 @@ public synchronized boolean robbiOnTile(int col, int row) {
*/
public boolean placeItem(Item item, int x, int y) {
synchronized (this) {
- Tile t = tiles[normalizeCoord(x, numberOfColumns)][normalizeCoord(y, numberOfRows)];
+ Tile t = tiles[normalizeCoordinate(x, numberOfColumns)][normalizeCoordinate(y, numberOfRows)];
if (t.getItem() != null && !(t instanceof Stockpile))
return false;
t.setItem(item);
@@ -247,7 +235,7 @@ public boolean placeItem(Item item, int x, int y) {
* @return the item, which is placed at the given position
*/
public synchronized Item getItem(int x, int y) {
- Tile t = tiles[normalizeCoord(x, numberOfColumns)][normalizeCoord(y, numberOfRows)];
+ Tile t = tiles[normalizeCoordinate(x, numberOfColumns)][normalizeCoordinate(y, numberOfRows)];
return t.getItem();
}
@@ -259,9 +247,9 @@ public synchronized Item getItem(int x, int y) {
* @return the item that has been removed from the tile
*/
public Item removeItem(int x, int y) {
- Item i = null;
+ Item i;
synchronized (this) {
- Tile t = tiles[normalizeCoord(x, numberOfColumns)][normalizeCoord(y, numberOfRows)];
+ Tile t = tiles[normalizeCoordinate(x, numberOfColumns)][normalizeCoordinate(y, numberOfRows)];
i = t.pickItem();
}
setChanged();
@@ -277,9 +265,9 @@ public Item removeItem(int x, int y) {
*
* @param territory the new territory
* @param item the item robbi has in his bag
- * @param x robbis x position
- * @param y robbis y positions
- * @param facing robbis facing
+ * @param x robbi's x position
+ * @param y robbi's y positions
+ * @param facing robbi's facing
* @throws InvalidTerritoryException if it is impossible to create the territory
* with the given information
*/
@@ -355,8 +343,8 @@ public void changeSize(int newCols, int newRows) {
/**
* move robbi to the given position.
*
- * @param x robbis new x-position
- * @param y robbis new y-position
+ * @param x robbi's new x-position
+ * @param y robbi's new y-position
*/
public void placeRobbi(int x, int y) {
synchronized (this) {
@@ -372,12 +360,12 @@ public void placeRobbi(int x, int y) {
* Place a new Hollow at the given position if it is in bounds and robbi is not
* on the tile.
*
- * @param x Hollows x-Position
- * @param y Hollows y-Position
+ * @param x Hollow's x-Position
+ * @param y Hollow's y-Position
*/
public void placeHollow(int x, int y) {
- x = normalizeCoord(x, numberOfColumns);
- y = normalizeCoord(y, numberOfRows);
+ x = normalizeCoordinate(x, numberOfColumns);
+ y = normalizeCoordinate(y, numberOfRows);
synchronized (this) {
if ((x < numberOfColumns && y < numberOfRows) && !(x == robbi.getX() && y == robbi.getY()))
tiles[x][y] = new Hollow();
@@ -395,8 +383,8 @@ public void placeHollow(int x, int y) {
* @param y PileOfScrap y-Position
*/
public void placePileOfScrap(int x, int y) {
- x = normalizeCoord(x, numberOfColumns);
- y = normalizeCoord(y, numberOfRows);
+ x = normalizeCoordinate(x, numberOfColumns);
+ y = normalizeCoordinate(y, numberOfRows);
synchronized (this) {
tiles[x][y] = new PileOfScrap();
}
@@ -412,8 +400,8 @@ public void placePileOfScrap(int x, int y) {
* @param y Stockpile y-Position
*/
public void placeStockpile(int x, int y) {
- x = normalizeCoord(x, numberOfColumns);
- y = normalizeCoord(y, numberOfRows);
+ x = normalizeCoordinate(x, numberOfColumns);
+ y = normalizeCoordinate(y, numberOfRows);
synchronized (this) {
tiles[x][y] = new Stockpile();
}
@@ -428,8 +416,8 @@ public void placeStockpile(int x, int y) {
* @param y Accu y-Position
*/
public void placeAccu(int x, int y) {
- x = normalizeCoord(x, numberOfColumns);
- y = normalizeCoord(y, numberOfRows);
+ x = normalizeCoordinate(x, numberOfColumns);
+ y = normalizeCoordinate(y, numberOfRows);
synchronized (this) {
tiles[x][y].setItem(new Accu());
}
@@ -445,8 +433,8 @@ public void placeAccu(int x, int y) {
* @param y Screw y-Position
*/
public void placeScrew(int x, int y) {
- x = normalizeCoord(x, numberOfColumns);
- y = normalizeCoord(y, numberOfRows);
+ x = normalizeCoordinate(x, numberOfColumns);
+ y = normalizeCoordinate(y, numberOfRows);
synchronized (this) {
tiles[x][y].setItem(new Screw());
}
@@ -461,8 +449,8 @@ public void placeScrew(int x, int y) {
* @param y Nut y-Position
*/
public void placeNut(int x, int y) {
- x = normalizeCoord(x, numberOfColumns);
- y = normalizeCoord(y, numberOfRows);
+ x = normalizeCoordinate(x, numberOfColumns);
+ y = normalizeCoordinate(y, numberOfRows);
synchronized (this) {
tiles[x][y].setItem(new Nut());
}
@@ -477,8 +465,8 @@ public void placeNut(int x, int y) {
* @param y Tile y-Position
*/
public void clearTile(int x, int y) {
- x = normalizeCoord(x, numberOfColumns);
- y = normalizeCoord(y, numberOfRows);
+ x = normalizeCoordinate(x, numberOfColumns);
+ y = normalizeCoordinate(y, numberOfRows);
synchronized (this) {
tiles[x][y] = new Tile();
}
@@ -549,8 +537,7 @@ public boolean fromXML(InputStream stream) {
}
break;
case "facing":
- DIRECTION facing = DIRECTION.valueOf(parser.getAttributeValue(null, "facing"));
- robbiDirection = facing;
+ robbiDirection = DIRECTION.valueOf(parser.getAttributeValue(null, "facing"));
break;
case "robbi":
robbiX = Integer.parseInt(parser.getAttributeValue(null, "col"));
@@ -579,7 +566,7 @@ public boolean fromXML(InputStream stream) {
try {
stream.close();
} catch (IOException e) {
- e.printStackTrace();
+ logger.error("Could not close stream", e);
}
}
}
@@ -594,14 +581,12 @@ public boolean fromXML(InputStream stream) {
*/
private Item getItemFromParser(XMLStreamReader parser) {
String type = parser.getAttributeValue(null, "type");
- if (type.equals("Nut")) {
- return new Nut();
- } else if (type.equals("Accu")) {
- return new Accu();
- } else if (type.equals("Screw")) {
- return new Screw();
- }
- return null;
+ return switch (type) {
+ case "Nut" -> new Nut();
+ case "Accu" -> new Accu();
+ case "Screw" -> new Screw();
+ default -> null;
+ };
}
/**
@@ -689,14 +674,13 @@ public ByteArrayOutputStream toXML() {
return baos;
} catch (FactoryConfigurationError | XMLStreamException e) {
- e.printStackTrace();
- logger.error("failed to save as XML.");
+ logger.error("failed to save as XML.", e);
return null;
}
}
/**
- * Helper to store an item in an xml-file.
+ * Helper to store an item in a xml-file.
*
* @param writer the writer, the item needs to be written to
* @param item the item to write
@@ -717,7 +701,7 @@ private void writeItem(XMLStreamWriter writer, Item item) throws XMLStreamExcept
*/
private Optional getDTD() {
Optional module = ModuleLayer.boot().findModule("RobbiSimulator");
- if(module.isEmpty()) {
+ if (module.isEmpty()) {
logger.warn("Could not load dtd");
return Optional.empty();
}
@@ -736,18 +720,18 @@ private Optional getDTD() {
}
/**
- * Getter for Robbis x Position.
+ * Getter for Robbi's x Position.
*
- * @return robbis x Position
+ * @return robbi's x Position
*/
public synchronized int getRobbiX() {
return robbi.getX();
}
/**
- * Getter for Robbis y Position.
+ * Getter for Robbi's y Position.
*
- * @return robbis y Position
+ * @return robbi's y Position
*/
public synchronized int getRobbiY() {
return robbi.getY();
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/TerritoryState.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/TerritoryState.java
index 592104f..556a239 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/TerritoryState.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/TerritoryState.java
@@ -9,59 +9,58 @@
/**
* Territory State to store all state relevant attributes in order to apply the
* Memento-Pattern.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@XmlRootElement
@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TerritoryState {
- @XmlElement
- private int numberOfColumns;
- @XmlElement
- private int numberOfRows;
-
- @XmlElement
- private Tile[][] tiles;
- @XmlElement
- private RobbiState robbiState;
+ @XmlElement
+ private int numberOfColumns;
+ @XmlElement
+ private int numberOfRows;
- /**
- * Constructor to create a Territory state. Creates an independet copy of the
- * tiles array and the robbi.
- *
- * @param numberOfColumns number of columns in the territory
- * @param numberOfRows number of rows in the territory
- * @param tiles the tiles array representing the territory
- * @param robbi the robbi in the territory
- */
- public TerritoryState(int numberOfColumns, int numberOfRows, Tile[][] tiles, Robbi robbi) {
- this.numberOfColumns = numberOfColumns;
- this.numberOfRows = numberOfRows;
- this.tiles = new Tile[tiles.length][tiles[0].length];
- for (int i = 0; i < tiles.length; i++) {
- for (int j = 0; j < tiles[i].length; j++) {
- Tile t = tiles[i][j];
- Tile newTile;
- if (t instanceof Hollow) {
- newTile = new Hollow();
- } else if (t instanceof PileOfScrap) {
- newTile = new PileOfScrap();
- } else if (t instanceof Stockpile stockpile) {
- newTile = new Stockpile();
- for (Item item : stockpile.getAllItems())
- newTile.setItem(item);
- } else {
- newTile = new Tile();
- newTile.setItem(t.getItem());
- }
- this.tiles[i][j] = newTile;
+ @XmlElement
+ private Tile[][] tiles;
+ @XmlElement
+ private RobbiState robbiState;
- }
- }
- this.robbiState = new RobbiState(robbi.getX(), robbi.getY(), robbi.getFacing(), robbi.getItem());
- }
+ /**
+ * Constructor to create a Territory state. Creates an independent copy of the
+ * tiles array and the robbi.
+ *
+ * @param numberOfColumns number of columns in the territory
+ * @param numberOfRows number of rows in the territory
+ * @param tiles the tiles array representing the territory
+ * @param robbi the robbi in the territory
+ */
+ public TerritoryState(int numberOfColumns, int numberOfRows, Tile[][] tiles, Robbi robbi) {
+ this.numberOfColumns = numberOfColumns;
+ this.numberOfRows = numberOfRows;
+ this.tiles = new Tile[tiles.length][tiles[0].length];
+ for (int i = 0; i < tiles.length; i++) {
+ for (int j = 0; j < tiles[i].length; j++) {
+ Tile newTile = switch (tiles[i][j]) {
+ case Hollow ignored:
+ yield new Hollow();
+ case PileOfScrap ignored:
+ yield new PileOfScrap();
+ case Stockpile stockpile:
+ Stockpile s = new Stockpile();
+ for (Item item : stockpile.getAllItems())
+ s.setItem(item);
+ yield s;
+ case Tile t:
+ Tile t2 = new Tile();
+ t2.setItem(t.getItem());
+ yield t2;
+ };
+ this.tiles[i][j] = newTile;
+ }
+ }
+ this.robbiState = new RobbiState(robbi.getX(), robbi.getY(), robbi.getFacing(), robbi.getItem());
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/Tile.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/Tile.java
index e8f79e6..7f3caba 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/Tile.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/Tile.java
@@ -1,7 +1,5 @@
package com.JayPi4c.RobbiSimulator.model;
-import java.io.Serializable;
-
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAnyElement;
@@ -9,35 +7,38 @@
import lombok.Getter;
import lombok.Setter;
+import java.io.Serial;
+import java.io.Serializable;
+
/**
* The default Tile for the territory.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
+@Getter
+@Setter
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Tile implements Serializable {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Attribute to store the item whoch is placed on the tile.
- */
- @Getter
- @Setter
- @XmlAnyElement(lax = true)
- private Item item = null;
+ /**
+ * Attribute to store the item which is placed on the tile.
+ */
+ @XmlAnyElement(lax = true)
+ private Item item = null;
- /**
- * Removes the item from the tile and returns it.
- *
- * @return the item stored on the tile
- */
- public Item pickItem() {
- Item it = item;
- item = null;
- return it;
- }
+ /**
+ * Removes the item from the tile and returns it.
+ *
+ * @return the item stored on the tile
+ */
+ public Item pickItem() {
+ Item it = item;
+ item = null;
+ return it;
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/TileBlockedException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/TileBlockedException.java
index e8e4fe9..50a4728 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/TileBlockedException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/TileBlockedException.java
@@ -1,21 +1,23 @@
package com.JayPi4c.RobbiSimulator.model;
+import java.io.Serial;
+
/**
* Exception to be thrown if robbi attempts to move a pile of Scrap while the
* tile ahead is not suitable to push a pile to.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class TileBlockedException extends RobbiException {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new TileBlockedException with localized message.
- */
- public TileBlockedException() {
- super("Exception.TileBlocked");
- }
+ /**
+ * Constructor for a new TileBlockedException with localized message.
+ */
+ public TileBlockedException() {
+ super("Exception.TileBlocked");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/model/TileIsFullException.java b/src/main/java/com/JayPi4c/RobbiSimulator/model/TileIsFullException.java
index 8aeb97b..c3c6efa 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/model/TileIsFullException.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/model/TileIsFullException.java
@@ -1,21 +1,23 @@
package com.JayPi4c.RobbiSimulator.model;
+import java.io.Serial;
+
/**
* Exception to be thrown if robbi attempts to place an item on a tile, that has
* already an item stored.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class TileIsFullException extends RobbiException {
- private static final long serialVersionUID = 1L;
+ @Serial
+ private static final long serialVersionUID = 1L;
- /**
- * Constructor for a new TileIsFullException with localized message.
- */
- public TileIsFullException() {
- super("Exception.TileIsFull");
- }
+ /**
+ * Constructor for a new TileIsFullException with localized message.
+ */
+ public TileIsFullException() {
+ super("Exception.TileIsFull");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/AlertHelper.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/AlertHelper.java
index f020d40..272d006 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/AlertHelper.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/AlertHelper.java
@@ -9,104 +9,103 @@
/**
* Static class to create Alerts with the necessary information.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class AlertHelper {
- /**
- * Creates and shows an alert with the given information.
- *
- * @param type the AlertType of the alert
- * @param message the contentText for the alert
- * @param owner the alerts owner to place it relative to the parent
- */
- public static void showAlertAndWait(AlertType type, String message, Window owner) {
- Alert alert = createAlert(type, message, owner);
- alert.showAndWait();
- }
+ /**
+ * Creates and shows an alert with the given information.
+ *
+ * @param type the AlertType of the alert
+ * @param message the contentText for the alert
+ * @param owner the alerts owner to place it relative to the parent
+ */
+ public static void showAlertAndWait(AlertType type, String message, Window owner) {
+ Alert alert = createAlert(type, message, owner);
+ alert.showAndWait();
+ }
- /**
- * Creates and shows an alert with the given information.
- *
- * @param type the AlertType of the alert
- * @param message the contentText for the alert
- * @param owner the alerts owner to place it relative to the parent
- * @param modality the modality of the alert
- */
- public static void showAlertAndWait(AlertType type, String message, Window owner, Modality modality) {
- Alert alert = createAlert(type, message, owner, modality);
- alert.showAndWait();
- }
+ /**
+ * Creates and shows an alert with the given information.
+ *
+ * @param type the AlertType of the alert
+ * @param message the contentText for the alert
+ * @param owner the alerts owner to place it relative to the parent
+ * @param modality the modality of the alert
+ */
+ public static void showAlertAndWait(AlertType type, String message, Window owner, Modality modality) {
+ Alert alert = createAlert(type, message, owner, modality);
+ alert.showAndWait();
+ }
- /**
- * Creates and shows an alert with the given information.
- *
- * @param type the AlertType of the alert
- * @param message the contentText for the alert
- * @param owner the alerts owner to place it relative to the parent
- * @param modality the modality of the alert
- * @param title the title for the alert
- * @param header the header for the alert
- */
- public static void showAlertAndWait(AlertType type, String message, Window owner, Modality modality, String title,
- String header) {
- Alert alert = createAlert(type, message, owner, modality, title, header);
- alert.showAndWait();
- }
+ /**
+ * Creates and shows an alert with the given information.
+ *
+ * @param type the AlertType of the alert
+ * @param message the contentText for the alert
+ * @param owner the alerts owner to place it relative to the parent
+ * @param modality the modality of the alert
+ * @param title the title for the alert
+ * @param header the header for the alert
+ */
+ public static void showAlertAndWait(AlertType type, String message, Window owner, Modality modality, String title,
+ String header) {
+ Alert alert = createAlert(type, message, owner, modality, title, header);
+ alert.showAndWait();
+ }
- /**
- * Creates an alert with the given information.
- *
- * @param type the AlertType of the alert
- * @param message the contentText for the alert
- * @param owner the alerts owner to place it relative to the parent
- * @param modality the modality of the alert
- * @param title the title for the alert
- * @param header the header for the alert
- * @return the alert with the given information
- */
- public static Alert createAlert(AlertType type, String message, Window owner, Modality modality, String title,
- String header) {
- Alert alert = new Alert(type);
- alert.setContentText(message);
- if (title != null)
- alert.setTitle(title);
- if (header != null)
- alert.setHeaderText(header);
- alert.initModality(modality);
- alert.initOwner(owner);
- return alert;
- }
+ /**
+ * Creates an alert with the given information.
+ *
+ * @param type the AlertType of the alert
+ * @param message the contentText for the alert
+ * @param owner the alerts owner to place it relative to the parent
+ * @param modality the modality of the alert
+ * @param title the title for the alert
+ * @param header the header for the alert
+ * @return the alert with the given information
+ */
+ public static Alert createAlert(AlertType type, String message, Window owner, Modality modality, String title,
+ String header) {
+ Alert alert = new Alert(type);
+ alert.setContentText(message);
+ if (title != null)
+ alert.setTitle(title);
+ if (header != null)
+ alert.setHeaderText(header);
+ alert.initModality(modality);
+ alert.initOwner(owner);
+ return alert;
+ }
- /**
- * Creates an alert with the given information.
- *
- * @param type the AlertType of the alert
- * @param message the contentText for the alert
- * @param owner the alerts owner to place it relative to the parent
- * @param modality the modality of the alert
- * @return the alert with the given information
- */
- public static Alert createAlert(AlertType type, String message, Window owner, Modality modality) {
- return createAlert(type, message, owner, modality, null, null);
- }
+ /**
+ * Creates an alert with the given information.
+ *
+ * @param type the AlertType of the alert
+ * @param message the contentText for the alert
+ * @param owner the alerts owner to place it relative to the parent
+ * @param modality the modality of the alert
+ * @return the alert with the given information
+ */
+ public static Alert createAlert(AlertType type, String message, Window owner, Modality modality) {
+ return createAlert(type, message, owner, modality, null, null);
+ }
- /**
- * Creates an alert with the given information.
- *
- * @param type the AlertType of the alert
- * @param message the contentText for the alert
- * @param owner the alerts owner to place it relative to the parent
- * @return the alert with the given information
- */
- public static Alert createAlert(AlertType type, String message, Window owner) {
- Alert alert = new Alert(type);
- alert.setContentText(message);
- alert.initOwner(owner);
- return alert;
- }
+ /**
+ * Creates an alert with the given information.
+ *
+ * @param type the AlertType of the alert
+ * @param message the contentText for the alert
+ * @param owner the alerts owner to place it relative to the parent
+ * @return the alert with the given information
+ */
+ public static Alert createAlert(AlertType type, String message, Window owner) {
+ Alert alert = new Alert(type);
+ alert.setContentText(message);
+ alert.initOwner(owner);
+ return alert;
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/HibernateUtils.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/HibernateUtils.java
index c6f7174..0289b37 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/HibernateUtils.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/HibernateUtils.java
@@ -1,15 +1,14 @@
package com.JayPi4c.RobbiSimulator.utils;
-import org.hibernate.SessionFactory;
-import org.hibernate.cfg.Configuration;
-
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
/**
* Utility class to manage the Hibernate SessionFactory.
- *
+ *
* @author Jonas Pohl
* @since 1.0.0
*/
@@ -17,37 +16,36 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class HibernateUtils {
- /**
- * The session factory to interact with the database via hibernate.
- */
- private static SessionFactory sessionFactory;
+ /**
+ * The session factory to interact with the database via hibernate.
+ */
+ private static SessionFactory sessionFactory;
- /**
- * Getter for the SessionFactory. If the SessionFactory is null, it will be
- * created.
- *
- * @return The SessionFactory.
- *
- */
- public static SessionFactory getSessionFactory() {
- if (sessionFactory == null) {
- System.setProperty("derby.stream.error.file", "logs/derby.log"); // make sure log-file is in logs folder
- try {
- sessionFactory = new Configuration().configure().buildSessionFactory();
- } catch (Exception ex) {
- logger.error("Initial SessionFactory creation failed: {}", ex);
- throw new ExceptionInInitializerError(ex);
- }
- }
- return sessionFactory;
- }
+ /**
+ * Getter for the SessionFactory. If the SessionFactory is null, it will be
+ * created.
+ *
+ * @return The SessionFactory.
+ */
+ public static SessionFactory getSessionFactory() {
+ if (sessionFactory == null) {
+ System.setProperty("derby.stream.error.file", "logs/derby.log"); // make sure log-file is in logs folder
+ try {
+ sessionFactory = new Configuration().configure().buildSessionFactory();
+ } catch (Exception ex) {
+ logger.error("Initial SessionFactory creation failed.", ex);
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+ return sessionFactory;
+ }
- /**
- * Utility function to shutdown the database connection.
- */
- public static void shutdown() {
- if (sessionFactory != null)
- sessionFactory.close();
- }
+ /**
+ * Utility function to shut down the database connection.
+ */
+ public static void shutdown() {
+ if (sessionFactory != null)
+ sessionFactory.close();
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/I18nUtils.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/I18nUtils.java
index 89c460c..3897137 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/I18nUtils.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/I18nUtils.java
@@ -1,9 +1,5 @@
package com.JayPi4c.RobbiSimulator.utils;
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.ResourceBundle;
-
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.ObjectProperty;
@@ -13,9 +9,13 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
/**
* Utility-Class to support internationalization.
- *
+ *
*
* Some research pointed out the eclipse solution for i18n. For further
* information have a look in the this
* Stack Overflow article.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class I18nUtils {
- /**
- * The resource bundle on which elements can bind in order to be updated on
- * language change.
- */
- private static final ObjectProperty bundle = new SimpleObjectProperty<>();
+ /**
+ * The resource bundle on which elements can bind in order to be updated on
+ * language change.
+ */
+ private static final ObjectProperty bundle = new SimpleObjectProperty<>();
- /**
- * The current locale. Will be initially set to {@link Locale#UK} in JavaFX init
- * Method.
- *
- */
- @Getter
- private static Locale locale;
+ /**
+ * The current locale. Will be initially set to {@link Locale#UK} in JavaFX init
+ * Method.
+ */
+ @Getter
+ private static Locale locale;
- static {
- setLocale(PropertiesLoader.getLocale());
- }
+ static {
+ setLocale(PropertiesLoader.getLocale());
+ }
- /**
- * ObjectProperty to allow bindings
- *
- * @return The ObjectProperty
- */
- public static ObjectProperty bundleProperty() {
- return bundle;
- }
+ /**
+ * ObjectProperty to allow bindings
+ *
+ * @return The ObjectProperty
+ */
+ public static ObjectProperty bundleProperty() {
+ return bundle;
+ }
- /**
- * Getter for the current locale.
- *
- * @return the current locale
- */
- public static ResourceBundle getBundle() {
- return bundle.get();
- }
+ /**
+ * Getter for the current locale.
+ *
+ * @return the current locale
+ */
+ public static ResourceBundle getBundle() {
+ return bundle.get();
+ }
- /**
- * Setter for the current resourceBundle.
- *
- * @param bundle the new bundle
- */
- public static void setBundle(ResourceBundle bundle) {
- bundleProperty().set(bundle);
- }
+ /**
+ * Setter for the current resourceBundle.
+ *
+ * @param bundle the new bundle
+ */
+ public static void setBundle(ResourceBundle bundle) {
+ bundleProperty().set(bundle);
+ }
- /**
- * Returns the String mapped to the provided key in the current locale.
- *
- * @param key the key to be mapped
- * @param args the arguments to be inserted into the String
- * @return the localized String for the key
- */
- public static String i18n(String key, final Object... args) {
- return MessageFormat.format(getBundle().getString(key), args);
- }
+ /**
+ * Returns the String mapped to the provided key in the current locale.
+ *
+ * @param key the key to be mapped
+ * @param args the arguments to be inserted into the String
+ * @return the localized String for the key
+ */
+ public static String i18n(String key, final Object... args) {
+ return MessageFormat.format(getBundle().getString(key), args);
+ }
- /**
- * Helper to create a new String Binding for the provided key.
- *
- * @param key the key to be mapped on the resources
- * @param args the arguments to be inserted into the String
- * @return a binding for the provided key
- */
- public static StringBinding createBinding(String key, final Object... args) {
- return Bindings.createStringBinding(() -> i18n(key, args), bundleProperty());
- }
+ /**
+ * Helper to create a new String Binding for the provided key.
+ *
+ * @param key the key to be mapped on the resources
+ * @param args the arguments to be inserted into the String
+ * @return a binding for the provided key
+ */
+ public static StringBinding createBinding(String key, final Object... args) {
+ return Bindings.createStringBinding(() -> i18n(key, args), bundleProperty());
+ }
- /**
- * Method to create a tooltip for the given key and object parameters
- *
- * @param key the key for the language file
- * @param args the arguments for the language file
- * @return a i18n tooltip
- */
- public static Tooltip createTooltip(String key, final Object... args) {
- Tooltip tt = new Tooltip();
- tt.textProperty().bind(I18nUtils.createBinding(key, args));
- return tt;
- }
+ /**
+ * Method to create a tooltip for the given key and object parameters
+ *
+ * @param key the key for the language file
+ * @param args the arguments for the language file
+ * @return a i18n tooltip
+ */
+ public static Tooltip createTooltip(String key, final Object... args) {
+ Tooltip tt = new Tooltip();
+ tt.textProperty().bind(I18nUtils.createBinding(key, args));
+ return tt;
+ }
- /**
- * Sets the bundle to the given locale.
- *
- * @param locale the new locale for the resourceBundle
- */
- public static void setLocale(Locale locale) {
- I18nUtils.locale = locale;
- Locale.setDefault(locale);
- setBundle(ResourceBundle.getBundle("lang.messages", locale));
- }
+ /**
+ * Sets the bundle to the given locale.
+ *
+ * @param locale the new locale for the resourceBundle
+ */
+ public static void setLocale(Locale locale) {
+ I18nUtils.locale = locale;
+ Locale.setDefault(locale);
+ setBundle(ResourceBundle.getBundle("lang.messages", locale));
+ }
- /**
- * Setter for the current locale by the String representation of the locale.
- *
- * @param locale the locale as String
- */
- public static void setLocale(String locale) {
- try {
- String[] parts = locale.split("_");
- setLocale(new Locale(parts[0], parts[1]));
- } catch (IndexOutOfBoundsException | NullPointerException e) {
- setLocale(Locale.UK);
- }
- }
+ /**
+ * Setter for the current locale by the String representation of the locale.
+ *
+ * @param languageTag the locale defined by a language tag
+ */
+ public static void setLocale(String languageTag) {
+ try {
+ setLocale(Locale.forLanguageTag(languageTag));
+ } catch (IndexOutOfBoundsException | NullPointerException e) {
+ setLocale(Locale.UK);
+ }
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/Observable.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/Observable.java
index 23f16d2..2b85e5e 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/Observable.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/Observable.java
@@ -5,83 +5,82 @@
/**
* Abstract class to allow the Observer-Pattern. Classes implementing the
* Observer Interface can register to classes extending this Observable class.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public abstract class Observable {
- private CopyOnWriteArrayList observers; // faster than vector for read access and thread save
+ private final CopyOnWriteArrayList observers; // faster than vector for read access and thread save
- private boolean changed;
+ private boolean changed;
- private boolean notify = true;
+ private boolean notify = true;
- /**
- * Constructor for the Observable class which initializes the observer array.
- */
- protected Observable() {
- observers = new CopyOnWriteArrayList<>();
- changed = false;
- }
+ /**
+ * Constructor for the Observable class which initializes the observer array.
+ */
+ protected Observable() {
+ observers = new CopyOnWriteArrayList<>();
+ changed = false;
+ }
- /**
- * Sets the changed flag to true, in order to allow the notifyAllObservers
- * method to inform all observers.
- */
- public void setChanged() {
- changed = true;
- }
+ /**
+ * Sets the changed flag to true, in order to allow the notifyAllObservers
+ * method to inform all observers.
+ */
+ public void setChanged() {
+ changed = true;
+ }
- /**
- * Notifies all observers that the Observable Object has been updated.
- */
- public void notifyAllObservers() {
- if (notify) {
- if (changed) {
- for (Observer s : observers)
- s.update(this);
- }
- changed = false;
- }
- }
+ /**
+ * Notifies all observers that the Observable Object has been updated.
+ */
+ public void notifyAllObservers() {
+ if (notify) {
+ if (changed) {
+ for (Observer s : observers)
+ s.update(this);
+ }
+ changed = false;
+ }
+ }
- /**
- * Register a new Observer to the list of Observers.
- *
- * @param obs the new Observer to add to the list of observers.
- */
- public void addObserver(Observer obs) {
- observers.add(obs);
- }
+ /**
+ * Register a new Observer to the list of Observers.
+ *
+ * @param obs the new Observer to add to the list of observers.
+ */
+ public void addObserver(Observer obs) {
+ observers.add(obs);
+ }
- /**
- * Removes the given Observer from the list of observers. The Observer will no
- * longer be notified about any updates.
- *
- * @param obs the observer to remove from the list of observers
- * @return true if the observer could be removed, false otherwise
- */
- public boolean removeObserver(Observer obs) {
- return observers.remove(obs);
- }
+ /**
+ * Removes the given Observer from the list of observers. The Observer will no
+ * longer be notified about any updates.
+ *
+ * @param obs the observer to remove from the list of observers
+ * @return true if the observer could be removed, false otherwise
+ */
+ public boolean removeObserver(Observer obs) {
+ return observers.remove(obs);
+ }
- /**
- * Allows to send Notifications to all observers and notifies all Observers if
- * changes have been made while the notifications had been deactivated.
- */
- public void activateNotification() {
- this.notify = true;
- notifyAllObservers();
- }
+ /**
+ * Allows to send Notifications to all observers and notifies all Observers if
+ * changes have been made while the notifications had been deactivated.
+ */
+ public void activateNotification() {
+ this.notify = true;
+ notifyAllObservers();
+ }
- /**
- * Prevents the Observable class from notifying any observers even if
- * notifyAllObservers is called. To activate notifications again, call
- * activateNotification.
- */
- public void deactivateNotification() {
- this.notify = false;
- }
+ /**
+ * Prevents the Observable class from notifying any observers even if
+ * notifyAllObservers is called. To activate notifications again, call
+ * activateNotification.
+ */
+ public void deactivateNotification() {
+ this.notify = false;
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/Observer.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/Observer.java
index 9b78eac..4529ed6 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/Observer.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/Observer.java
@@ -3,18 +3,17 @@
/**
* Interface to allow to register to Observable classes. The update function
* will be called whenever the observable class decides to notify all Observers.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public interface Observer {
- /**
- * Notifies the observer whenever the Observable class is notifying all
- * observers about changes.
- *
- * @param observable the Observable to call the update function.
- */
- public void update(Observable observable);
+ /**
+ * Notifies the observer whenever the Observable class is notifying all
+ * observers about changes.
+ *
+ * @param observable the Observable to call the update function.
+ */
+ void update(Observable observable);
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/PropertiesLoader.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/PropertiesLoader.java
index cadcb8f..15bfc8b 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/PropertiesLoader.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/PropertiesLoader.java
@@ -1,5 +1,9 @@
package com.JayPi4c.RobbiSimulator.utils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -7,160 +11,154 @@
import java.util.Locale;
import java.util.Properties;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
/**
* Utility-class for Properties.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PropertiesLoader {
- private static Properties properties;
-
- private static final String DIR = System.getProperty("user.dir");
- private static final String FILE = "/simulator.properties";
- private static final String COMMENTS = "role=student OR tutor";
-
- private static final String DARKMODE_PROPERTY = "darkmode";
- private static final String SOUNDS_PROPERTY = "sounds";
- private static final String TUTORPORT_PROPERTY = "tutorport";
- private static final String ROLE_PROPERTY = "role";
- private static final String LANGUAGE_PROPERTY = "lang";
- private static final String TUTORHOST_PROPERTY = "tutorhost";
-
- private static final String TUTORHOST_DEFAULT_VALUE = "localhost";
- private static final String TUTORPORT_DEFAULT_VALUE = "3579";
-
- /**
- * Loads the properties and stores them in an Object.
- *
- * If the simulator.properties file can't be found, default values will be
- * loaded.
- *
- * @return true if the initialization was successful, false otherwise
- */
- public static boolean initialize() {
- properties = new Properties();
- try (InputStream in = new FileInputStream(DIR + FILE)) {
- properties.load(in);
- return true;
- } catch (IOException e) {
- loadDefaultProperties();
- return false;
- }
- }
-
- /**
- * Getter for the role
- *
- * @return true if the role is set to tutor, false otherwise
- */
- public static boolean isTutor() {
- try {
- return properties.getProperty(ROLE_PROPERTY).equalsIgnoreCase("tutor");
- } catch (NullPointerException e) {
- properties.put(ROLE_PROPERTY, "student");
- return false;
- }
- }
-
- /**
- * Getter for the sounds property.
- *
- * @return true if the sounds property is set to true
- */
- public static boolean getSounds() {
- return Boolean.parseBoolean(properties.getProperty(SOUNDS_PROPERTY));
- }
-
- /**
- * Getter for the sounds property.
- *
- * @return true if the sounds property is set to true
- */
- public static boolean getDarkmode() {
- return Boolean.parseBoolean(properties.getProperty(DARKMODE_PROPERTY));
- }
-
- /**
- * Getter for the tutorhost.
- *
- * @return the tutorhost stored in the properties file, localhost if no
- * propterty is found
- */
- public static String getTutorhost() {
- String host = properties.getProperty(TUTORHOST_PROPERTY);
- if (host == null) {
- host = TUTORHOST_DEFAULT_VALUE;
- properties.put(TUTORHOST_PROPERTY, host);
- }
- return host;
- }
-
- /**
- * Getter for the tutorport.
- *
- * @return the tutorport stored in the properties file
- */
- public static int getTutorport() {
- try {
- return Integer.parseInt(properties.getProperty(TUTORPORT_PROPERTY));
- } catch (NumberFormatException | NullPointerException e) {
- properties.put(TUTORPORT_PROPERTY, TUTORPORT_DEFAULT_VALUE);
- return Integer.parseInt(TUTORPORT_DEFAULT_VALUE);
- }
- }
-
- /**
- * Getter for the locale.
- *
- * @return the locale stored in the properties file
- */
- public static Locale getLocale() {
- try {
- String[] parts = properties.getProperty(LANGUAGE_PROPERTY).split("_");
- return new Locale(parts[0], parts[1]);
- } catch (IndexOutOfBoundsException | NullPointerException e) {
- logger.debug("Failed to load locale from properties");
- properties.put(LANGUAGE_PROPERTY, Locale.GERMANY.toString());
- return Locale.GERMANY;
- }
- }
-
- /**
- * Stores all properties back in the properties file.
- *
- * @return true, if the saving was successful, false otherwise
- */
- public static boolean finish() {
- properties.put(LANGUAGE_PROPERTY, I18nUtils.getLocale().toString());
- properties.put(SOUNDS_PROPERTY, Boolean.toString(SoundManager.getSound()));
- properties.put(DARKMODE_PROPERTY, Boolean.toString(SceneManager.getDarkmode()));
- try (FileOutputStream fos = new FileOutputStream(DIR + FILE)) {
- properties.store(fos, COMMENTS);
- return true;
- } catch (IOException e) {
- return false;
- }
- }
-
- /**
- * Loads initial values in the properties object. This is needed if the
- * application failed to load properties from the file.
- */
- private static void loadDefaultProperties() {
- properties.put(LANGUAGE_PROPERTY, Locale.GERMANY.toString());
- properties.put(ROLE_PROPERTY, "student");
- properties.put(TUTORPORT_PROPERTY, TUTORPORT_DEFAULT_VALUE);
- properties.put(TUTORHOST_PROPERTY, TUTORHOST_DEFAULT_VALUE);
- properties.put(SOUNDS_PROPERTY, Boolean.toString(false));
- properties.put(DARKMODE_PROPERTY, Boolean.toString(false));
- }
+ private static Properties properties;
+
+ private static final String DIR = System.getProperty("user.dir");
+ private static final String FILE = "/simulator.properties";
+ private static final String COMMENTS = "role=student OR tutor";
+
+ private static final String DARKMODE_PROPERTY = "darkmode";
+ private static final String SOUNDS_PROPERTY = "sounds";
+ private static final String TUTORPORT_PROPERTY = "tutorport";
+ private static final String ROLE_PROPERTY = "role";
+ private static final String LANGUAGE_PROPERTY = "lang";
+ private static final String TUTORHOST_PROPERTY = "tutorhost";
+
+ private static final String TUTORHOST_DEFAULT_VALUE = "localhost";
+ private static final String TUTORPORT_DEFAULT_VALUE = "3579";
+
+ /**
+ * Loads the properties and stores them in an Object.
+ *
+ * If the simulator.properties file can't be found, default values will be
+ * loaded.
+ *
+ * @return true if the initialization was successful, false otherwise
+ */
+ public static boolean initialize() {
+ properties = new Properties();
+ try (InputStream in = new FileInputStream(DIR + FILE)) {
+ properties.load(in);
+ return true;
+ } catch (IOException e) {
+ loadDefaultProperties();
+ return false;
+ }
+ }
+
+ /**
+ * Getter for the role
+ *
+ * @return true if the role is set to tutor, false otherwise
+ */
+ public static boolean isTutor() {
+ try {
+ return properties.getProperty(ROLE_PROPERTY).equalsIgnoreCase("tutor");
+ } catch (NullPointerException e) {
+ properties.put(ROLE_PROPERTY, "student");
+ return false;
+ }
+ }
+
+ /**
+ * Getter for the sounds-property.
+ *
+ * @return true if the sounds property is set to true
+ */
+ public static boolean getSounds() {
+ return Boolean.parseBoolean(properties.getProperty(SOUNDS_PROPERTY));
+ }
+
+ /**
+ * Getter for the darkmode-property.
+ *
+ * @return true if the darkmode property is set to true
+ */
+ public static boolean getDarkmode() {
+ return Boolean.parseBoolean(properties.getProperty(DARKMODE_PROPERTY));
+ }
+
+ /**
+ * Getter for the tutorhost.
+ *
+ * @return the tutorhost stored in the properties file, localhost if no
+ * propterty is found
+ */
+ public static String getTutorhost() {
+ String host = properties.getProperty(TUTORHOST_PROPERTY);
+ if (host == null) {
+ host = TUTORHOST_DEFAULT_VALUE;
+ properties.put(TUTORHOST_PROPERTY, host);
+ }
+ return host;
+ }
+
+ /**
+ * Getter for the tutor-port.
+ *
+ * @return the tutor-port stored in the properties file
+ */
+ public static int getTutorport() {
+ try {
+ return Integer.parseInt(properties.getProperty(TUTORPORT_PROPERTY));
+ } catch (NumberFormatException | NullPointerException e) {
+ properties.put(TUTORPORT_PROPERTY, TUTORPORT_DEFAULT_VALUE);
+ return Integer.parseInt(TUTORPORT_DEFAULT_VALUE);
+ }
+ }
+
+ /**
+ * Getter for the locale.
+ *
+ * @return the locale stored in the properties file
+ */
+ public static Locale getLocale() {
+ try {
+ return Locale.forLanguageTag(properties.getProperty(LANGUAGE_PROPERTY));
+ } catch (IndexOutOfBoundsException | NullPointerException e) {
+ logger.debug("Failed to load locale from properties");
+ properties.put(LANGUAGE_PROPERTY, Locale.GERMANY.toLanguageTag());
+ return Locale.GERMANY;
+ }
+ }
+
+ /**
+ * Stores all properties back in the properties file.
+ *
+ * @return true, if the saving was successful, false otherwise
+ */
+ public static boolean finish() {
+ properties.put(LANGUAGE_PROPERTY, I18nUtils.getLocale().toLanguageTag());
+ properties.put(SOUNDS_PROPERTY, Boolean.toString(SoundManager.getSound()));
+ properties.put(DARKMODE_PROPERTY, Boolean.toString(SceneManager.getDarkmode()));
+ try (FileOutputStream fos = new FileOutputStream(DIR + FILE)) {
+ properties.store(fos, COMMENTS);
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Loads initial values in the properties object. This is needed if the
+ * application failed to load properties from the file.
+ */
+ private static void loadDefaultProperties() {
+ properties.put(LANGUAGE_PROPERTY, Locale.GERMANY.toLanguageTag());
+ properties.put(ROLE_PROPERTY, "student");
+ properties.put(TUTORPORT_PROPERTY, TUTORPORT_DEFAULT_VALUE);
+ properties.put(TUTORHOST_PROPERTY, TUTORHOST_DEFAULT_VALUE);
+ properties.put(SOUNDS_PROPERTY, Boolean.toString(false));
+ properties.put(DARKMODE_PROPERTY, Boolean.toString(false));
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/SceneManager.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/SceneManager.java
index 49b1928..daf24a8 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/SceneManager.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/SceneManager.java
@@ -9,55 +9,54 @@
/**
* Class to manage the loaded scene.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SceneManager {
-
- private static final String DARK_MODE_CSS = Objects.requireNonNull(SceneManager.class.getResource("/css/dark-theme.css")).toExternalForm();
-
- /**
- * The boolean on which elements can bind in order to be updated on dark-mode
- * change.
- */
- private static final ObjectProperty darkmode = new SimpleObjectProperty<>(PropertiesLoader.getDarkmode());
-
- /**
- * ObjectProperty to allow bindings
- *
- * @return The ObjectProperty
- */
- public static ObjectProperty darkmodeProperty() {
- return darkmode;
- }
-
- /**
- * Getter for the current dark-mode flag.
- *
- * @return the current dark-mode setting
- */
- public static boolean getDarkmode() {
- return darkmode.get();
- }
-
- /**
- * Setter for the current dark-mode flag.
- *
- * @param flag the new value
- */
- public static void setDarkmode(boolean flag) {
- darkmodeProperty().set(flag);
- }
-
- /**
- * Getter for the dark-mode css source.
- *
- * @return the source for the dark-mode css
- */
- public static String getDarkmodeCss() {
- return DARK_MODE_CSS;
- }
+
+ private static final String DARK_MODE_CSS = Objects.requireNonNull(SceneManager.class.getResource("/css/dark-theme.css")).toExternalForm();
+
+ /**
+ * The boolean on which elements can bind in order to be updated on dark-mode
+ * change.
+ */
+ private static final ObjectProperty darkmode = new SimpleObjectProperty<>(PropertiesLoader.getDarkmode());
+
+ /**
+ * ObjectProperty to allow bindings
+ *
+ * @return The ObjectProperty
+ */
+ public static ObjectProperty darkmodeProperty() {
+ return darkmode;
+ }
+
+ /**
+ * Getter for the current dark-mode flag.
+ *
+ * @return the current dark-mode setting
+ */
+ public static boolean getDarkmode() {
+ return darkmode.get();
+ }
+
+ /**
+ * Setter for the current dark-mode flag.
+ *
+ * @param flag the new value
+ */
+ public static void setDarkmode(boolean flag) {
+ darkmodeProperty().set(flag);
+ }
+
+ /**
+ * Getter for the dark-mode css source.
+ *
+ * @return the source for the dark-mode css
+ */
+ public static String getDarkmodeCss() {
+ return DARK_MODE_CSS;
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/SoundManager.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/SoundManager.java
index fc123ca..b778472 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/SoundManager.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/SoundManager.java
@@ -1,75 +1,76 @@
package com.JayPi4c.RobbiSimulator.utils;
-import java.net.URISyntaxException;
-
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.URISyntaxException;
/**
* Manager to load and play sounds.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
+@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SoundManager {
- /**
- * The boolean on which elements can bind in order to be updated if sound is
- * deactivated /activated
- */
- private static final ObjectProperty sound = new SimpleObjectProperty<>(PropertiesLoader.getSounds());
+ /**
+ * The boolean on which elements can bind in order to be updated if sound is
+ * deactivated /activated
+ */
+ private static final ObjectProperty sound = new SimpleObjectProperty<>(PropertiesLoader.getSounds());
- private static Media warningSound = null;
+ private static Media warningSound = null;
- /**
- * Plays a warning sounds. If the sound is not loaded yet, the sound will be
- * loaded and stored for further plays.
- */
- public static void playWarnSound() {
- if (Boolean.FALSE.equals(sound.get()))
- return;
- if (warningSound == null) {
- try {
- warningSound = new Media(
- SoundManager.class.getResource("/sounds/warning-sound.mp3").toURI().toString());
- } catch (URISyntaxException e) {
- e.printStackTrace();
- }
- }
- MediaPlayer mediaPlayer = new MediaPlayer(warningSound);
- mediaPlayer.play();
- }
+ /**
+ * Plays a warning sounds. If the sound is not loaded yet, the sound will be
+ * loaded and stored for further plays.
+ */
+ public static void playWarnSound() {
+ if (Boolean.FALSE.equals(sound.get()))
+ return;
+ if (warningSound == null) {
+ try {
+ warningSound = new Media(
+ SoundManager.class.getResource("/sounds/warning-sound.mp3").toURI().toString());
+ } catch (URISyntaxException e) {
+ logger.error("Could not load sound file.", e);
+ }
+ }
+ MediaPlayer mediaPlayer = new MediaPlayer(warningSound);
+ mediaPlayer.play();
+ }
- /**
- * ObjectProperty to allow bindings
- *
- * @return The ObjectProperty
- */
- public static ObjectProperty soundProperty() {
- return sound;
- }
+ /**
+ * ObjectProperty to allow bindings
+ *
+ * @return The ObjectProperty
+ */
+ public static ObjectProperty soundProperty() {
+ return sound;
+ }
- /**
- * Getter for the current sound flag.
- *
- * @return the current sound setting
- */
- public static boolean getSound() {
- return sound.get();
- }
+ /**
+ * Getter for the current sound flag.
+ *
+ * @return the current sound setting
+ */
+ public static boolean getSound() {
+ return sound.get();
+ }
- /**
- * Setter for the current sound flag.
- *
- * @param flag the new value
- */
- public static void setSound(boolean flag) {
- soundProperty().set(flag);
- }
+ /**
+ * Setter for the current sound flag.
+ *
+ * @param flag the new value
+ */
+ public static void setSound(boolean flag) {
+ soundProperty().set(flag);
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/utils/annotations/Invisible.java b/src/main/java/com/JayPi4c/RobbiSimulator/utils/annotations/Invisible.java
index 6015cfd..a2e064b 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/utils/annotations/Invisible.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/utils/annotations/Invisible.java
@@ -9,9 +9,8 @@
* Annotation to hide methods from the ContextMenu. Methods annotated with this
* annotation will not show up in the ContextMenu. Nonetheless, they still can
* be used in the code without any restrictions.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/view/MainStage.java b/src/main/java/com/JayPi4c/RobbiSimulator/view/MainStage.java
index 5740cdb..39c7d96 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/view/MainStage.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/view/MainStage.java
@@ -1,10 +1,6 @@
package com.JayPi4c.RobbiSimulator.view;
-import com.JayPi4c.RobbiSimulator.controller.ButtonState;
-import com.JayPi4c.RobbiSimulator.controller.LanguageController;
-import com.JayPi4c.RobbiSimulator.controller.MainStageController;
-import com.JayPi4c.RobbiSimulator.controller.SnackbarController;
-import com.JayPi4c.RobbiSimulator.controller.TerritorySaveController;
+import com.JayPi4c.RobbiSimulator.controller.*;
import com.JayPi4c.RobbiSimulator.controller.examples.ExamplesController;
import com.JayPi4c.RobbiSimulator.controller.program.Program;
import com.JayPi4c.RobbiSimulator.controller.simulation.SimulationController;
@@ -12,7 +8,6 @@
import com.JayPi4c.RobbiSimulator.controller.tutor.TutorController;
import com.JayPi4c.RobbiSimulator.model.Territory;
import com.JayPi4c.RobbiSimulator.utils.PropertiesLoader;
-
import eu.mihosoft.monacofx.MonacoFX;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
@@ -28,249 +23,237 @@
/**
* This class is the mainStage of the application and holds all GUI elements
* that are visible to the user.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
@Getter
public class MainStage extends Stage {
- private Territory territory;
-
- private ButtonState buttonState;
-
- // controllers
- private MainStageController mainStageController;
- private SimulationController simulationController;
- private TerritorySaveController territorySaveController;
- private ExamplesController examplesController;
- private StudentController studenController;
- private TutorController tutorController;
- private LanguageController languageController;
- private SnackbarController snackbarController;
-
- /**
- * Constant for the minimum width of the stage.
- */
- public static final int MIN_WIDTH = 500;
- /**
- * Constant for the minimum height of the stage.
- */
- public static final int MIN_HEIGHT = 200;
- /**
- * Constant for the default width of the stage.
- * Currently not in use.
- */
- public static final int WIDTH = 1200;
- /**
- * Constant for the default height of the stage.
- */
- public static final int HEIGHT = 450;
-
- private Program program;
-
- private MenuBar menubar;
-
- private Toolbar toolbar;
-
- // Content Pane
- private MonacoFX textArea;
- private ScrollPane territoryScrollPane;
- private TerritoryPanel territoryPanel;
- private SplitPane splitPane;
-
- private Scene mainStageScene;
-
- /**
- * Constant Image for open icon.
- */
- public static final Image openImage;
- /**
- * Constant Image for new icon.
- */
- public static final Image newImage;
- /**
- * Constant Image for save icon.
- */
- public static final Image saveImage;
- /**
- * Constant Image for compile icon.
- */
- public static final Image compileImage;
- /**
- * Constant Image for print icon.
- */
- public static final Image printImage;
- /**
- * Constant Image for terrain icon. (Used for changeSize button)
- */
- public static final Image terrainImage;
-
- /**
- * Constant Image for robbi icon.
- */
- public static final Image menuRobbiImage;
- /**
- * Constant Image for hollow icon.
- */
- public static final Image menuHollowImage;
- /**
- * Constant Image for pileOfScrap icon.
- */
- public static final Image menuPileOfScrapImage;
- /**
- * Constant Image for stockpile icon.
- */
- public static final Image menuStockpileImage;
- /**
- * Constant Image for accu icon.
- */
- public static final Image menuAccuImage;
- /**
- * Constant Image for screw icon.
- */
- public static final Image menuScrewImage;
- /**
- * Constant Image for nut icon.
- */
- public static final Image menuNutImage;
- /**
- * Constant Image for delete icon.
- */
- public static final Image menuDeleteImage;
-
- /**
- * Constant Image for reset icon.
- */
- public static final Image resetImage;
- /**
- * Constant Image for simulation start/resume icon.
- */
- public static final Image menuStartImage;
- /**
- * Constant Image for simulation pause icon.
- */
- public static final Image menuPauseImage;
- /**
- * Constant Image for simulation stop icon.
- */
- public static final Image menuStopImage;
-
- /**
- * Constant Image for RobbiMove icon.
- */
- public static final Image robbiMove;
- /**
- * Constant Image for RobbiTurnLeft icon.
- */
- public static final Image robbiTurnLeft;
- /**
- * Constant Image for RobbiPut icon.
- */
- public static final Image robbiPut;
- /**
- * Constant Image for RobbiTake icon.
- */
- public static final Image robbiTake;
-
- /**
- * loading images
- */
- static {
- logger.debug("Loading stage images");
- newImage = new Image(String.valueOf(MainStage.class.getResource("/img/New24.gif")));
- saveImage = new Image(String.valueOf(MainStage.class.getResource("/img/Save24.gif")));
- openImage = new Image(String.valueOf(MainStage.class.getResource("/img/Open24.gif")));
- compileImage = new Image(String.valueOf(MainStage.class.getResource("/img/Compile24.gif")));
- printImage = new Image(String.valueOf(MainStage.class.getResource("/img/Print24.gif")));
- terrainImage = new Image(String.valueOf(MainStage.class.getResource("/img/Terrain24.gif")));
- menuRobbiImage = new Image(String.valueOf(MainStage.class.getResource("/img/Robbi24.png")));
- menuHollowImage = new Image(String.valueOf(MainStage.class.getResource("/img/Hollow24.png")));
- menuPileOfScrapImage = new Image(String.valueOf(MainStage.class.getResource("/img/PileOfScrap24.png")));
- menuStockpileImage = new Image(String.valueOf(MainStage.class.getResource("/img/Stockpile24.png")));
- menuAccuImage = new Image(String.valueOf(MainStage.class.getResource("/img/Accu24.png")));
- menuScrewImage = new Image(String.valueOf(MainStage.class.getResource("/img/Screw24.png")));
- menuNutImage = new Image(String.valueOf(MainStage.class.getResource("/img/Nut24.png")));
- menuDeleteImage = new Image(String.valueOf(MainStage.class.getResource("/img/Delete24.gif")));
-
- resetImage = new Image(String.valueOf(MainStage.class.getResource("/img/reset24.png")));
- menuStartImage = new Image(String.valueOf(MainStage.class.getResource("/img/Play24.gif")));
- menuPauseImage = new Image(String.valueOf(MainStage.class.getResource("/img/Pause24.gif")));
- menuStopImage = new Image(String.valueOf(MainStage.class.getResource("/img/Stop24.gif")));
-
- robbiMove = new Image(String.valueOf(MainStage.class.getResource("/img/RobbiMove24.png")));
- robbiTurnLeft = new Image(String.valueOf(MainStage.class.getResource("/img/RobbiLeft24.png")));
- robbiPut = new Image(String.valueOf(MainStage.class.getResource("/img/RobbiPut24.png")));
- robbiTake = new Image(String.valueOf(MainStage.class.getResource("/img/RobbiTake24.png")));
- }
-
- /**
- * Constructor for the MainStage. It creates a mainStage for the given Program
- * and loads and creates all needed Gui elements and controller.
- * This is the place, where the territory and the buttonState are created
- *
- * @param program the program this mainStage is for
- */
- public MainStage(Program program) {
- this.program = program;
-
- territory = new Territory();
- buttonState = new ButtonState();
-
- menubar = new MenuBar();
- toolbar = new Toolbar(menubar);
- createContentPane();
-
- VBox.setVgrow(splitPane, Priority.ALWAYS);
- var vBox = new VBox(menubar, toolbar, splitPane);
-
- mainStageScene = new Scene(vBox);
- setScene(mainStageScene);
-
- setMinWidth(MIN_WIDTH);
- setMinHeight(MIN_HEIGHT);
- setHeight(HEIGHT);
- getIcons().add(menuRobbiImage);
-
- snackbarController = new SnackbarController(vBox);
- mainStageController = new MainStageController(this, buttonState);
- simulationController = new SimulationController(this, territory);
- territorySaveController = new TerritorySaveController(this);
- examplesController = new ExamplesController(this);
- languageController = new LanguageController(this);
-
- if (PropertiesLoader.isTutor())
- tutorController = new TutorController(this);
- else
- studenController = new StudentController(this);
-
- show();
- textArea.requestFocus();
- logger.info("Finished loading '{}'", program.getName());
- }
-
- /**
- * Creates the contentPane in which the text-editor and the territoryPanel take
- * place.
- */
- private void createContentPane() {
- logger.debug("Create content panel");
-
- textArea = new MonacoFX();
- textArea.getEditor().getDocument().setText(program.getEditorContent());
- textArea.getEditor().setCurrentLanguage("java");
- textArea.setMinWidth(250);
-
- territoryPanel = new TerritoryPanel(this.territory, this.buttonState, this);
-
- territoryScrollPane = new ScrollPane(territoryPanel);
- territoryScrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
- territoryScrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
- territoryScrollPane.viewportBoundsProperty()
- .addListener((observable, oldValue, newValue) -> territoryPanel.center(newValue));// credits: Dibo
-
- splitPane = new SplitPane(textArea, territoryScrollPane);
- }
+ /**
+ * Constant for the minimum width of the stage.
+ */
+ public static final int MIN_WIDTH = 500;
+ /**
+ * Constant for the minimum height of the stage.
+ */
+ public static final int MIN_HEIGHT = 200;
+ /**
+ * Constant for the default width of the stage.
+ * Currently not in use.
+ */
+ public static final int WIDTH = 1200;
+ /**
+ * Constant for the default height of the stage.
+ */
+ public static final int HEIGHT = 450;
+ /**
+ * Constant Image for open icon.
+ */
+ public static final Image openImage;
+ /**
+ * Constant Image for new icon.
+ */
+ public static final Image newImage;
+ /**
+ * Constant Image for save icon.
+ */
+ public static final Image saveImage;
+ /**
+ * Constant Image for compile icon.
+ */
+ public static final Image compileImage;
+ /**
+ * Constant Image for print icon.
+ */
+ public static final Image printImage;
+ /**
+ * Constant Image for terrain icon. (Used for changeSize button)
+ */
+ public static final Image terrainImage;
+ /**
+ * Constant Image for robbi icon.
+ */
+ public static final Image menuRobbiImage;
+ /**
+ * Constant Image for hollow icon.
+ */
+ public static final Image menuHollowImage;
+ /**
+ * Constant Image for pileOfScrap icon.
+ */
+ public static final Image menuPileOfScrapImage;
+ /**
+ * Constant Image for stockpile icon.
+ */
+ public static final Image menuStockpileImage;
+ /**
+ * Constant Image for accu icon.
+ */
+ public static final Image menuAccuImage;
+ /**
+ * Constant Image for screw icon.
+ */
+ public static final Image menuScrewImage;
+ /**
+ * Constant Image for the nut icon.
+ */
+ public static final Image menuNutImage;
+ /**
+ * Constant Image for delete icon.
+ */
+ public static final Image menuDeleteImage;
+ /**
+ * Constant Image for reset icon.
+ */
+ public static final Image resetImage;
+ /**
+ * Constant Image for simulation start/resume icon.
+ */
+ public static final Image menuStartImage;
+ /**
+ * Constant Image for simulation pause icon.
+ */
+ public static final Image menuPauseImage;
+ /**
+ * Constant Image for simulation stop icon.
+ */
+ public static final Image menuStopImage;
+ /**
+ * Constant Image for RobbiMove icon.
+ */
+ public static final Image robbiMove;
+ /**
+ * Constant Image for RobbiTurnLeft icon.
+ */
+ public static final Image robbiTurnLeft;
+ /**
+ * Constant Image for RobbiPut icon.
+ */
+ public static final Image robbiPut;
+ /**
+ * Constant Image for RobbiTake icon.
+ */
+ public static final Image robbiTake;
+
+ static {
+ logger.debug("Loading stage images");
+ newImage = new Image(String.valueOf(MainStage.class.getResource("/img/New24.gif")));
+ saveImage = new Image(String.valueOf(MainStage.class.getResource("/img/Save24.gif")));
+ openImage = new Image(String.valueOf(MainStage.class.getResource("/img/Open24.gif")));
+ compileImage = new Image(String.valueOf(MainStage.class.getResource("/img/Compile24.gif")));
+ printImage = new Image(String.valueOf(MainStage.class.getResource("/img/Print24.gif")));
+ terrainImage = new Image(String.valueOf(MainStage.class.getResource("/img/Terrain24.gif")));
+ menuRobbiImage = new Image(String.valueOf(MainStage.class.getResource("/img/Robbi24.png")));
+ menuHollowImage = new Image(String.valueOf(MainStage.class.getResource("/img/Hollow24.png")));
+ menuPileOfScrapImage = new Image(String.valueOf(MainStage.class.getResource("/img/PileOfScrap24.png")));
+ menuStockpileImage = new Image(String.valueOf(MainStage.class.getResource("/img/Stockpile24.png")));
+ menuAccuImage = new Image(String.valueOf(MainStage.class.getResource("/img/Accu24.png")));
+ menuScrewImage = new Image(String.valueOf(MainStage.class.getResource("/img/Screw24.png")));
+ menuNutImage = new Image(String.valueOf(MainStage.class.getResource("/img/Nut24.png")));
+ menuDeleteImage = new Image(String.valueOf(MainStage.class.getResource("/img/Delete24.gif")));
+
+ resetImage = new Image(String.valueOf(MainStage.class.getResource("/img/reset24.png")));
+ menuStartImage = new Image(String.valueOf(MainStage.class.getResource("/img/Play24.gif")));
+ menuPauseImage = new Image(String.valueOf(MainStage.class.getResource("/img/Pause24.gif")));
+ menuStopImage = new Image(String.valueOf(MainStage.class.getResource("/img/Stop24.gif")));
+
+ robbiMove = new Image(String.valueOf(MainStage.class.getResource("/img/RobbiMove24.png")));
+ robbiTurnLeft = new Image(String.valueOf(MainStage.class.getResource("/img/RobbiLeft24.png")));
+ robbiPut = new Image(String.valueOf(MainStage.class.getResource("/img/RobbiPut24.png")));
+ robbiTake = new Image(String.valueOf(MainStage.class.getResource("/img/RobbiTake24.png")));
+ }
+
+ private final Territory territory;
+ private final ButtonState buttonState;
+ // controllers
+ private final MainStageController mainStageController;
+ private final SimulationController simulationController;
+ private final TerritorySaveController territorySaveController;
+ private final ExamplesController examplesController;
+ private StudentController studentController;
+ private TutorController tutorController;
+ private final LanguageController languageController;
+ private final NotificationController notificationController;
+ private final Program program;
+ private final MenuBar menubar;
+ private final Toolbar toolbar;
+ // Content Pane
+ private MonacoFX textArea;
+ private ScrollPane territoryScrollPane;
+ private TerritoryPanel territoryPanel;
+ private SplitPane splitPane;
+ private final Scene mainStageScene;
+
+ /**
+ * Constructor for the MainStage. It creates a mainStage for the given Program
+ * and loads and creates all needed Gui elements and controller.
+ * This is the place, where the territory and the buttonState are created
+ *
+ * @param program the program this mainStage is for
+ */
+ public MainStage(Program program) {
+ this.program = program;
+
+ territory = new Territory();
+ buttonState = new ButtonState();
+
+ menubar = new MenuBar();
+ toolbar = new Toolbar(menubar);
+ createContentPane();
+
+ VBox.setVgrow(splitPane, Priority.ALWAYS);
+ var vBox = new VBox(menubar, toolbar, splitPane);
+
+ notificationController = new NotificationController(vBox);
+
+ mainStageScene = new Scene(notificationController.getScene());
+ setScene(mainStageScene);
+
+ setMinWidth(MIN_WIDTH);
+ setMinHeight(MIN_HEIGHT);
+ setHeight(HEIGHT);
+ getIcons().add(menuRobbiImage);
+
+
+ mainStageController = new MainStageController(this, buttonState);
+ simulationController = new SimulationController(this, territory);
+ territorySaveController = new TerritorySaveController(this);
+ examplesController = new ExamplesController(this);
+ languageController = new LanguageController(this);
+
+ if (PropertiesLoader.isTutor())
+ tutorController = new TutorController(this);
+ else
+ studentController = new StudentController(this);
+
+ show();
+ textArea.requestFocus();
+ logger.info("Finished loading '{}'", program.getName());
+ notificationController.showMessage(2500, "Snackbar.message.startup");
+ }
+
+ /**
+ * Creates the contentPane in which the text-editor and the territoryPanel take
+ * place.
+ */
+ private void createContentPane() {
+ logger.debug("Create content panel");
+
+ textArea = new MonacoFX();
+ textArea.getEditor().getDocument().setText(program.getEditorContent());
+ textArea.getEditor().setCurrentLanguage("java");
+ textArea.setMinWidth(250);
+
+ territoryPanel = new TerritoryPanel(this.territory, this.buttonState, this);
+
+ territoryScrollPane = new ScrollPane(territoryPanel);
+ territoryScrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
+ territoryScrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
+ territoryScrollPane.viewportBoundsProperty()
+ .addListener((observable, oldValue, newValue) -> territoryPanel.center(newValue));// credits: Dibo
+
+ splitPane = new SplitPane(textArea, territoryScrollPane);
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/view/MenuBar.java b/src/main/java/com/JayPi4c/RobbiSimulator/view/MenuBar.java
index 943ebe0..7dc426b 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/view/MenuBar.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/view/MenuBar.java
@@ -1,13 +1,7 @@
package com.JayPi4c.RobbiSimulator.view;
import com.JayPi4c.RobbiSimulator.utils.PropertiesLoader;
-
-import javafx.scene.control.CheckMenuItem;
-import javafx.scene.control.Menu;
-import javafx.scene.control.MenuItem;
-import javafx.scene.control.RadioMenuItem;
-import javafx.scene.control.SeparatorMenuItem;
-import javafx.scene.control.ToggleGroup;
+import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
@@ -16,310 +10,308 @@
import lombok.extern.slf4j.Slf4j;
/**
- *
* The menuBar holds all possible actions for the application in one menuBar.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
@Getter
public class MenuBar extends javafx.scene.control.MenuBar {
- // Menu Bar
- // editor Menu
- private MenuItem newEditorMenuItem;
- private MenuItem saveEditorMenuItem;
- private MenuItem openEditorMenuItem;
- private MenuItem formatSourceCodeMenuItem;
- private MenuItem compileEditorMenuItem;
- private MenuItem printEditorMenuItem;
-
- private MenuItem quitEditorMenuItem;
- private Menu editorMenu;
-
- // territory Menu
- private MenuItem saveXMLTerritoryMenuItem;
- private MenuItem saveJAXBTerritoryMenuItem;
- private MenuItem saveSerialTerritoryMenuItem;
-
- private Menu saveTerritoryMenu;
- private MenuItem loadXMLTerritoryMenuItem;
- private MenuItem loadJAXBTerritoryMenuItem;
- private MenuItem loadSerialTerritoryMenuItem;
-
- private Menu loadTerritoryMenu;
- private Menu saveAsPicMenu;
- private MenuItem saveAsPNGMenuItem;
- private MenuItem saveAsGifMenuItem;
- private MenuItem printTerritoryMenuItem;
- private MenuItem changeSizeTerritoryMenuItem;
- private RadioMenuItem placeRobbiTerritoryRadioMenuItem;
- private RadioMenuItem placeHollowTerritoryRadioMenuItem;
- private RadioMenuItem placePileOfScrapTerritoryRadioMenuItem;
- private RadioMenuItem placeStockpileTerritoryRadioMenuItem;
- private RadioMenuItem placeAccuTerritoryRadioMenuItem;
- private RadioMenuItem placeScrewTerritoryRadioMenuItem;
- private RadioMenuItem placeNutTerritoryRadioMenuItem;
- private RadioMenuItem deleteFieldRadioMenuItem;
- private Menu territoryMenu;
- private ToggleGroup placeGroupTerritoryMenu;
-
- // robbi Menu
- private MenuItem itemPresentMenuItem;
- private MenuItem isStockpileMenuItem;
- private MenuItem hollowAheadMenuItem;
- private MenuItem pileOfScrapAheadMenuItem;
- private MenuItem isBagFullMenuItem;
- private MenuItem pushPileOfScrapMenuItem;
- private MenuItem moveMenuItem;
- private MenuItem turnLeftMenuItem;
- private MenuItem putMenuItem;
- private MenuItem takeMenuItem;
- private Menu robbiMenu;
-
- // simulation Menu
- private MenuItem resetMenuItem;
- private MenuItem startMenuItem;
- private MenuItem pauseMenuItem;
- private MenuItem stopMenuItem;
- private Menu simulationMenu;
-
- // examples Menu
- private MenuItem loadExampleMenuItem;
- private MenuItem saveExampleMenuItem;
- private Menu examplesMenu;
-
- // window Menu
- private Menu languageMenu;
- private MenuItem englishLanguageMenuItem;
- private MenuItem germanLanguageMenuItem;
- private CheckMenuItem changeCursorMenuItem;
- private CheckMenuItem darkModeMenuItem;
- private CheckMenuItem enableSoundsMenuItem;
- private MenuItem infoMenuItem;
- private MenuItem libraryMenuItem;
- private Menu windowMenu;
-
- // tutor Menu
- private Menu tutorMenu;
- private MenuItem sendRequestMenuItem;
- private MenuItem receiveAnswerMenuItem;
- private MenuItem loadRequestMenuItem;
- private MenuItem saveAnswerMenuItem;
-
- /**
- * Creates a new MenuBar
- */
- public MenuBar() {
- createMenuBar();
- getMenus().addAll(editorMenu, territoryMenu, robbiMenu, simulationMenu, examplesMenu, tutorMenu, windowMenu);
- }
-
- /**
- * Creates the editor-related menu-bar elements.
- */
- private void createEditor() {
- logger.debug("Create editor entry for menubar");
- newEditorMenuItem = new MenuItem();
- newEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.N, KeyCombination.CONTROL_DOWN));
- newEditorMenuItem.setMnemonicParsing(true);
- newEditorMenuItem.setGraphic(new ImageView(MainStage.newImage));
- saveEditorMenuItem = new MenuItem();
- saveEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN));
- saveEditorMenuItem.setGraphic(new ImageView(MainStage.saveImage));
- openEditorMenuItem = new MenuItem();
- openEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.O, KeyCombination.CONTROL_DOWN));
- openEditorMenuItem.setGraphic(new ImageView(MainStage.openImage));
-
- formatSourceCodeMenuItem = new MenuItem();
- formatSourceCodeMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN)); // T
- // for
- // tidy
-
- compileEditorMenuItem = new MenuItem();
- compileEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.K, KeyCombination.CONTROL_DOWN));
- compileEditorMenuItem.setGraphic(new ImageView(MainStage.compileImage));
-
- printEditorMenuItem = new MenuItem();
- printEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.P, KeyCombination.CONTROL_DOWN));
- printEditorMenuItem.setGraphic(new ImageView(MainStage.printImage));
- quitEditorMenuItem = new MenuItem();
- quitEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.Q, KeyCombination.CONTROL_DOWN));
- editorMenu = new Menu("", null, newEditorMenuItem, openEditorMenuItem, saveEditorMenuItem,
- new SeparatorMenuItem(), formatSourceCodeMenuItem, compileEditorMenuItem, printEditorMenuItem,
- new SeparatorMenuItem(), quitEditorMenuItem);
- editorMenu.setMnemonicParsing(true);
- }
-
- /**
- * Creates the territory-related menu-bar elements.
- */
- private void createTerritory() {
- logger.debug("Create territory entry for menubar");
- saveXMLTerritoryMenuItem = new MenuItem();
- saveJAXBTerritoryMenuItem = new MenuItem();
- saveSerialTerritoryMenuItem = new MenuItem();
-
- saveTerritoryMenu = new Menu("", null, saveXMLTerritoryMenuItem, saveJAXBTerritoryMenuItem,
- saveSerialTerritoryMenuItem);
- loadXMLTerritoryMenuItem = new MenuItem();
- loadJAXBTerritoryMenuItem = new MenuItem();
- loadSerialTerritoryMenuItem = new MenuItem();
- loadTerritoryMenu = new Menu("", null, loadXMLTerritoryMenuItem, loadJAXBTerritoryMenuItem,
- loadSerialTerritoryMenuItem);
-
- saveAsPNGMenuItem = new MenuItem();
- saveAsGifMenuItem = new MenuItem();
- saveAsPicMenu = new Menu("", null, saveAsPNGMenuItem, saveAsGifMenuItem);
-
- printTerritoryMenuItem = new MenuItem();
- changeSizeTerritoryMenuItem = new MenuItem();
-
- placeGroupTerritoryMenu = new ToggleGroup();
-
- placeRobbiTerritoryRadioMenuItem = new RadioMenuItem();
- placeRobbiTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
-
- placeHollowTerritoryRadioMenuItem = new RadioMenuItem();
- placeHollowTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
-
- placePileOfScrapTerritoryRadioMenuItem = new RadioMenuItem();
- placePileOfScrapTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
-
- placeStockpileTerritoryRadioMenuItem = new RadioMenuItem();
- placeStockpileTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
-
- placeAccuTerritoryRadioMenuItem = new RadioMenuItem();
- placeAccuTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
-
- placeScrewTerritoryRadioMenuItem = new RadioMenuItem();
- placeScrewTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
-
- placeNutTerritoryRadioMenuItem = new RadioMenuItem();
- placeNutTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
-
- deleteFieldRadioMenuItem = new RadioMenuItem();
- deleteFieldRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
-
- territoryMenu = new Menu("", null, saveTerritoryMenu, loadTerritoryMenu, saveAsPicMenu, printTerritoryMenuItem,
- changeSizeTerritoryMenuItem, new SeparatorMenuItem(), placeRobbiTerritoryRadioMenuItem,
- placeHollowTerritoryRadioMenuItem, placePileOfScrapTerritoryRadioMenuItem,
- placeStockpileTerritoryRadioMenuItem, placeAccuTerritoryRadioMenuItem, placeScrewTerritoryRadioMenuItem,
- placeNutTerritoryRadioMenuItem, deleteFieldRadioMenuItem);
- }
-
- /**
- * Creates the robbi-related menu-bar elements.
- */
- private void createRobbi() {
- logger.debug("Create Robbi entry for menubar");
- territoryMenu.setMnemonicParsing(true);
- itemPresentMenuItem = new MenuItem();
- isStockpileMenuItem = new MenuItem();
- hollowAheadMenuItem = new MenuItem();
- pileOfScrapAheadMenuItem = new MenuItem();
- isBagFullMenuItem = new MenuItem();
- pushPileOfScrapMenuItem = new MenuItem();
- moveMenuItem = new MenuItem();
- moveMenuItem.setAccelerator(
- new KeyCodeCombination(KeyCode.V, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN));
- turnLeftMenuItem = new MenuItem();
- turnLeftMenuItem.setAccelerator(
- new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN));
-
- putMenuItem = new MenuItem();
- putMenuItem.setAccelerator(
- new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN));
- takeMenuItem = new MenuItem();
- takeMenuItem.setAccelerator(
- new KeyCodeCombination(KeyCode.N, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN));
- robbiMenu = new Menu("", null, moveMenuItem, turnLeftMenuItem, putMenuItem, takeMenuItem,
- pushPileOfScrapMenuItem, itemPresentMenuItem, isStockpileMenuItem, hollowAheadMenuItem,
- pileOfScrapAheadMenuItem, isBagFullMenuItem);
- robbiMenu.setMnemonicParsing(true);
- }
-
- /**
- * Creates the simulation-related menu-bar elements.
- */
- private void createSimulation() {
- logger.debug("Create simulation entry for menubar");
-
- resetMenuItem = new MenuItem();
- resetMenuItem.setGraphic(new ImageView(MainStage.resetImage));
- startMenuItem = new MenuItem();
- startMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.F11, KeyCombination.CONTROL_DOWN));
- startMenuItem.setGraphic(new ImageView(MainStage.menuStartImage));
- pauseMenuItem = new MenuItem();
- pauseMenuItem.setGraphic(new ImageView(MainStage.menuPauseImage));
- stopMenuItem = new MenuItem();
- stopMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.F12, KeyCombination.CONTROL_DOWN));
- stopMenuItem.setGraphic(new ImageView(MainStage.menuStopImage));
- simulationMenu = new Menu("", null, resetMenuItem, startMenuItem, pauseMenuItem, stopMenuItem);
- simulationMenu.setMnemonicParsing(true);
- }
-
- /**
- * Creates the examples-related menu-bar elements
- */
- private void createExamplesMenu() {
- saveExampleMenuItem = new MenuItem();
- loadExampleMenuItem = new MenuItem();
- examplesMenu = new Menu("", null, saveExampleMenuItem, loadExampleMenuItem);
- }
-
- /**
- * Creates the tutor-related menu-bar elements
- */
- private void createTutorMenu() {
- if (PropertiesLoader.isTutor()) {
- loadRequestMenuItem = new MenuItem();
- saveAnswerMenuItem = new MenuItem();
-
- tutorMenu = new Menu("", null, loadRequestMenuItem, saveAnswerMenuItem);
- } else {
- sendRequestMenuItem = new MenuItem();
- receiveAnswerMenuItem = new MenuItem();
-
- tutorMenu = new Menu("", null, sendRequestMenuItem, receiveAnswerMenuItem);
- }
- }
-
- /**
- * Creates the window-related menu-bar elements.
- */
- private void createWindowMenu() {
- englishLanguageMenuItem = new MenuItem();
- germanLanguageMenuItem = new MenuItem();
- languageMenu = new Menu("", null, englishLanguageMenuItem, germanLanguageMenuItem);
-
- changeCursorMenuItem = new CheckMenuItem();
- // https://stackoverflow.com/a/49159612/13670629
- darkModeMenuItem = new CheckMenuItem();
- enableSoundsMenuItem = new CheckMenuItem();
-
- infoMenuItem = new MenuItem();
- libraryMenuItem = new MenuItem();
-
- windowMenu = new Menu("", null, languageMenu, changeCursorMenuItem, darkModeMenuItem, enableSoundsMenuItem,
- new SeparatorMenuItem(), infoMenuItem, libraryMenuItem);
- }
-
- /**
- * Creates the entire menuBar.
- */
- private void createMenuBar() {
- logger.debug("Create menubar");
-
- createEditor();
- createTerritory();
- createRobbi();
- createSimulation();
- createExamplesMenu();
- createTutorMenu();
- createWindowMenu();
-
- }
+ // Menu Bar
+ // editor Menu
+ private MenuItem newEditorMenuItem;
+ private MenuItem saveEditorMenuItem;
+ private MenuItem openEditorMenuItem;
+ private MenuItem formatSourceCodeMenuItem;
+ private MenuItem compileEditorMenuItem;
+ private MenuItem printEditorMenuItem;
+
+ private MenuItem quitEditorMenuItem;
+ private Menu editorMenu;
+
+ // territory Menu
+ private MenuItem saveXMLTerritoryMenuItem;
+ private MenuItem saveJAXBTerritoryMenuItem;
+ private MenuItem saveSerialTerritoryMenuItem;
+
+ private Menu saveTerritoryMenu;
+ private MenuItem loadXMLTerritoryMenuItem;
+ private MenuItem loadJAXBTerritoryMenuItem;
+ private MenuItem loadSerialTerritoryMenuItem;
+
+ private Menu loadTerritoryMenu;
+ private Menu saveAsPicMenu;
+ private MenuItem saveAsPNGMenuItem;
+ private MenuItem saveAsGifMenuItem;
+ private MenuItem printTerritoryMenuItem;
+ private MenuItem changeSizeTerritoryMenuItem;
+ private RadioMenuItem placeRobbiTerritoryRadioMenuItem;
+ private RadioMenuItem placeHollowTerritoryRadioMenuItem;
+ private RadioMenuItem placePileOfScrapTerritoryRadioMenuItem;
+ private RadioMenuItem placeStockpileTerritoryRadioMenuItem;
+ private RadioMenuItem placeAccuTerritoryRadioMenuItem;
+ private RadioMenuItem placeScrewTerritoryRadioMenuItem;
+ private RadioMenuItem placeNutTerritoryRadioMenuItem;
+ private RadioMenuItem deleteFieldRadioMenuItem;
+ private Menu territoryMenu;
+ private ToggleGroup placeGroupTerritoryMenu;
+
+ // robbi Menu
+ private MenuItem itemPresentMenuItem;
+ private MenuItem isStockpileMenuItem;
+ private MenuItem hollowAheadMenuItem;
+ private MenuItem pileOfScrapAheadMenuItem;
+ private MenuItem isBagFullMenuItem;
+ private MenuItem pushPileOfScrapMenuItem;
+ private MenuItem moveMenuItem;
+ private MenuItem turnLeftMenuItem;
+ private MenuItem putMenuItem;
+ private MenuItem takeMenuItem;
+ private Menu robbiMenu;
+
+ // simulation Menu
+ private MenuItem resetMenuItem;
+ private MenuItem startMenuItem;
+ private MenuItem pauseMenuItem;
+ private MenuItem stopMenuItem;
+ private Menu simulationMenu;
+
+ // examples Menu
+ private MenuItem loadExampleMenuItem;
+ private MenuItem saveExampleMenuItem;
+ private Menu examplesMenu;
+
+ // window Menu
+ private Menu languageMenu;
+ private MenuItem englishLanguageMenuItem;
+ private MenuItem germanLanguageMenuItem;
+ private CheckMenuItem changeCursorMenuItem;
+ private CheckMenuItem darkModeMenuItem;
+ private CheckMenuItem enableSoundsMenuItem;
+ private MenuItem infoMenuItem;
+ private MenuItem libraryMenuItem;
+ private Menu windowMenu;
+
+ // tutor Menu
+ private Menu tutorMenu;
+ private MenuItem sendRequestMenuItem;
+ private MenuItem receiveAnswerMenuItem;
+ private MenuItem loadRequestMenuItem;
+ private MenuItem saveAnswerMenuItem;
+
+ /**
+ * Creates a new MenuBar
+ */
+ public MenuBar() {
+ createMenuBar();
+ getMenus().addAll(editorMenu, territoryMenu, robbiMenu, simulationMenu, examplesMenu, tutorMenu, windowMenu);
+ }
+
+ /**
+ * Creates the editor-related menu-bar elements.
+ */
+ private void createEditor() {
+ logger.debug("Create editor entry for menubar");
+ newEditorMenuItem = new MenuItem();
+ newEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.N, KeyCombination.CONTROL_DOWN));
+ newEditorMenuItem.setMnemonicParsing(true);
+ newEditorMenuItem.setGraphic(new ImageView(MainStage.newImage));
+ saveEditorMenuItem = new MenuItem();
+ saveEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN));
+ saveEditorMenuItem.setGraphic(new ImageView(MainStage.saveImage));
+ openEditorMenuItem = new MenuItem();
+ openEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.O, KeyCombination.CONTROL_DOWN));
+ openEditorMenuItem.setGraphic(new ImageView(MainStage.openImage));
+
+ formatSourceCodeMenuItem = new MenuItem();
+ formatSourceCodeMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN)); // T
+ // for
+ // tidy
+
+ compileEditorMenuItem = new MenuItem();
+ compileEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.K, KeyCombination.CONTROL_DOWN));
+ compileEditorMenuItem.setGraphic(new ImageView(MainStage.compileImage));
+
+ printEditorMenuItem = new MenuItem();
+ printEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.P, KeyCombination.CONTROL_DOWN));
+ printEditorMenuItem.setGraphic(new ImageView(MainStage.printImage));
+ quitEditorMenuItem = new MenuItem();
+ quitEditorMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.Q, KeyCombination.CONTROL_DOWN));
+ editorMenu = new Menu("", null, newEditorMenuItem, openEditorMenuItem, saveEditorMenuItem,
+ new SeparatorMenuItem(), formatSourceCodeMenuItem, compileEditorMenuItem, printEditorMenuItem,
+ new SeparatorMenuItem(), quitEditorMenuItem);
+ editorMenu.setMnemonicParsing(true);
+ }
+
+ /**
+ * Creates the territory-related menu-bar elements.
+ */
+ private void createTerritory() {
+ logger.debug("Create territory entry for menubar");
+ saveXMLTerritoryMenuItem = new MenuItem();
+ saveJAXBTerritoryMenuItem = new MenuItem();
+ saveSerialTerritoryMenuItem = new MenuItem();
+
+ saveTerritoryMenu = new Menu("", null, saveXMLTerritoryMenuItem, saveJAXBTerritoryMenuItem,
+ saveSerialTerritoryMenuItem);
+ loadXMLTerritoryMenuItem = new MenuItem();
+ loadJAXBTerritoryMenuItem = new MenuItem();
+ loadSerialTerritoryMenuItem = new MenuItem();
+ loadTerritoryMenu = new Menu("", null, loadXMLTerritoryMenuItem, loadJAXBTerritoryMenuItem,
+ loadSerialTerritoryMenuItem);
+
+ saveAsPNGMenuItem = new MenuItem();
+ saveAsGifMenuItem = new MenuItem();
+ saveAsPicMenu = new Menu("", null, saveAsPNGMenuItem, saveAsGifMenuItem);
+
+ printTerritoryMenuItem = new MenuItem();
+ changeSizeTerritoryMenuItem = new MenuItem();
+
+ placeGroupTerritoryMenu = new ToggleGroup();
+
+ placeRobbiTerritoryRadioMenuItem = new RadioMenuItem();
+ placeRobbiTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
+
+ placeHollowTerritoryRadioMenuItem = new RadioMenuItem();
+ placeHollowTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
+
+ placePileOfScrapTerritoryRadioMenuItem = new RadioMenuItem();
+ placePileOfScrapTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
+
+ placeStockpileTerritoryRadioMenuItem = new RadioMenuItem();
+ placeStockpileTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
+
+ placeAccuTerritoryRadioMenuItem = new RadioMenuItem();
+ placeAccuTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
+
+ placeScrewTerritoryRadioMenuItem = new RadioMenuItem();
+ placeScrewTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
+
+ placeNutTerritoryRadioMenuItem = new RadioMenuItem();
+ placeNutTerritoryRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
+
+ deleteFieldRadioMenuItem = new RadioMenuItem();
+ deleteFieldRadioMenuItem.setToggleGroup(placeGroupTerritoryMenu);
+
+ territoryMenu = new Menu("", null, saveTerritoryMenu, loadTerritoryMenu, saveAsPicMenu, printTerritoryMenuItem,
+ changeSizeTerritoryMenuItem, new SeparatorMenuItem(), placeRobbiTerritoryRadioMenuItem,
+ placeHollowTerritoryRadioMenuItem, placePileOfScrapTerritoryRadioMenuItem,
+ placeStockpileTerritoryRadioMenuItem, placeAccuTerritoryRadioMenuItem, placeScrewTerritoryRadioMenuItem,
+ placeNutTerritoryRadioMenuItem, deleteFieldRadioMenuItem);
+ }
+
+ /**
+ * Creates the robbi-related menu-bar elements.
+ */
+ private void createRobbi() {
+ logger.debug("Create Robbi entry for menubar");
+ territoryMenu.setMnemonicParsing(true);
+ itemPresentMenuItem = new MenuItem();
+ isStockpileMenuItem = new MenuItem();
+ hollowAheadMenuItem = new MenuItem();
+ pileOfScrapAheadMenuItem = new MenuItem();
+ isBagFullMenuItem = new MenuItem();
+ pushPileOfScrapMenuItem = new MenuItem();
+ moveMenuItem = new MenuItem();
+ moveMenuItem.setAccelerator(
+ new KeyCodeCombination(KeyCode.V, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN));
+ turnLeftMenuItem = new MenuItem();
+ turnLeftMenuItem.setAccelerator(
+ new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN));
+
+ putMenuItem = new MenuItem();
+ putMenuItem.setAccelerator(
+ new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN));
+ takeMenuItem = new MenuItem();
+ takeMenuItem.setAccelerator(
+ new KeyCodeCombination(KeyCode.N, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN));
+ robbiMenu = new Menu("", null, moveMenuItem, turnLeftMenuItem, putMenuItem, takeMenuItem,
+ pushPileOfScrapMenuItem, itemPresentMenuItem, isStockpileMenuItem, hollowAheadMenuItem,
+ pileOfScrapAheadMenuItem, isBagFullMenuItem);
+ robbiMenu.setMnemonicParsing(true);
+ }
+
+ /**
+ * Creates the simulation-related menu-bar elements.
+ */
+ private void createSimulation() {
+ logger.debug("Create simulation entry for menubar");
+
+ resetMenuItem = new MenuItem();
+ resetMenuItem.setGraphic(new ImageView(MainStage.resetImage));
+ startMenuItem = new MenuItem();
+ startMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.F11, KeyCombination.CONTROL_DOWN));
+ startMenuItem.setGraphic(new ImageView(MainStage.menuStartImage));
+ pauseMenuItem = new MenuItem();
+ pauseMenuItem.setGraphic(new ImageView(MainStage.menuPauseImage));
+ stopMenuItem = new MenuItem();
+ stopMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.F12, KeyCombination.CONTROL_DOWN));
+ stopMenuItem.setGraphic(new ImageView(MainStage.menuStopImage));
+ simulationMenu = new Menu("", null, resetMenuItem, startMenuItem, pauseMenuItem, stopMenuItem);
+ simulationMenu.setMnemonicParsing(true);
+ }
+
+ /**
+ * Creates the examples-related menu-bar elements
+ */
+ private void createExamplesMenu() {
+ saveExampleMenuItem = new MenuItem();
+ loadExampleMenuItem = new MenuItem();
+ examplesMenu = new Menu("", null, saveExampleMenuItem, loadExampleMenuItem);
+ }
+
+ /**
+ * Creates the tutor-related menu-bar elements
+ */
+ private void createTutorMenu() {
+ if (PropertiesLoader.isTutor()) {
+ loadRequestMenuItem = new MenuItem();
+ saveAnswerMenuItem = new MenuItem();
+
+ tutorMenu = new Menu("", null, loadRequestMenuItem, saveAnswerMenuItem);
+ } else {
+ sendRequestMenuItem = new MenuItem();
+ receiveAnswerMenuItem = new MenuItem();
+
+ tutorMenu = new Menu("", null, sendRequestMenuItem, receiveAnswerMenuItem);
+ }
+ }
+
+ /**
+ * Creates the window-related menu-bar elements.
+ */
+ private void createWindowMenu() {
+ englishLanguageMenuItem = new MenuItem();
+ germanLanguageMenuItem = new MenuItem();
+ languageMenu = new Menu("", null, englishLanguageMenuItem, germanLanguageMenuItem);
+
+ changeCursorMenuItem = new CheckMenuItem();
+ // https://stackoverflow.com/a/49159612/13670629
+ darkModeMenuItem = new CheckMenuItem();
+ enableSoundsMenuItem = new CheckMenuItem();
+
+ infoMenuItem = new MenuItem();
+ libraryMenuItem = new MenuItem();
+
+ windowMenu = new Menu("", null, languageMenu, changeCursorMenuItem, darkModeMenuItem, enableSoundsMenuItem,
+ new SeparatorMenuItem(), infoMenuItem, libraryMenuItem);
+ }
+
+ /**
+ * Creates the entire menuBar.
+ */
+ private void createMenuBar() {
+ logger.debug("Create menubar");
+
+ createEditor();
+ createTerritory();
+ createRobbi();
+ createSimulation();
+ createExamplesMenu();
+ createTutorMenu();
+ createWindowMenu();
+
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/view/RobbiContextMenu.java b/src/main/java/com/JayPi4c/RobbiSimulator/view/RobbiContextMenu.java
index eaaf00b..38b9222 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/view/RobbiContextMenu.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/view/RobbiContextMenu.java
@@ -1,201 +1,193 @@
package com.JayPi4c.RobbiSimulator.view;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Parameter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
import com.JayPi4c.RobbiSimulator.controller.MethodHandler;
import com.JayPi4c.RobbiSimulator.model.Robbi;
import com.JayPi4c.RobbiSimulator.model.Territory;
import com.JayPi4c.RobbiSimulator.utils.I18nUtils;
import com.JayPi4c.RobbiSimulator.utils.annotations.Default;
import com.JayPi4c.RobbiSimulator.utils.annotations.Invisible;
+import javafx.scene.control.*;
-import javafx.scene.control.ContextMenu;
-import javafx.scene.control.CustomMenuItem;
-import javafx.scene.control.Label;
-import javafx.scene.control.MenuItem;
-import javafx.scene.control.SeparatorMenuItem;
-import javafx.scene.control.Tooltip;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
+import java.util.ArrayList;
+import java.util.List;
/**
* Class to for the ContextMenu which opens, when clicked on robbi in the
* simulator.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
public class RobbiContextMenu extends ContextMenu {
- private static final String EDITOR_CONTEXTMENU_TOOLTIP = "Editor.contextMenu.tooltip";
-
- /**
- * Constructor to create a new RobbiContextMenu. It fills itself with all
- * methods that are provided by robbi and allows to run a particular method on
- * its own.
- *
- * @param territory the territory this contextMenu is for
- * @param parent the parent window in order to display the alerts relative to
- * the calling window
- */
- public RobbiContextMenu(Territory territory, MainStage parent) {
-
- for (Method method : getDefaultMethods()) {
- MenuItem item = getMenuItem(method);
-
- // if method needs arguments and no Parameterized Annotation is set -> disable
- if (method.getParameterCount() != 0)
- item.setDisable(true);
- else
- // get Annotation parameters
- item.setOnAction(new MethodHandler(method, territory, parent));
-
- getItems().add(item);
- }
-
- Method[] methods = getCustomMethods(territory.getRobbi());
- if (methods.length > 0) {
- getItems().add(new SeparatorMenuItem());
-
- for (Method method : methods) {
- CustomMenuItem item = getMenuItem(method);
- // if method needs arguments and no parameterized Annotation is set -> disable
- if (method.getParameterCount() != 0 && !hasCorrectDefaultAnnotations(method)) {
- item.setDisable(true);
- // https://stackoverflow.com/a/43053529/13670629
- Tooltip tooltip = I18nUtils.createTooltip(EDITOR_CONTEXTMENU_TOOLTIP);
- Tooltip.install(item.getContent(), tooltip);
-
- } else
- item.setOnAction(new MethodHandler(method, territory, parent));
-
- getItems().add(item);
- }
- }
-
- }
-
- /**
- * This method checks if the given method m has the @Default annotation for all
- * parameters set.
- *
- * @param m the method to check for
- * @return true if all parameters have the default Annotation, false otherwise
- */
- private boolean hasCorrectDefaultAnnotations(Method m) {
- if (m.getParameterCount() != m.getAnnotatedParameterTypes().length)
- return false;
-
- for (Parameter parameter : m.getParameters()) {
- boolean valid = false;
- for (Annotation anno : parameter.getAnnotations()) {
- if (anno instanceof Default) {
- valid = true;
- break;
- }
- }
- if (!valid)
- return false;
- }
- return true;
- }
-
- /**
- * Creates the MenuItem for the given Method.
- * MenuItems will look like this:
- * foo(int, int)
- * bar(long = 7, int = 3)
- *
- * @param m the method to make a menuItem from
- * @return a CustomMenuItem with the correct text
- */
- private CustomMenuItem getMenuItem(Method m) {
- StringBuilder bobTheBuilder = new StringBuilder();
- bobTheBuilder.append(m.getReturnType().toString());
- bobTheBuilder.append(" ");
- bobTheBuilder.append(m.getName());
- bobTheBuilder.append("(");
- for (Parameter parameter : m.getParameters()) {
- bobTheBuilder.append(parameter.getType());
- List annos = Arrays.asList(parameter.getAnnotations());
- for (Annotation anno : annos)
- if (anno instanceof Default a) {
- bobTheBuilder.append(" = ");
- bobTheBuilder.append(a.value());
- }
- bobTheBuilder.append(", ");
- }
- if (m.getParameterCount() > 0)
- bobTheBuilder.delete(bobTheBuilder.length() - 2, bobTheBuilder.length());
- bobTheBuilder.append(")");
- return new CustomMenuItem(new Label(bobTheBuilder.toString()));
- }
-
- /**
- * Get all methods that are part of the default implementation, that are
- * visibile to the user.
- *
- * @return all methods that are part of the default implementation
- */
- private Method[] getDefaultMethods() {
- List methods = new ArrayList<>();
-
- for (Method m : Robbi.class.getDeclaredMethods()) {
- if (Modifier.isPublic(m.getModifiers()) && !isMainMethod(m))
- methods.add(m);
- }
- return methods.toArray(Method[]::new);
- }
-
- /**
- * Get all methods that are implemented by the user and are not part of the
- * default implementation of robbi.
- *
- * @param robbi the Robbi instance to get the custom methods from
- * @return all methods that are not part of the default implementation
- */
- private Method[] getCustomMethods(Robbi robbi) {
- List methods = new ArrayList<>();
- // if robbi is custom class
- if (Robbi.class != robbi.getClass()) {
- for (Method m : robbi.getClass().getDeclaredMethods()) {
-
- int modifiers = m.getModifiers();
-
- if (!Modifier.isPrivate(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isAbstract(modifiers)
- && !isInvisible(m))
- methods.add(m);
- }
- }
-
- return methods.toArray(Method[]::new);
- }
-
- /**
- * Checks if a method has the invisible annotation.
- *
- * @param m the method to check for
- * @return true if the Invisible annotation is set, false otherwise
- */
- private boolean isInvisible(Method m) {
- for (Annotation anno : m.getAnnotations())
- if (anno instanceof Invisible)
- return true;
- return false;
- }
-
- /**
- * Checks if the method is the main-Method.
- *
- * @param m method to check
- * @return true if the name of the method equals "main", false otherwise
- */
- private boolean isMainMethod(Method m) {
- return m.getName().equals("main");
- }
+ private static final String EDITOR_CONTEXTMENU_TOOLTIP = "Editor.contextMenu.tooltip";
+
+ /**
+ * Constructor to create a new RobbiContextMenu. It fills itself with all
+ * methods that are provided by robbi and allows to run a particular method on
+ * its own.
+ *
+ * @param territory the territory this contextMenu is for
+ * @param parent the parent window in order to display the alerts relative to
+ * the calling window
+ */
+ public RobbiContextMenu(Territory territory, MainStage parent) {
+
+ for (Method method : getDefaultMethods()) {
+ MenuItem item = getMenuItem(method);
+
+ // if method needs arguments and no Parameterized Annotation is set -> disable
+ if (method.getParameterCount() != 0)
+ item.setDisable(true);
+ else
+ // get Annotation parameters
+ item.setOnAction(new MethodHandler(method, territory, parent));
+
+ getItems().add(item);
+ }
+
+ Method[] methods = getCustomMethods(territory.getRobbi());
+ if (methods.length > 0) {
+ getItems().add(new SeparatorMenuItem());
+
+ for (Method method : methods) {
+ CustomMenuItem item = getMenuItem(method);
+ // if method needs arguments and no parameterized Annotation is set -> disable
+ if (method.getParameterCount() != 0 && !hasCorrectDefaultAnnotations(method)) {
+ item.setDisable(true);
+ // https://stackoverflow.com/a/43053529/13670629
+ Tooltip tooltip = I18nUtils.createTooltip(EDITOR_CONTEXTMENU_TOOLTIP);
+ Tooltip.install(item.getContent(), tooltip);
+
+ } else
+ item.setOnAction(new MethodHandler(method, territory, parent));
+
+ getItems().add(item);
+ }
+ }
+
+ }
+
+ /**
+ * This method checks if the given method m has the @Default annotation for all
+ * parameters set.
+ *
+ * @param m the method to check for
+ * @return true if all parameters have the default Annotation, false otherwise
+ */
+ private boolean hasCorrectDefaultAnnotations(Method m) {
+ if (m.getParameterCount() != m.getAnnotatedParameterTypes().length)
+ return false;
+
+ for (Parameter parameter : m.getParameters()) {
+ boolean valid = false;
+ for (Annotation anno : parameter.getAnnotations()) {
+ if (anno instanceof Default) {
+ valid = true;
+ break;
+ }
+ }
+ if (!valid)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Creates the MenuItem for the given Method.
+ * MenuItems will look like this:
+ * foo(int, int)
+ * bar(long = 7, int = 3)
+ *
+ * @param m the method to make a menuItem from
+ * @return a CustomMenuItem with the correct text
+ */
+ private CustomMenuItem getMenuItem(Method m) {
+ StringBuilder bobTheBuilder = new StringBuilder();
+ bobTheBuilder.append(m.getReturnType());
+ bobTheBuilder.append(" ");
+ bobTheBuilder.append(m.getName());
+ bobTheBuilder.append("(");
+ for (Parameter parameter : m.getParameters()) {
+ bobTheBuilder.append(parameter.getType());
+ Annotation[] annotations = parameter.getAnnotations();
+ for (Annotation anno : annotations)
+ if (anno instanceof Default a) {
+ bobTheBuilder.append(" = ");
+ bobTheBuilder.append(a.value());
+ }
+ bobTheBuilder.append(", ");
+ }
+ if (m.getParameterCount() > 0)
+ bobTheBuilder.delete(bobTheBuilder.length() - 2, bobTheBuilder.length());
+ bobTheBuilder.append(")");
+ return new CustomMenuItem(new Label(bobTheBuilder.toString()));
+ }
+
+ /**
+ * Get all methods that are part of the default implementation, that are
+ * visible to the user.
+ *
+ * @return all methods that are part of the default implementation
+ */
+ private Method[] getDefaultMethods() {
+ List methods = new ArrayList<>();
+
+ for (Method m : Robbi.class.getDeclaredMethods()) {
+ if (Modifier.isPublic(m.getModifiers()) && !isMainMethod(m))
+ methods.add(m);
+ }
+ return methods.toArray(Method[]::new);
+ }
+
+ /**
+ * Get all methods that are implemented by the user and are not part of the
+ * default implementation of robbi.
+ *
+ * @param robbi the Robbi instance to get the custom methods from
+ * @return all methods that are not part of the default implementation
+ */
+ private Method[] getCustomMethods(Robbi robbi) {
+ List methods = new ArrayList<>();
+ // if robbi is custom class
+ if (Robbi.class != robbi.getClass()) {
+ for (Method m : robbi.getClass().getDeclaredMethods()) {
+
+ int modifiers = m.getModifiers();
+
+ if (!Modifier.isPrivate(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isAbstract(modifiers)
+ && !isInvisible(m))
+ methods.add(m);
+ }
+ }
+
+ return methods.toArray(Method[]::new);
+ }
+
+ /**
+ * Checks if a method has the invisible annotation.
+ *
+ * @param m the method to check for
+ * @return true if the Invisible annotation is set, false otherwise
+ */
+ private boolean isInvisible(Method m) {
+ for (Annotation anno : m.getAnnotations())
+ if (anno instanceof Invisible)
+ return true;
+ return false;
+ }
+
+ /**
+ * Checks if the method is the main-Method.
+ *
+ * @param m method to check
+ * @return true if the name of the method equals "main", false otherwise
+ */
+ private boolean isMainMethod(Method m) {
+ return m.getName().equals("main");
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/view/TerritoryPanel.java b/src/main/java/com/JayPi4c/RobbiSimulator/view/TerritoryPanel.java
index cb4f187..f05e430 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/view/TerritoryPanel.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/view/TerritoryPanel.java
@@ -2,18 +2,9 @@
import com.JayPi4c.RobbiSimulator.controller.ButtonState;
import com.JayPi4c.RobbiSimulator.controller.TerritoryEventHandler;
-import com.JayPi4c.RobbiSimulator.model.Accu;
-import com.JayPi4c.RobbiSimulator.model.Hollow;
-import com.JayPi4c.RobbiSimulator.model.Item;
-import com.JayPi4c.RobbiSimulator.model.Nut;
-import com.JayPi4c.RobbiSimulator.model.PileOfScrap;
-import com.JayPi4c.RobbiSimulator.model.Screw;
-import com.JayPi4c.RobbiSimulator.model.Stockpile;
-import com.JayPi4c.RobbiSimulator.model.Territory;
-import com.JayPi4c.RobbiSimulator.model.Tile;
+import com.JayPi4c.RobbiSimulator.model.*;
import com.JayPi4c.RobbiSimulator.utils.Observable;
import com.JayPi4c.RobbiSimulator.utils.Observer;
-
import javafx.application.Platform;
import javafx.geometry.Bounds;
import javafx.scene.canvas.Canvas;
@@ -23,273 +14,267 @@
import lombok.extern.slf4j.Slf4j;
/**
- *
* This class draws the territory on a panel to allow interacting with the
* graphical interface.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Slf4j
public class TerritoryPanel extends Canvas implements Observer {
- private Territory territory;
-
- private static final Image[] tileImages = new Image[4];
- private static final Image[] itemImages = new Image[3];
- private static final Image robbiImage;
-
- private static final int TILE = 0;
- private static final int STOCKPILE = 1;
- private static final int HOLLOW = 2;
- private static final int PILEOFSCRAP = 3;
- private static final int NUT = 0;
- private static final int SCREW = 1;
- private static final int ACCU = 2;
-
- private static final int CELLSIZE = 32;
- private static final int CELLSPACER = 1;
-
- // store current bounds to allow centering on updated territory size
- private Bounds bounds;
-
- /**
- * loading territory images
- */
- static {
-
- logger.debug("Loading territory images");
-
- robbiImage = new Image(String.valueOf(MainStage.class.getResource("/img/0Robbi32.png")));
-
- tileImages[TILE] = new Image(String.valueOf(MainStage.class.getResource("/img/Tile32.png")));
- tileImages[STOCKPILE] = new Image(String.valueOf(MainStage.class.getResource("/img/Stockpile32.png")));
- tileImages[HOLLOW] = new Image(String.valueOf(MainStage.class.getResource("/img/Hollow32.png")));
- tileImages[PILEOFSCRAP] = new Image(String.valueOf(MainStage.class.getResource("/img/PileOfScrap32.png")));
-
- itemImages[NUT] = new Image(String.valueOf(MainStage.class.getResource("/img/Nut32.png")));
- itemImages[SCREW] = new Image(String.valueOf(MainStage.class.getResource("/img/Screw32.png")));
- itemImages[ACCU] = new Image(String.valueOf(MainStage.class.getResource("/img/Accu32.png")));
- }
-
- /**
- * Constructor to create a new territory panel for the given territory.
- *
- * @param territory the territory this panel is for
- * @param buttonState the buttonState to be able to create a
- * TerritoryEventHandler
- * @param parent the parent Window to show alerts relative to the calling
- * window
- */
- public TerritoryPanel(Territory territory, ButtonState buttonState, MainStage parent) {
- this.territory = territory;
- this.territory.addObserver(this);
-
- TerritoryEventHandler eventHandler = new TerritoryEventHandler(territory, this, buttonState, parent);
- this.setOnMousePressed(eventHandler);
- this.setOnMouseDragged(eventHandler);
- this.setOnMouseReleased(eventHandler);
-
- drawPanel();
- }
-
- /**
- * Getter for the CELLSIZE.
- *
- * @return CELLSIZE value
- */
- public static int getCellsize() {
- return CELLSIZE;
- }
-
- /**
- * Getter for the CELLSPACER.
- *
- * @return CELLSPACER value
- */
- public static int getCellspacer() {
- return CELLSPACER;
- }
-
- /**
- * updates the size of the territory if the size has changed. Paints the
- * territory afterwards.
- */
- private void drawPanel() {
- if (getWidth() != getTerritoryWidth())
- setWidth(getTerritoryWidth());
- if (getHeight() != getTerritoryHeight())
- setHeight(getTerritoryHeight());
- paintTerritory();
-
- }
-
- /**
- * Getter for the territory width.
- *
- * @return the width of the territory, calculated by number of cols, Cellsize
- * and cellspacer
- */
- private int getTerritoryWidth() {
- return (territory.getNumCols()) * (CELLSIZE + CELLSPACER);
- }
-
- /**
- * Getter for the territory height.
- *
- * @return the height of the territory, calculated by number of rows, Cellsize
- * and cellspacer
- */
- private int getTerritoryHeight() {
- return (territory.getNumRows()) * (CELLSIZE + CELLSPACER);
- }
-
- /**
- * Paint all graphics for the territory and the robbi on the GUI.
- */
- private void paintTerritory() {
-
- GraphicsContext gc = getGraphicsContext2D();
- for (int i = 0; i < territory.getNumCols(); i++) {
-
- for (int j = 0; j < territory.getNumRows(); j++) {
- Tile t = territory.getTile(i, j);
- gc.drawImage(tileImages[TILE], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
- if (t instanceof Hollow) {
- gc.drawImage(tileImages[HOLLOW], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
-
- } else if (t instanceof PileOfScrap) {
- gc.drawImage(tileImages[PILEOFSCRAP], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
- } else if (t instanceof Stockpile stockpile) {
- gc.drawImage(tileImages[STOCKPILE], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
- boolean nutDrawn = false;
- boolean accuDrawn = false;
- boolean screwDrawn = false;
- for (Item item : stockpile.getAllItems()) {
- if (!nutDrawn && item instanceof Nut) {
- gc.drawImage(itemImages[NUT], getPos(i) + CELLSIZE / 2d, getPos(j), CELLSIZE / 2d,
- CELLSIZE / 2d);
- nutDrawn = true;
- } else if (!accuDrawn && item instanceof Accu) {
- gc.drawImage(itemImages[ACCU], getPos(i), getPos(j), CELLSIZE / 2d, CELLSIZE / 2d);
- accuDrawn = true;
- } else if (!screwDrawn && item instanceof Screw) {
- gc.drawImage(itemImages[SCREW], getPos(i) + CELLSIZE / 3d, getPos(j) + CELLSIZE / 2d,
- CELLSIZE / 2d, CELLSIZE / 2d);
- screwDrawn = true;
- }
- if (nutDrawn && accuDrawn && screwDrawn)
- break;
- }
- }
- if (!(t instanceof Stockpile)) {
- Item item = t.getItem();
- if (item instanceof Nut) {
- gc.drawImage(itemImages[NUT], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
- } else if (item instanceof Screw) {
- gc.drawImage(itemImages[SCREW], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
- } else if (item instanceof Accu) {
- gc.drawImage(itemImages[ACCU], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
- }
-
- }
- }
- }
-
- double angle = switch (territory.getRobbiDirection()) {
- case NORTH:
- yield 270;
- case WEST:
- yield 180;
- case SOUTH:
- yield 90;
- case EAST:
- default:
- yield 0;
- };
- drawRotatedImage(gc, robbiImage, angle, (double) territory.getRobbiX() * (CELLSIZE + CELLSPACER) + CELLSPACER,
- (double) territory.getRobbiY() * (CELLSIZE + CELLSPACER) + CELLSPACER, CELLSIZE, CELLSIZE);
- }
-
- /**
- * Sets the transform for the GraphicsContext to rotate around a pivot point.
- *
- * @param gc the graphics context the transform to applied to.
- * @param angle the angle of rotation.
- * @param px the x pivot co-ordinate for the rotation (in canvas
- * co-ordinates).
- * @param py the y pivot co-ordinate for the rotation (in canvas
- * co-ordinates).
- * @see Stackoverflow
- */
- private void rotate(GraphicsContext gc, double angle, double px, double py) {
- Rotate r = new Rotate(angle, px, py);
- gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
- }
-
- /**
- * Draws an image on a graphics context.
- *
- * The image is drawn at (tlpx, tlpy) rotated by angle pivoted around the point:
- * (tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2)
- *
- * @param gc the graphics context the image is to be drawn on.
- * @param angle the angle of rotation.
- * @param tlpx the top left x co-ordinate where the image will be plotted (in
- * canvas co-ordinates).
- * @param tlpy the top left y co-ordinate where the image will be plotted (in
- * canvas co-ordinates).
- * @see Stackoverflow
- */
- private void drawRotatedImage(GraphicsContext gc, Image image, double angle, double tlpx, double tlpy, double w,
- double h) {
- gc.save(); // saves the current state on stack, including the current transform
- rotate(gc, angle, tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2);
- gc.drawImage(image, tlpx, tlpy, w, h);
- gc.restore(); // back to original state (before rotation)
- }
-
- private int getPos(int val) {
- return (val) * (CELLSIZE + CELLSPACER) + CELLSPACER;
- }
-
- /**
- * taken from Dibo
- * Centers the territory-panel in the center of the viewPortBounds.
- *
- * @param vpb The bounds in which the territory has to be centered
- */
- public void center(Bounds vpb) {
- this.bounds = vpb;
- double w = vpb.getWidth();
- double h = vpb.getHeight();
- if (w > getTerritoryWidth()) {
- setTranslateX((w - getTerritoryWidth()) / 2);
- } else
- setTranslateX(0);
- if (h > getTerritoryHeight()) {
- setTranslateY((h - getTerritoryHeight()) / 2);
- } else
- setTranslateY(0);
- }
-
- @Override
- public void update(Observable observable) {
- Platform.runLater(this::update);
- }
-
- /**
- * Centers the territory if the size has changed. Afterwards, it draws the
- * territorypanel.
- */
- public void update() {
- if (territory.hasSizeChanged()) {
- center(bounds);
- territory.setSizeChanged(false);
- }
- drawPanel();
- }
+ private final Territory territory;
+
+ private static final Image[] tileImages = new Image[4];
+ private static final Image[] itemImages = new Image[3];
+ private static final Image robbiImage;
+
+ private static final int TILE = 0;
+ private static final int STOCKPILE = 1;
+ private static final int HOLLOW = 2;
+ private static final int PILEOFSCRAP = 3;
+ private static final int NUT = 0;
+ private static final int SCREW = 1;
+ private static final int ACCU = 2;
+
+ private static final int CELLSIZE = 32;
+ private static final int CELLSPACER = 1;
+
+ // store current bounds to allow centering on updated territory size
+ private Bounds bounds;
+
+ static {
+
+ logger.debug("Loading territory images");
+
+ robbiImage = new Image(String.valueOf(MainStage.class.getResource("/img/0Robbi32.png")));
+
+ tileImages[TILE] = new Image(String.valueOf(MainStage.class.getResource("/img/Tile32.png")));
+ tileImages[STOCKPILE] = new Image(String.valueOf(MainStage.class.getResource("/img/Stockpile32.png")));
+ tileImages[HOLLOW] = new Image(String.valueOf(MainStage.class.getResource("/img/Hollow32.png")));
+ tileImages[PILEOFSCRAP] = new Image(String.valueOf(MainStage.class.getResource("/img/PileOfScrap32.png")));
+
+ itemImages[NUT] = new Image(String.valueOf(MainStage.class.getResource("/img/Nut32.png")));
+ itemImages[SCREW] = new Image(String.valueOf(MainStage.class.getResource("/img/Screw32.png")));
+ itemImages[ACCU] = new Image(String.valueOf(MainStage.class.getResource("/img/Accu32.png")));
+ }
+
+ /**
+ * Constructor to create a new territory panel for the given territory.
+ *
+ * @param territory the territory this panel is for
+ * @param buttonState the buttonState to be able to create a
+ * TerritoryEventHandler
+ * @param parent the parent Window to show alerts relative to the calling
+ * window
+ */
+ public TerritoryPanel(Territory territory, ButtonState buttonState, MainStage parent) {
+ this.territory = territory;
+ this.territory.addObserver(this);
+
+ TerritoryEventHandler eventHandler = new TerritoryEventHandler(territory, this, buttonState, parent);
+ this.setOnMousePressed(eventHandler);
+ this.setOnMouseDragged(eventHandler);
+ this.setOnMouseReleased(eventHandler);
+
+ drawPanel();
+ }
+
+ /**
+ * Getter for the CELLSIZE.
+ *
+ * @return CELLSIZE value
+ */
+ public static int getCellsize() {
+ return CELLSIZE;
+ }
+
+ /**
+ * Getter for the CELLSPACER.
+ *
+ * @return CELLSPACER value
+ */
+ public static int getCellspacer() {
+ return CELLSPACER;
+ }
+
+ /**
+ * updates the size of the territory if the size has changed. Paints the
+ * territory afterward.
+ */
+ private void drawPanel() {
+ if (getWidth() != getTerritoryWidth())
+ setWidth(getTerritoryWidth());
+ if (getHeight() != getTerritoryHeight())
+ setHeight(getTerritoryHeight());
+ paintTerritory();
+
+ }
+
+ /**
+ * Getter for the territory width.
+ *
+ * @return the width of the territory, calculated by number of cols, Cell-size
+ * and cell-spacer
+ */
+ private int getTerritoryWidth() {
+ return (territory.getNumCols()) * (CELLSIZE + CELLSPACER);
+ }
+
+ /**
+ * Getter for the territory height.
+ *
+ * @return the height of the territory, calculated by number of rows, Cellsize
+ * and cellspacer
+ */
+ private int getTerritoryHeight() {
+ return (territory.getNumRows()) * (CELLSIZE + CELLSPACER);
+ }
+
+ /**
+ * Paint all graphics for the territory and the robbi on the GUI.
+ */
+ private void paintTerritory() {
+
+ GraphicsContext gc = getGraphicsContext2D();
+ for (int i = 0; i < territory.getNumCols(); i++) {
+
+ for (int j = 0; j < territory.getNumRows(); j++) {
+ Tile t = territory.getTile(i, j);
+ gc.drawImage(tileImages[TILE], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
+ if (t instanceof Hollow) {
+ gc.drawImage(tileImages[HOLLOW], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
+
+ } else if (t instanceof PileOfScrap) {
+ gc.drawImage(tileImages[PILEOFSCRAP], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
+ } else if (t instanceof Stockpile stockpile) {
+ gc.drawImage(tileImages[STOCKPILE], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
+ boolean nutDrawn = false;
+ boolean accuDrawn = false;
+ boolean screwDrawn = false;
+ for (Item item : stockpile.getAllItems()) {
+ if (!nutDrawn && item instanceof Nut) {
+ gc.drawImage(itemImages[NUT], getPos(i) + CELLSIZE / 2d, getPos(j), CELLSIZE / 2d,
+ CELLSIZE / 2d);
+ nutDrawn = true;
+ } else if (!accuDrawn && item instanceof Accu) {
+ gc.drawImage(itemImages[ACCU], getPos(i), getPos(j), CELLSIZE / 2d, CELLSIZE / 2d);
+ accuDrawn = true;
+ } else if (!screwDrawn && item instanceof Screw) {
+ gc.drawImage(itemImages[SCREW], getPos(i) + CELLSIZE / 3d, getPos(j) + CELLSIZE / 2d,
+ CELLSIZE / 2d, CELLSIZE / 2d);
+ screwDrawn = true;
+ }
+ if (nutDrawn && accuDrawn && screwDrawn)
+ break;
+ }
+ }
+ if (!(t instanceof Stockpile)) {
+ Item item = t.getItem();
+ if (item instanceof Nut) {
+ gc.drawImage(itemImages[NUT], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
+ } else if (item instanceof Screw) {
+ gc.drawImage(itemImages[SCREW], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
+ } else if (item instanceof Accu) {
+ gc.drawImage(itemImages[ACCU], getPos(i), getPos(j), CELLSIZE, CELLSIZE);
+ }
+
+ }
+ }
+ }
+
+ double angle = switch (territory.getRobbiDirection()) {
+ case NORTH:
+ yield 270;
+ case WEST:
+ yield 180;
+ case SOUTH:
+ yield 90;
+ case EAST:
+ yield 0;
+ };
+ drawRotatedImage(gc, robbiImage, angle, (double) territory.getRobbiX() * (CELLSIZE + CELLSPACER) + CELLSPACER,
+ (double) territory.getRobbiY() * (CELLSIZE + CELLSPACER) + CELLSPACER, CELLSIZE, CELLSIZE);
+ }
+
+ /**
+ * Sets the transform for the GraphicsContext to rotate around a pivot point.
+ *
+ * @param gc the graphics context the transform to applied to.
+ * @param angle the angle of rotation.
+ * @param px the x pivot co-ordinate for the rotation (in canvas
+ * co-ordinates).
+ * @param py the y pivot co-ordinate for the rotation (in canvas
+ * co-ordinates).
+ * @see Stackoverflow
+ */
+ private void rotate(GraphicsContext gc, double angle, double px, double py) {
+ Rotate r = new Rotate(angle, px, py);
+ gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
+ }
+
+ /**
+ * Draws an image on a graphics context.
+ *
+ * The image is drawn at (tlpx, tlpy) rotated by angle pivoted around the point:
+ * (tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2)
+ *
+ * @param gc the graphics context the image is to be drawn on.
+ * @param angle the angle of rotation.
+ * @param tlpx the top left x co-ordinate where the image will be plotted (in
+ * canvas co-ordinates).
+ * @param tlpy the top left y co-ordinate where the image will be plotted (in
+ * canvas co-ordinates).
+ * @see Stackoverflow
+ */
+ private void drawRotatedImage(GraphicsContext gc, Image image, double angle, double tlpx, double tlpy, double w,
+ double h) {
+ gc.save(); // saves the current state on stack, including the current transform
+ rotate(gc, angle, tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2);
+ gc.drawImage(image, tlpx, tlpy, w, h);
+ gc.restore(); // back to original state (before rotation)
+ }
+
+ private int getPos(int val) {
+ return (val) * (CELLSIZE + CELLSPACER) + CELLSPACER;
+ }
+
+ /**
+ * taken from Dibo
+ * Centers the territory-panel in the center of the viewPortBounds.
+ *
+ * @param vpb The bounds in which the territory has to be centered
+ */
+ public void center(Bounds vpb) {
+ this.bounds = vpb;
+ double w = vpb.getWidth();
+ double h = vpb.getHeight();
+ if (w > getTerritoryWidth()) {
+ setTranslateX((w - getTerritoryWidth()) / 2);
+ } else
+ setTranslateX(0);
+ if (h > getTerritoryHeight()) {
+ setTranslateY((h - getTerritoryHeight()) / 2);
+ } else
+ setTranslateY(0);
+ }
+
+ @Override
+ public void update(Observable observable) {
+ Platform.runLater(this::update);
+ }
+
+ /**
+ * Centers the territory if the size has changed. Afterward, it draws the
+ * territory-panel.
+ */
+ public void update() {
+ if (territory.hasSizeChanged()) {
+ center(bounds);
+ territory.setSizeChanged(false);
+ }
+ drawPanel();
+ }
}
diff --git a/src/main/java/com/JayPi4c/RobbiSimulator/view/Toolbar.java b/src/main/java/com/JayPi4c/RobbiSimulator/view/Toolbar.java
index 575beb9..838a801 100644
--- a/src/main/java/com/JayPi4c/RobbiSimulator/view/Toolbar.java
+++ b/src/main/java/com/JayPi4c/RobbiSimulator/view/Toolbar.java
@@ -1,178 +1,162 @@
package com.JayPi4c.RobbiSimulator.view;
-import com.jfoenix.controls.JFXButton;
-import com.jfoenix.controls.JFXButton.ButtonType;
-import com.jfoenix.controls.JFXSlider;
-import com.jfoenix.controls.JFXToggleNode;
-
-import javafx.scene.control.Button;
-import javafx.scene.control.Separator;
-import javafx.scene.control.Slider;
-import javafx.scene.control.ToggleButton;
-import javafx.scene.control.ToggleGroup;
-import javafx.scene.control.ToolBar;
+import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
/**
* The toolbar allows faster access to the most common actions.
- *
- * @author Jonas Pohl
*
+ * @author Jonas Pohl
*/
@Getter
@Slf4j
public class Toolbar extends ToolBar {
- private MenuBar menubar;
-
- // Tool bar
- private Button newButtonToolbar;
- private Button loadButtonToolbar;
-
- private Button saveButtonToolbar;
- private Button compileButtonToolbar;
-
- private Button changeSizeButtonToolbar;
- private ToggleButton placeRobbiToggleButtonToolbar;
- private ToggleButton placeHollowToggleButtonToolbar;
- private ToggleButton placePileOfScrapToggleButtonToolbar;
- private ToggleButton placeStockpileToggleButtonToolbar;
- private ToggleButton placeAccuToggleButtonToolbar;
- private ToggleButton placeScrewToggleButtonToolbar;
- private ToggleButton placeNutToggleButtonToolbar;
- private ToggleButton deleteFieldToggleButtonToolbar;
-
- private Button robbiTurnLeftButtonToolbar;
- private Button robbiMoveButtonToolbar;
- private Button robbiPutButtonToolbar;
- private Button robbiTakeButtonToolbar;
-
- private Button resetButtonToolbar;
- private ToggleButton startToggleButtonToolbar;
- private ToggleButton pauseToggleButtonToolbar;
- private ToggleButton stopToggleButtonToolbar;
-
- private Slider speedSliderToolbar;
-
- /**
- * Constant for the minimum value for the speed slider.
- */
- public static final int MIN_SPEED_VALUE = 1;
- /**
- * Constant for the maximum value for the speed slider.
- */
- public static final int MAX_SPEED_VALUE = 100;
-
- /**
- * Creates a new Toolbar
- *
- * @param menubar the menubar to link some actions from the menubar to the
- * toolbar buttons
- */
- public Toolbar(MenuBar menubar) {
- this.menubar = menubar;
- createToolbar();
- }
-
- /**
- * Creates a toolbar for direct-access to the most important features.
- */
- private void createToolbar() {
- logger.debug("Create toolbar");
- newButtonToolbar = new JFXButton(null, new ImageView(MainStage.newImage));
- ((JFXButton) newButtonToolbar).setButtonType(ButtonType.RAISED);
-
- loadButtonToolbar = new JFXButton(null, new ImageView(MainStage.openImage));
-
- saveButtonToolbar = new JFXButton(null, new ImageView(MainStage.saveImage));
-
- compileButtonToolbar = new JFXButton(null, new ImageView(MainStage.compileImage));
-
- changeSizeButtonToolbar = new JFXButton(null, new ImageView(MainStage.terrainImage));
-
- var placeGroupToolbar = new ToggleGroup();
-
- placeRobbiToggleButtonToolbar = new JFXToggleNode();
- placeRobbiToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuRobbiImage));
- placeRobbiToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
- placeRobbiToggleButtonToolbar.selectedProperty()
- .bindBidirectional(menubar.getPlaceRobbiTerritoryRadioMenuItem().selectedProperty());
-
- placeHollowToggleButtonToolbar = new JFXToggleNode();
- placeHollowToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuHollowImage));
- placeHollowToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
- placeHollowToggleButtonToolbar.selectedProperty()
- .bindBidirectional(menubar.getPlaceHollowTerritoryRadioMenuItem().selectedProperty());
-
- placePileOfScrapToggleButtonToolbar = new JFXToggleNode();
- placePileOfScrapToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuPileOfScrapImage));
- placePileOfScrapToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
- placePileOfScrapToggleButtonToolbar.selectedProperty()
- .bindBidirectional(menubar.getPlacePileOfScrapTerritoryRadioMenuItem().selectedProperty());
-
- placeStockpileToggleButtonToolbar = new JFXToggleNode();
- placeStockpileToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuStockpileImage));
- placeStockpileToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
- placeStockpileToggleButtonToolbar.selectedProperty()
- .bindBidirectional(menubar.getPlaceStockpileTerritoryRadioMenuItem().selectedProperty());
-
- placeAccuToggleButtonToolbar = new JFXToggleNode();
- placeAccuToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuAccuImage));
- placeAccuToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
- placeAccuToggleButtonToolbar.selectedProperty()
- .bindBidirectional(menubar.getPlaceAccuTerritoryRadioMenuItem().selectedProperty());
-
- placeScrewToggleButtonToolbar = new JFXToggleNode();
- placeScrewToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuScrewImage));
- placeScrewToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
- placeScrewToggleButtonToolbar.selectedProperty()
- .bindBidirectional(menubar.getPlaceScrewTerritoryRadioMenuItem().selectedProperty());
-
- placeNutToggleButtonToolbar = new JFXToggleNode();
- placeNutToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuNutImage));
- placeNutToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
- placeNutToggleButtonToolbar.selectedProperty()
- .bindBidirectional(menubar.getPlaceNutTerritoryRadioMenuItem().selectedProperty());
-
- deleteFieldToggleButtonToolbar = new JFXToggleNode();
- deleteFieldToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuDeleteImage));
- deleteFieldToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
- deleteFieldToggleButtonToolbar.selectedProperty()
- .bindBidirectional(menubar.getDeleteFieldRadioMenuItem().selectedProperty());
-
- robbiMoveButtonToolbar = new JFXButton(null, new ImageView(MainStage.robbiMove));
-
- robbiTurnLeftButtonToolbar = new JFXButton(null, new ImageView(MainStage.robbiTurnLeft));
-
- robbiPutButtonToolbar = new JFXButton(null, new ImageView(MainStage.robbiPut));
-
- robbiTakeButtonToolbar = new JFXButton(null, new ImageView(MainStage.robbiTake));
-
- resetButtonToolbar = new JFXButton(null, new ImageView(MainStage.resetImage));
-
- var simulationGroupToolbar = new ToggleGroup();
- startToggleButtonToolbar = new JFXToggleNode();
- startToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuStartImage));
- startToggleButtonToolbar.setToggleGroup(simulationGroupToolbar);
-
- pauseToggleButtonToolbar = new JFXToggleNode();
- pauseToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuPauseImage));
- pauseToggleButtonToolbar.setToggleGroup(simulationGroupToolbar);
-
- stopToggleButtonToolbar = new JFXToggleNode();
- stopToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuStopImage));
- stopToggleButtonToolbar.setToggleGroup(simulationGroupToolbar);
-
- speedSliderToolbar = new JFXSlider(MIN_SPEED_VALUE, MAX_SPEED_VALUE, (MIN_SPEED_VALUE + MAX_SPEED_VALUE) / 2d);
-
- getItems().addAll(newButtonToolbar, loadButtonToolbar, new Separator(), saveButtonToolbar, compileButtonToolbar,
- new Separator(), changeSizeButtonToolbar, placeRobbiToggleButtonToolbar, placeHollowToggleButtonToolbar,
- placePileOfScrapToggleButtonToolbar, placeStockpileToggleButtonToolbar, placeAccuToggleButtonToolbar,
- placeScrewToggleButtonToolbar, placeNutToggleButtonToolbar, deleteFieldToggleButtonToolbar,
- new Separator(), robbiMoveButtonToolbar, robbiTurnLeftButtonToolbar, robbiPutButtonToolbar,
- robbiTakeButtonToolbar, new Separator(), resetButtonToolbar, startToggleButtonToolbar,
- pauseToggleButtonToolbar, stopToggleButtonToolbar, new Separator(), speedSliderToolbar);
- }
+ /**
+ * Constant for the minimum value for the speed slider.
+ */
+ public static final int MIN_SPEED_VALUE = 1;
+ /**
+ * Constant for the maximum value for the speed slider.
+ */
+ public static final int MAX_SPEED_VALUE = 10;
+ private final MenuBar menubar;
+ // Toolbar
+ private Button newButtonToolbar;
+ private Button loadButtonToolbar;
+ private Button saveButtonToolbar;
+ private Button compileButtonToolbar;
+ private Button changeSizeButtonToolbar;
+ private ToggleButton placeRobbiToggleButtonToolbar;
+ private ToggleButton placeHollowToggleButtonToolbar;
+ private ToggleButton placePileOfScrapToggleButtonToolbar;
+ private ToggleButton placeStockpileToggleButtonToolbar;
+ private ToggleButton placeAccuToggleButtonToolbar;
+ private ToggleButton placeScrewToggleButtonToolbar;
+ private ToggleButton placeNutToggleButtonToolbar;
+ private ToggleButton deleteFieldToggleButtonToolbar;
+ private Button robbiTurnLeftButtonToolbar;
+ private Button robbiMoveButtonToolbar;
+ private Button robbiPutButtonToolbar;
+ private Button robbiTakeButtonToolbar;
+ private Button resetButtonToolbar;
+ private ToggleButton startToggleButtonToolbar;
+ private ToggleButton pauseToggleButtonToolbar;
+ private ToggleButton stopToggleButtonToolbar;
+ private Slider speedSliderToolbar;
+
+ /**
+ * Creates a new Toolbar
+ *
+ * @param menubar the menubar to link some actions from the menubar to the
+ * toolbar buttons
+ */
+ public Toolbar(MenuBar menubar) {
+ this.menubar = menubar;
+ createToolbar();
+ }
+
+ /**
+ * Creates a toolbar for direct-access to the most important features.
+ */
+ private void createToolbar() {
+ logger.debug("Create toolbar");
+ newButtonToolbar = new Button(null, new ImageView(MainStage.newImage));
+
+
+ loadButtonToolbar = new Button(null, new ImageView(MainStage.openImage));
+
+ saveButtonToolbar = new Button(null, new ImageView(MainStage.saveImage));
+
+ compileButtonToolbar = new Button(null, new ImageView(MainStage.compileImage));
+
+ changeSizeButtonToolbar = new Button(null, new ImageView(MainStage.terrainImage));
+
+ var placeGroupToolbar = new ToggleGroup();
+
+ placeRobbiToggleButtonToolbar = new ToggleButton();
+ placeRobbiToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuRobbiImage));
+ placeRobbiToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
+ placeRobbiToggleButtonToolbar.selectedProperty()
+ .bindBidirectional(menubar.getPlaceRobbiTerritoryRadioMenuItem().selectedProperty());
+
+ placeHollowToggleButtonToolbar = new ToggleButton();
+ placeHollowToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuHollowImage));
+ placeHollowToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
+ placeHollowToggleButtonToolbar.selectedProperty()
+ .bindBidirectional(menubar.getPlaceHollowTerritoryRadioMenuItem().selectedProperty());
+
+ placePileOfScrapToggleButtonToolbar = new ToggleButton();
+ placePileOfScrapToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuPileOfScrapImage));
+ placePileOfScrapToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
+ placePileOfScrapToggleButtonToolbar.selectedProperty()
+ .bindBidirectional(menubar.getPlacePileOfScrapTerritoryRadioMenuItem().selectedProperty());
+
+ placeStockpileToggleButtonToolbar = new ToggleButton();
+ placeStockpileToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuStockpileImage));
+ placeStockpileToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
+ placeStockpileToggleButtonToolbar.selectedProperty()
+ .bindBidirectional(menubar.getPlaceStockpileTerritoryRadioMenuItem().selectedProperty());
+
+ placeAccuToggleButtonToolbar = new ToggleButton();
+ placeAccuToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuAccuImage));
+ placeAccuToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
+ placeAccuToggleButtonToolbar.selectedProperty()
+ .bindBidirectional(menubar.getPlaceAccuTerritoryRadioMenuItem().selectedProperty());
+
+ placeScrewToggleButtonToolbar = new ToggleButton();
+ placeScrewToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuScrewImage));
+ placeScrewToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
+ placeScrewToggleButtonToolbar.selectedProperty()
+ .bindBidirectional(menubar.getPlaceScrewTerritoryRadioMenuItem().selectedProperty());
+
+ placeNutToggleButtonToolbar = new ToggleButton();
+ placeNutToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuNutImage));
+ placeNutToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
+ placeNutToggleButtonToolbar.selectedProperty()
+ .bindBidirectional(menubar.getPlaceNutTerritoryRadioMenuItem().selectedProperty());
+
+ deleteFieldToggleButtonToolbar = new ToggleButton();
+ deleteFieldToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuDeleteImage));
+ deleteFieldToggleButtonToolbar.setToggleGroup(placeGroupToolbar);
+ deleteFieldToggleButtonToolbar.selectedProperty()
+ .bindBidirectional(menubar.getDeleteFieldRadioMenuItem().selectedProperty());
+
+ robbiMoveButtonToolbar = new Button(null, new ImageView(MainStage.robbiMove));
+
+ robbiTurnLeftButtonToolbar = new Button(null, new ImageView(MainStage.robbiTurnLeft));
+
+ robbiPutButtonToolbar = new Button(null, new ImageView(MainStage.robbiPut));
+
+ robbiTakeButtonToolbar = new Button(null, new ImageView(MainStage.robbiTake));
+
+ resetButtonToolbar = new Button(null, new ImageView(MainStage.resetImage));
+
+ var simulationGroupToolbar = new ToggleGroup();
+ startToggleButtonToolbar = new ToggleButton();
+ startToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuStartImage));
+ startToggleButtonToolbar.setToggleGroup(simulationGroupToolbar);
+
+ pauseToggleButtonToolbar = new ToggleButton();
+ pauseToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuPauseImage));
+ pauseToggleButtonToolbar.setToggleGroup(simulationGroupToolbar);
+
+ stopToggleButtonToolbar = new ToggleButton();
+ stopToggleButtonToolbar.setGraphic(new ImageView(MainStage.menuStopImage));
+ stopToggleButtonToolbar.setToggleGroup(simulationGroupToolbar);
+
+ speedSliderToolbar = new Slider(MIN_SPEED_VALUE, MAX_SPEED_VALUE, (MIN_SPEED_VALUE + MAX_SPEED_VALUE) / 2d);
+ speedSliderToolbar.setShowTickLabels(true);
+ speedSliderToolbar.setShowTickMarks(true);
+
+ getItems().addAll(newButtonToolbar, loadButtonToolbar, new Separator(), saveButtonToolbar, compileButtonToolbar,
+ new Separator(), changeSizeButtonToolbar, placeRobbiToggleButtonToolbar, placeHollowToggleButtonToolbar,
+ placePileOfScrapToggleButtonToolbar, placeStockpileToggleButtonToolbar, placeAccuToggleButtonToolbar,
+ placeScrewToggleButtonToolbar, placeNutToggleButtonToolbar, deleteFieldToggleButtonToolbar,
+ new Separator(), robbiMoveButtonToolbar, robbiTurnLeftButtonToolbar, robbiPutButtonToolbar,
+ robbiTakeButtonToolbar, new Separator(), resetButtonToolbar, startToggleButtonToolbar,
+ pauseToggleButtonToolbar, stopToggleButtonToolbar, new Separator(), speedSliderToolbar);
+ }
}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 087c4f8..1eb5585 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -5,8 +5,8 @@
requires javafx.media;
requires javafx.web;
- requires com.jfoenix;
requires eu.mihosoft.monacofx;
+ requires org.controlsfx.controls;
requires java.desktop;
requires java.rmi;
@@ -22,8 +22,11 @@
requires org.apache.derby.tools;
opens com.JayPi4c.RobbiSimulator.controller.examples to org.hibernate.orm.core;
+ opens com.JayPi4c.RobbiSimulator.model to jakarta.xml.bind;
exports com.JayPi4c.RobbiSimulator.utils.annotations;
exports com.JayPi4c.RobbiSimulator.model;
exports com.JayPi4c.RobbiSimulator;
+
+ exports com.JayPi4c.RobbiSimulator.controller.tutor to java.rmi;
}
\ No newline at end of file
diff --git a/src/main/resources/css/dark-theme.css b/src/main/resources/css/dark-theme.css
index c5f6a3c..262f9b9 100644
--- a/src/main/resources/css/dark-theme.css
+++ b/src/main/resources/css/dark-theme.css
@@ -1,3 +1,4 @@
+/* Taken from stack overflow: https://stackoverflow.com/a/49159612 */
.root {
-fx-base: #3f474f;
-fx-accent: #e7eff7;
@@ -5,18 +6,18 @@
-fx-focus-color: #efefef;
-fx-faint-focus-color: #efefef22;
-fx-focused-text-base-color: ladder(-fx-selection-bar,
- -fx-light-text-color 45%,
- -fx-dark-text-color 46%,
- -fx-dark-text-color 59%,
- -fx-mid-text-color 60%);
+ -fx-light-text-color 45%,
+ -fx-dark-text-color 46%,
+ -fx-dark-text-color 59%,
+ -fx-mid-text-color 60%);
-fx-focused-mark-color: -fx-focused-text-base-color;
}
.text-input:focused {
-fx-highlight-text-fill: ladder(-fx-highlight-fill,
- -fx-light-text-color 45%,
- -fx-dark-text-color 46%,
- -fx-dark-text-color 59%,
- -fx-mid-text-color 60%);
+ -fx-light-text-color 45%,
+ -fx-dark-text-color 46%,
+ -fx-dark-text-color 59%,
+ -fx-mid-text-color 60%);
}
\ No newline at end of file
diff --git a/src/main/resources/lang/messages_de_DE.properties b/src/main/resources/lang/messages_de_DE.properties
index ae903e5..f8ae153 100644
--- a/src/main/resources/lang/messages_de_DE.properties
+++ b/src/main/resources/lang/messages_de_DE.properties
@@ -1,186 +1,173 @@
-
-ChangeSize.dialog.cols = Spalten:
-ChangeSize.dialog.header = Bitte w\u00E4hle eine neue Gr\u00F6\u00DFe
-ChangeSize.dialog.rows = Reihen:
-ChangeSize.dialog.title = Gr\u00F6\u00DFe \u00E4ndern
-
-Compilation.annotations.header = Annotationen fehlerhaft
-Compilation.annotations.msg.default = Aufgrund fehlerhafter Annotationen konnte Robbi nicht in das Territorium geladen werden.
-Compilation.annotations.msg.info = "%s" ist nicht anwendbar f\u00FCr den Typ "%s".
-Compilation.annotations.title = Annotationenfehler
-Compilation.diagnostic = Kompilierungsfehler
-Compilation.diagnostic.CodeAndMessage = Code und Nachricht: %s: %s%n
-Compilation.diagnostic.kind = Art: %s%n
-Compilation.diagnostic.override = Robbi \u00FCberschreibt nicht die main-Methode.
-Compilation.diagnostic.row = Zeile: %s%n
-Compilation.diagnostic.source = Quelle: %s%n
-Compilation.diagnostic.title = Kompilierung Fehlgeschlagen
-Compilation.success.header = Kompilierung erfolgreich
-Compilation.success.message = Dein Sketch '%s' wurde erfolgreich kompiliert.
-Compilation.success.title = Erfolg
-
-Editor.contextMenu.executionError = Die @Default Annotation hat einen falschen String ('%s') in der Methode '%s'.
-Editor.contextMenu.tooltip = Bitte nutze die @Default Annotation.
-
-Examples.duplication.header = Es existiert bereits ein Programm mit dem Namen des Beispiels.
-Examples.duplication.message = Altes Programm umbennen?\n(Das alte Programm wird sonst \u00FCberschrieben.)
-Examples.duplication.title = Namenduplikat
-Examples.load.dialog.program.header = W\u00E4hle ein Programm aus.
-Examples.load.dialog.program.name = Programm
-Examples.load.dialog.program.title = Programmauswahl
-Examples.load.dialog.tags.fail = Es konnten keine Tags in der Datenbank gefunden werden.
-Examples.load.dialog.tags.header = W\u00E4hle einen Tag f\u00FCr ein Beispiel.
-Examples.load.dialog.tags.name = Tag
-Examples.load.dialog.tags.title = Tagauswahl
-Examples.save.tags.header = Gebe leerzeichengetrennt Tags ein.
-Examples.save.tags.name = Tags
-Examples.save.tags.prompt = Tags f\u00FCr das Beispiel
-Examples.save.tags.title = Tageingabe
-
-Exception.BagIsEmpty = Ooops! Robbi kann kein Item ablegen. Die Tasche ist leer.
-Exception.BagIsFull = Ooops! Robbi kann kein Item aufnehmen. Seine Tasche ist voll.
-Exception.HollowAhead = Ooops! Robbi kann nicht vorw\u00E4rts gehen. Es ist eine Kuhle voraus.
-Exception.NoItem = Ooops! Hier liegt kein Item, welches Robbi aufheben kann.
-Exception.NoPileOfScrapAhead = Ooops! Robbi Kann keinen Schrotthaufen zum Schieben finden.
-Exception.TileBlocked = Ooops! Robbi kann diesen Schrotthaufen nicht schieben. Die folgende Kachel ist blockiert.
-Exception.TileIsFull = Ooops! Es ist schon ein Item auf der Kachel. Robbi kann hier nichts ablegen.
-
-Execution.information.bag = Tasche voll: {0}
-Execution.information.hollow = Kuhle voraus: {0}
-Execution.information.itemPresent = Gegenstand da: {0}
-Execution.information.pileOfScrap = Schrotthaufen voraus: {0}
-Execution.information.result = Das Ergebnis des Aufrufs ist:
-Execution.information.stockpile = Lager da: {0}
-
-Init.error.header = Initialisierungsfehler
-Init.error.message = Der Program Controller konnte nicht initialisiert werden.
-Init.error.title = Error
-
-Main.title = Robbi Simulator
-
-Menu.editor = _Editor
-Menu.editor.compile = _Kompilieren
-Menu.editor.format = formatieren
-Menu.editor.new = _Neu
-Menu.editor.open = _\u00D6ffnen
-Menu.editor.print = _Drucken
-Menu.editor.quit = _Beenden
-Menu.editor.save = _Speichern
-Menu.examples = Beispiele
-Menu.examples.load = Laden
-Menu.examples.save = Speichern
-Menu.robbi = _Robbi
-Menu.robbi.hollowAhead = Vorn Kuhle
-Menu.robbi.isBagFull = Ist Tasche voll
-Menu.robbi.isStockpile = Ist Lagerplatz
-Menu.robbi.itemPresent = Gegenstand da
-Menu.robbi.move = vor
-Menu.robbi.pileOfScrapAhead = Vorn Schrotthaufen
-Menu.robbi.pushPileOfScrap = Schiebe Schrotthaufen
-Menu.robbi.put = lege ab
-Menu.robbi.take = nehme auf
-Menu.robbi.turnLeft = links um
-Menu.simulation = _Simulation
-Menu.simulation.pause = Pause
-Menu.simulation.reset = Zur\u00FCcksetzten
-Menu.simulation.start = Start/Fortsetzen
-Menu.simulation.stop = Stopp
-Menu.territory = _Territorium
-Menu.territory.delete = Kachel leeren
-Menu.territory.load = _Laden
-Menu.territory.load.deserialize = _Deserialisieren
-Menu.territory.load.jaxb = _JAXB
-Menu.territory.load.xml = _XML
-Menu.territory.place.accu = Akku platzieren
-Menu.territory.place.hollow = Kuhle platzieren
-Menu.territory.place.nut = Mutter platzieren
-Menu.territory.place.pileOfScrap = Schrotthaufen platzieren
-Menu.territory.place.robbi = Robbi platzieren
-Menu.territory.place.screw = Schraube platzieren
-Menu.territory.place.stockpile = Lagerplatz platzieren
-Menu.territory.print = _Drucken
-Menu.territory.print.error = Der Drucker konnte nicht initialisiert werden.
-Menu.territory.save = _Speichern
-Menu.territory.save.jaxb = _JAXB
-Menu.territory.save.serialize = _Serialisieren
-Menu.territory.save.xml = _XML
-Menu.territory.saveAsPic = Als _Bild speichern
-Menu.territory.saveAsPic.error = Das Territorium konnte im angegebenen Format nicht gespeichert werden.
-Menu.territory.saveAsPic.gif = Als GIF speichern
-Menu.territory.saveAsPic.png = Als PNG speichern
-Menu.territory.saveAsPic.png.descripion = png-Bilddateien
-Menu.territory.saveAsPic.png.extension = png
-Menu.territory.size = _Gr\u00F6\u00DFe \u00E4ndern...
-Menu.tutor = Tutor
-Menu.tutor.loadRequest = Anfrage laden
-Menu.tutor.loadRequest.success = Anfrage #{0} erfolgreich geladen.
-Menu.tutor.loadRequest.warning = Es sind keine Anfrage vorhanden.
-Menu.tutor.receiveAnswer = Tutorantwort holen
-Menu.tutor.receiveAnswer.error = Es konnte keine Antwort vom Tutor geladen werden.
-Menu.tutor.receiveAnswer.information = Es ist noch keine Antwort vorhanden.
-Menu.tutor.saveAnswer = Anfrage beantworten
-Menu.tutor.saveAnswer.information = Die Bearbeitung wurde gespeichert.
-Menu.tutor.sendRequest = Tutoranfrage schicken
-Menu.tutor.sendRequest.error = Die Anfrage konnte nicht verschickt werden.
-Menu.tutor.sendRequest.information = Die Anfrage wurde verschickt.
-Menu.window = Fenster
-Menu.window.changeCursor = Angepasster Cursor
-Menu.window.darkmode = Dunkelmodus
-Menu.window.enableSounds = T\u00F6ne aktivieren
-Menu.window.info = Info
-Menu.window.info.content = Dieses Program wurde geschrieben von JayPi4c.\nDer Robbi-Simulator ist inspiriert an dem Hamster-Simulator von Dibo.
-Menu.window.info.header = Informationen zum Robbi-Simulator
-Menu.window.info.title = Information
-Menu.window.language = Sprache
-Menu.window.language.english = English
-Menu.window.language.german = Deutsch
-Menu.window.libraries = Bibliotheken
-Menu.window.libraries.content = Java Version: {0}\nJavaFX Version: {1}\nJFoenix Version: {2}\nMonacoFX Version: {3}\nDerby Version: {4}\nJAXB Version: {5}\nHibernate Version: {6}\nLog4J Version: {7}\nLombok Version: {8}
-Menu.window.libraries.header = Verwendete Bibliotheken
-Menu.window.libraries.title = Bibliotheken
-
-New.dialog.header = Neues Programm erstellen
-New.dialog.name = Name:
-New.dialog.prompt = Dateiname
-New.dialog.title = Neue Datei
-
-Open.dialog.filter = Java Dateien
-Open.dialog.title = Program \u00F6ffnen
-
-Territory.load.dialog.filter.deserial = Serialisierungsdateien
-Territory.load.dialog.filter.jaxb = JAXB-Dateien
-Territory.load.dialog.filter.xml = XML-Dateien
-Territory.load.dialog.title = Territorium laden
-Territory.load.failure = Das Laden des Territoriums ist fehlgeschlagen.
-Territory.save.dialog.filter.jaxb = JAXB-Dateien
-Territory.save.dialog.filter.serial = Serialisierungsdateien
-Territory.save.dialog.filter.xml = XML-Dateien
-Territory.save.dialog.title = Territorium speichern
-Territory.xml.error.dtd = Die dtd Datei konnte nicht geladen werden.
-
-Toolbar.action.pause = Pausiert die Simulation
-Toolbar.action.reset = Zur\u00FCcksetzten
-Toolbar.action.speed = Stelle die Simulationsgeschwindigkeit ein
-Toolbar.action.start = Starte die Simulation
-Toolbar.action.stop = Stoppt die Simulation
-Toolbar.control.compile = Kompiliere den aktuellen Code
-Toolbar.control.load = \u00D6ffne einen gespeicherten Simulator
-Toolbar.control.new = \u00D6ffne einen neuen Simulator
-Toolbar.control.save = Speichere den aktuellen Simulator
-Toolbar.robbi.move = Bewege Robbi ein Feld in Blickrichtung
-Toolbar.robbi.put = Lege den Gegenstand aus der Tasche auf der Kachel ab
-Toolbar.robbi.take = Nehme den Gegenstand von der Kachel auf
-Toolbar.robbi.turnLeft = Drehe Robbi um 90 Grad im Uhrzeigersinn
-Toolbar.territory.delete = Entferne alle Elemente von einer Kachel
-Toolbar.territory.placeAccu = Platziere einen Akku auf dem Schrottplatz
-Toolbar.territory.placeHollow = Platziere eine Kuhle auf dem Schrottplatz
-Toolbar.territory.placeNut = Platziere eine Mutter auf dem Schrottplatz
-Toolbar.territory.placePileOfScrap = Platziere einen Schrotthaufen auf dem Schrottplatz
-Toolbar.territory.placeRobbi = Platziere Robbi auf dem Schrottplatz
-Toolbar.territory.placeScrew = Platziere eine Schraube auf dem Schrottplatz
-Toolbar.territory.placeStockpile = Platziere ein Lager auf dem Schrottplatz
-Toolbar.territory.size = Konfiguriere die Gr\u00F6\u00DFe des Territoriums
-
-language.changed = Sprache ge\u00E4ndert!
-
-not.implemented = Noch nicht implementiert!
+ChangeSize.dialog.cols=Spalten:
+ChangeSize.dialog.header=Bitte wähle eine neue Größe
+ChangeSize.dialog.rows=Reihen:
+ChangeSize.dialog.title=Größe ändern
+Compilation.annotations.header=Annotationen fehlerhaft
+Compilation.annotations.msg.default=Aufgrund fehlerhafter Annotationen konnte Robbi nicht in das Territorium geladen werden.
+Compilation.annotations.msg.info="%s" ist nicht anwendbar für den Typ "%s".
+Compilation.annotations.title=Annotationenfehler
+Compilation.diagnostic=Kompilierungsfehler
+Compilation.diagnostic.CodeAndMessage=Code und Nachricht: %s: %s%n
+Compilation.diagnostic.kind=Art: %s%n
+Compilation.diagnostic.override=Robbi überschreibt nicht die main-Methode.
+Compilation.diagnostic.row=Zeile: %s%n
+Compilation.diagnostic.source=Quelle: %s%n
+Compilation.diagnostic.title=Kompilierung Fehlgeschlagen
+Compilation.success.header=Kompilierung erfolgreich
+Compilation.success.message=Dein Sketch '%s' wurde erfolgreich kompiliert.
+Compilation.success.title=Erfolg
+Editor.contextMenu.executionError=Die @Default Annotation hat einen falschen String ('%s') in der Methode '%s'.
+Editor.contextMenu.tooltip=Bitte nutze die @Default Annotation.
+Examples.duplication.header=Es existiert bereits ein Programm mit dem Namen des Beispiels.
+Examples.duplication.message=Altes Programm umbennen?\n(Das alte Programm wird sonst überschrieben.)
+Examples.duplication.title=Namenduplikat
+Examples.load.dialog.program.header=Wähle ein Programm aus.
+Examples.load.dialog.program.name=Programm
+Examples.load.dialog.program.title=Programmauswahl
+Examples.load.dialog.tags.fail=Es konnten keine Tags in der Datenbank gefunden werden.
+Examples.load.dialog.tags.header=Wähle einen Tag für ein Beispiel.
+Examples.load.dialog.tags.name=Tag
+Examples.load.dialog.tags.title=Tagauswahl
+Examples.save.tags.header=Gebe leerzeichengetrennt Tags ein.
+Examples.save.tags.name=Tags
+Examples.save.tags.prompt=Tags für das Beispiel
+Examples.save.tags.title=Tageingabe
+Exception.BagIsEmpty=Ooops! Robbi kann kein Item ablegen. Die Tasche ist leer.
+Exception.BagIsFull=Ooops! Robbi kann kein Item aufnehmen. Seine Tasche ist voll.
+Exception.HollowAhead=Ooops! Robbi kann nicht vorwärts gehen. Es ist eine Kuhle voraus.
+Exception.NoItem=Ooops! Hier liegt kein Item, welches Robbi aufheben kann.
+Exception.NoPileOfScrapAhead=Ooops! Robbi Kann keinen Schrotthaufen zum Schieben finden.
+Exception.TileBlocked=Ooops! Robbi kann diesen Schrotthaufen nicht schieben. Die folgende Kachel ist blockiert.
+Exception.TileIsFull=Ooops! Es ist schon ein Item auf der Kachel. Robbi kann hier nichts ablegen.
+Execution.information.bag=Tasche voll: {0}
+Execution.information.hollow=Kuhle voraus: {0}
+Execution.information.itemPresent=Gegenstand da: {0}
+Execution.information.pileOfScrap=Schrotthaufen voraus: {0}
+Execution.information.result=Das Ergebnis des Aufrufs ist:
+Execution.information.stockpile=Lager da: {0}
+Init.error.header=Initialisierungsfehler
+Init.error.message=Der Program Controller konnte nicht initialisiert werden.
+Init.error.title=Error
+Main.title=Robbi Simulator
+Menu.editor=_Editor
+Menu.editor.compile=_Kompilieren
+Menu.editor.format=formatieren
+Menu.editor.new=_Neu
+Menu.editor.open=_Öffnen
+Menu.editor.print=_Drucken
+Menu.editor.quit=_Beenden
+Menu.editor.save=_Speichern
+Menu.examples=Beispiele
+Menu.examples.load=Laden
+Menu.examples.save=Speichern
+Menu.robbi=_Robbi
+Menu.robbi.hollowAhead=Vorn Kuhle
+Menu.robbi.isBagFull=Ist Tasche voll
+Menu.robbi.isStockpile=Ist Lagerplatz
+Menu.robbi.itemPresent=Gegenstand da
+Menu.robbi.move=vor
+Menu.robbi.pileOfScrapAhead=Vorn Schrotthaufen
+Menu.robbi.pushPileOfScrap=Schiebe Schrotthaufen
+Menu.robbi.put=lege ab
+Menu.robbi.take=nehme auf
+Menu.robbi.turnLeft=links um
+Menu.simulation=_Simulation
+Menu.simulation.pause=Pause
+Menu.simulation.reset=Zurücksetzten
+Menu.simulation.start=Start/Fortsetzen
+Menu.simulation.stop=Stopp
+Menu.territory=_Territorium
+Menu.territory.delete=Kachel leeren
+Menu.territory.load=_Laden
+Menu.territory.load.deserialize=_Deserialisieren
+Menu.territory.load.jaxb=_JAXB
+Menu.territory.load.xml=_XML
+Menu.territory.place.accu=Akku platzieren
+Menu.territory.place.hollow=Kuhle platzieren
+Menu.territory.place.nut=Mutter platzieren
+Menu.territory.place.pileOfScrap=Schrotthaufen platzieren
+Menu.territory.place.robbi=Robbi platzieren
+Menu.territory.place.screw=Schraube platzieren
+Menu.territory.place.stockpile=Lagerplatz platzieren
+Menu.territory.print=_Drucken
+Menu.territory.print.error=Der Drucker konnte nicht initialisiert werden.
+Menu.territory.save=_Speichern
+Menu.territory.save.jaxb=_JAXB
+Menu.territory.save.serialize=_Serialisieren
+Menu.territory.save.xml=_XML
+Menu.territory.saveAsPic=Als _Bild speichern
+Menu.territory.saveAsPic.error=Das Territorium konnte im angegebenen Format nicht gespeichert werden.
+Menu.territory.saveAsPic.gif=Als GIF speichern
+Menu.territory.saveAsPic.png=Als PNG speichern
+Menu.territory.saveAsPic.png.descripion=png-Bilddateien
+Menu.territory.saveAsPic.png.extension=png
+Menu.territory.size=_Größe ändern...
+Menu.tutor=Tutor
+Menu.tutor.loadRequest=Anfrage laden
+Menu.tutor.loadRequest.success=Anfrage #{0} erfolgreich geladen.
+Menu.tutor.loadRequest.warning=Es sind keine Anfrage vorhanden.
+Menu.tutor.receiveAnswer=Tutorantwort holen
+Menu.tutor.receiveAnswer.error=Es konnte keine Antwort vom Tutor geladen werden.
+Menu.tutor.receiveAnswer.information=Es ist noch keine Antwort vorhanden.
+Menu.tutor.saveAnswer=Anfrage beantworten
+Menu.tutor.saveAnswer.information=Die Bearbeitung wurde gespeichert.
+Menu.tutor.sendRequest=Tutoranfrage schicken
+Menu.tutor.sendRequest.error=Die Anfrage konnte nicht verschickt werden.
+Menu.tutor.sendRequest.information=Die Anfrage wurde verschickt.
+Menu.window=Fenster
+Menu.window.changeCursor=Angepasster Cursor
+Menu.window.darkmode=Dunkelmodus
+Menu.window.enableSounds=Töne aktivieren
+Menu.window.info=Info
+Menu.window.info.content=Dieses Program wurde geschrieben von JayPi4c.\nDer Robbi-Simulator ist inspiriert an dem Hamster-Simulator von Dibo.
+Menu.window.info.header=Informationen zum Robbi-Simulator
+Menu.window.info.title=Information
+Menu.window.language=Sprache
+Menu.window.language.english=English
+Menu.window.language.german=Deutsch
+Menu.window.libraries=Bibliotheken
+Menu.window.libraries.content=Java Version: {0}\nJavaFX Version: {1}\nMonacoFX Version: {3}\nDerby Version: {4}\nJAXB Version: {5}\nHibernate Version: {6}\nLog4J Version: {7}\nLombok Version: {8}
+Menu.window.libraries.header=Verwendete Bibliotheken
+Menu.window.libraries.title=Bibliotheken
+New.dialog.header=Neues Programm erstellen
+New.dialog.name=Name:
+New.dialog.prompt=Dateiname
+New.dialog.title=Neue Datei
+Open.dialog.filter=Java Dateien
+Open.dialog.title=Program öffnen
+Territory.load.dialog.filter.deserial=Serialisierungsdateien
+Territory.load.dialog.filter.jaxb=JAXB-Dateien
+Territory.load.dialog.filter.xml=XML-Dateien
+Territory.load.dialog.title=Territorium laden
+Territory.load.failure=Das Laden des Territoriums ist fehlgeschlagen.
+Territory.save.dialog.filter.jaxb=JAXB-Dateien
+Territory.save.dialog.filter.serial=Serialisierungsdateien
+Territory.save.dialog.filter.xml=XML-Dateien
+Territory.save.dialog.title=Territorium speichern
+Territory.xml.error.dtd=Die dtd Datei konnte nicht geladen werden.
+Toolbar.action.pause=Pausiert die Simulation
+Toolbar.action.reset=Zurücksetzten
+Toolbar.action.speed=Stelle die Simulationsgeschwindigkeit ein
+Toolbar.action.start=Starte die Simulation
+Toolbar.action.stop=Stoppt die Simulation
+Toolbar.control.compile=Kompiliere den aktuellen Code
+Toolbar.control.load=Öffne einen gespeicherten Simulator
+Toolbar.control.new=Öffne einen neuen Simulator
+Toolbar.control.save=Speichere den aktuellen Simulator
+Toolbar.robbi.move=Bewege Robbi ein Feld in Blickrichtung
+Toolbar.robbi.put=Lege den Gegenstand aus der Tasche auf der Kachel ab
+Toolbar.robbi.take=Nehme den Gegenstand von der Kachel auf
+Toolbar.robbi.turnLeft=Drehe Robbi um 90 Grad im Uhrzeigersinn
+Toolbar.territory.delete=Entferne alle Elemente von einer Kachel
+Toolbar.territory.placeAccu=Platziere einen Akku auf dem Schrottplatz
+Toolbar.territory.placeHollow=Platziere eine Kuhle auf dem Schrottplatz
+Toolbar.territory.placeNut=Platziere eine Mutter auf dem Schrottplatz
+Toolbar.territory.placePileOfScrap=Platziere einen Schrotthaufen auf dem Schrottplatz
+Toolbar.territory.placeRobbi=Platziere Robbi auf dem Schrottplatz
+Toolbar.territory.placeScrew=Platziere eine Schraube auf dem Schrottplatz
+Toolbar.territory.placeStockpile=Platziere ein Lager auf dem Schrottplatz
+Toolbar.territory.size=Konfiguriere die Größe des Territoriums
+language.changed=Sprache geändert!
+not.implemented=Noch nicht implementiert!
+Snackbar.message.startup=Erfolgreich gestartet!
+Snackbar.message.compile.success=Kompilierung erfolgreich!
diff --git a/src/main/resources/lang/messages_en_GB.properties b/src/main/resources/lang/messages_en_GB.properties
index 053afd5..1798ae5 100644
--- a/src/main/resources/lang/messages_en_GB.properties
+++ b/src/main/resources/lang/messages_en_GB.properties
@@ -1,188 +1,175 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
-
-ChangeSize.dialog.cols = Cols:
-ChangeSize.dialog.header = please choose new dimension
-ChangeSize.dialog.rows = Rows:
-ChangeSize.dialog.title = Change size
-
-Compilation.annotations.header = Annotations faulty
-Compilation.annotations.msg.default = Because of faulty Annotations Robbi could not be loaded into the territory.
-Compilation.annotations.msg.info = "%s" is not applicable for the type "%s".
-Compilation.annotations.title = Annotations error
-Compilation.diagnostic = Compilation Error
-Compilation.diagnostic.CodeAndMessage = Code and message: %s: %s%n
-Compilation.diagnostic.kind = Kind: %s%n
-Compilation.diagnostic.override = Robbi does not override the main-method.
-Compilation.diagnostic.row = Row: %s%n
-Compilation.diagnostic.source = Source: %s%n
-Compilation.diagnostic.title = Compilation Error
-Compilation.success.header = Compilation successful
-Compilation.success.message = Your sketch '%s' has been compiled successfully.
-Compilation.success.title = Success
-
-Editor.contextMenu.executionError = The @Default annotation uses a wrong String ('%s') in the method '%s'.
-Editor.contextMenu.tooltip = Please use the @Default annotation.
-
-Examples.duplication.header = There is another program with the examples name.
-Examples.duplication.message = Rename old program?\n(Otherwise the old program will be overwritten.)
-Examples.duplication.title = Name duplication
-Examples.load.dialog.program.header = Choose a program.
-Examples.load.dialog.program.name = Program
-Examples.load.dialog.program.title = Programselection
-Examples.load.dialog.tags.fail = No tags could be found in the database.
-Examples.load.dialog.tags.header = Choose a tag for an example.
-Examples.load.dialog.tags.name = Tag
-Examples.load.dialog.tags.title = Tagselection
-Examples.save.tags.header = Type in space-separated tags.
-Examples.save.tags.name = Tags
-Examples.save.tags.prompt = Tags for the example
-Examples.save.tags.title = Taginput
-
-Exception.BagIsEmpty = Ooops! Robbi can't place its item. The bag is empty.
-Exception.BagIsFull = Ooops! Robbi can't pick up an item. His bag is full.
-Exception.HollowAhead = Ooops! Robbi can't move forward. There is a hollow ahead.
-Exception.NoItem = Ooops! There is no item, robbi could pick up.
-Exception.NoPileOfScrapAhead = Ooops! Robbi can't find a pile to push.
-Exception.TileBlocked = Ooops! Robbi can't push this pile of scrap. The next tile is blocked.
-Exception.TileIsFull = Ooops! There is already an item on the tile. Robbi can't place anything here.
-
-Execution.information.bag = bag full: {0}
-Execution.information.hollow = Hollow ahead: {0}
-Execution.information.itemPresent = Item present: {0}
-Execution.information.pileOfScrap = Pile of scrap ahead: {0}
-Execution.information.result = The call's result is:
-Execution.information.stockpile = Is stockpile: {0}
-
-Init.error.header = Initialization error
-Init.error.message = Could not initialize Program Controller.
-Init.error.title = Error
-
-Main.title = Robbi Simulator
-
-Menu.editor = _Editor
-Menu.editor.compile = _Compile
-Menu.editor.format = format
-Menu.editor.new = _New
-Menu.editor.open = _Open
-Menu.editor.print = _Print
-Menu.editor.quit = _Quit
-Menu.editor.save = _Save
-Menu.examples = Examples
-Menu.examples.load = Load
-Menu.examples.save = Save
-Menu.robbi = _Robbi
-Menu.robbi.hollowAhead = hollow ahead
-Menu.robbi.isBagFull = is Bag full
-Menu.robbi.isStockpile = is stockpile
-Menu.robbi.itemPresent = item present
-Menu.robbi.move = move
-Menu.robbi.pileOfScrapAhead = Pile of scrap ahead
-Menu.robbi.pushPileOfScrap = push pile of scrap
-Menu.robbi.put = put
-Menu.robbi.take = take
-Menu.robbi.turnLeft = turn left
-Menu.simulation = _Simulation
-Menu.simulation.pause = Pause
-Menu.simulation.reset = Reset
-Menu.simulation.start = Start/Continue
-Menu.simulation.stop = Stop
-Menu.territory = _Territory
-Menu.territory.delete = clear tile
-Menu.territory.load = _Load
-Menu.territory.load.deserialize = _Deserialize
-Menu.territory.load.jaxb = _JAXB
-Menu.territory.load.xml = _XML
-Menu.territory.place.accu = Place accu
-Menu.territory.place.hollow = place Hollow
-Menu.territory.place.nut = place nut
-Menu.territory.place.pileOfScrap = Place pile of scrap
-Menu.territory.place.robbi = Place robbi
-Menu.territory.place.screw = Place screw
-Menu.territory.place.stockpile = Place Stockpile
-Menu.territory.print = _Print
-Menu.territory.print.error = Could no initialize printer.
-Menu.territory.save = _Save
-Menu.territory.save.jaxb = _JAXB
-Menu.territory.save.serialize = _Serialize
-Menu.territory.save.xml = _XML
-Menu.territory.saveAsPic = Save as Pi_cture
-Menu.territory.saveAsPic.error = Could not save the territory in the given format.
-Menu.territory.saveAsPic.gif = Save as GIF
-Menu.territory.saveAsPic.png = Save as PNG
-Menu.territory.saveAsPic.png.descripion = png-Imagefiles
-Menu.territory.saveAsPic.png.extension = png
-Menu.territory.size = change si_ze
-Menu.tutor = Tutor\n
-Menu.tutor.loadRequest = Load request
-Menu.tutor.loadRequest.success = Request #{0} successfully loaded.
-Menu.tutor.loadRequest.warning = There are no requests available.
-Menu.tutor.receiveAnswer = Fetch tutor-answer
-Menu.tutor.receiveAnswer.error = Failed to fetch an answer from the tutor.
-Menu.tutor.receiveAnswer.information = There is no answer yet.
-Menu.tutor.saveAnswer = Answer request.
-Menu.tutor.saveAnswer.information = The editing has been saved.
-Menu.tutor.sendRequest = Send tutor-request
-Menu.tutor.sendRequest.error = Failed to send the request.
-Menu.tutor.sendRequest.information = The request has been sent.
-Menu.window = Window
-Menu.window.changeCursor = Custom Cursor
-Menu.window.darkmode = Darkmode
-Menu.window.enableSounds = enable sounds
-Menu.window.info = Info
-Menu.window.info.content = This program was written by JayPi4c.\nThe Robbi-Simulator is inspired by the Hamster-Simulator by Dibo.
-Menu.window.info.header = Information for Robbi-Simulator
-Menu.window.info.title = Information
-Menu.window.language = Language
-Menu.window.language.english = English
-Menu.window.language.german = Deutsch
-Menu.window.libraries = Libraries
-Menu.window.libraries.content = Java Version: {0}\nJavaFX Version: {1}\nJFoenix Version: {2}\nMonacoFX Version: {3}\nDerby Version: {4}\nJAXB Version: {5}\nHibernate Version: {6}\nLog4J Version: {7}\nLombok Version: {8}
-Menu.window.libraries.header = Used libraries
-Menu.window.libraries.title = Libraries
-
-New.dialog.header = Create new Program
-New.dialog.name = Name:
-New.dialog.prompt = filename
-New.dialog.title = New file
-
-Open.dialog.filter = Java Files
-Open.dialog.title = Open Program
-
-Territory.load.dialog.filter = Serializationfiles
-Territory.load.dialog.filter.deserial = Serializationfiles
-Territory.load.dialog.filter.jaxb = JAXB-Files
-Territory.load.dialog.filter.xml = XML-Files
-Territory.load.dialog.title = Load territory
-Territory.load.failure = Failed to load territory.
-Territory.save.dialog.filter.jaxb = JAXB-Files
-Territory.save.dialog.filter.serial = Serializationfiles
-Territory.save.dialog.filter.xml = XML-Files
-Territory.save.dialog.title = Save territory
-Territory.xml.error.dtd = Could not laod the dtd-file.
-
-Toolbar.action.pause = pause the simulation
-Toolbar.action.reset = Reset
-Toolbar.action.speed = adjust speed of simulation
-Toolbar.action.start = start the simulation
-Toolbar.action.stop = stop the simulation
-Toolbar.control.compile = compile the current code
-Toolbar.control.load = load a saved simulator
-Toolbar.control.new = load a new simulator
-Toolbar.control.save = save the current simulator
-Toolbar.robbi.move = Move Robbi one tile forward in the direction of view
-Toolbar.robbi.put = Place the item from the bag in the tile
-Toolbar.robbi.take = Take the item from the tile
-Toolbar.robbi.turnLeft = Rotate Robbi 90 degrees clockwise
-Toolbar.territory.delete = Remove all elements from a tile
-Toolbar.territory.placeAccu = Place a bettery in the junkyard
-Toolbar.territory.placeHollow = Place a hollow in the junkyard
-Toolbar.territory.placeNut = Place a nut in the junkyard
-Toolbar.territory.placePileOfScrap = Place a pile of Scrap in the junkyard
-Toolbar.territory.placeRobbi = Place Robbi in the junkyard
-Toolbar.territory.placeScrew = Place a screw in the junkyard
-Toolbar.territory.placeStockpile = Place a stockpile in the junkyard
-Toolbar.territory.size = configure the size of the territory
-
-language.changed = Langauge changed!
-
-not.implemented = Not yet implemented!
+ChangeSize.dialog.cols=Cols:
+ChangeSize.dialog.header=please choose new dimension
+ChangeSize.dialog.rows=Rows:
+ChangeSize.dialog.title=Change size
+Compilation.annotations.header=Annotations faulty
+Compilation.annotations.msg.default=Because of faulty Annotations Robbi could not be loaded into the territory.
+Compilation.annotations.msg.info="%s" is not applicable for the type "%s".
+Compilation.annotations.title=Annotations error
+Compilation.diagnostic=Compilation Error
+Compilation.diagnostic.CodeAndMessage=Code and message: %s: %s%n
+Compilation.diagnostic.kind=Kind: %s%n
+Compilation.diagnostic.override=Robbi does not override the main-method.
+Compilation.diagnostic.row=Row: %s%n
+Compilation.diagnostic.source=Source: %s%n
+Compilation.diagnostic.title=Compilation Error
+Compilation.success.header=Compilation successful
+Compilation.success.message=Your sketch '%s' has been compiled successfully.
+Compilation.success.title=Success
+Editor.contextMenu.executionError=The @Default annotation uses a wrong String ('%s') in the method '%s'.
+Editor.contextMenu.tooltip=Please use the @Default annotation.
+Examples.duplication.header=There is another program with the examples name.
+Examples.duplication.message=Rename old program?\n(Otherwise the old program will be overwritten.)
+Examples.duplication.title=Name duplication
+Examples.load.dialog.program.header=Choose a program.
+Examples.load.dialog.program.name=Program
+Examples.load.dialog.program.title=Programselection
+Examples.load.dialog.tags.fail=No tags could be found in the database.
+Examples.load.dialog.tags.header=Choose a tag for an example.
+Examples.load.dialog.tags.name=Tag
+Examples.load.dialog.tags.title=Tagselection
+Examples.save.tags.header=Type in space-separated tags.
+Examples.save.tags.name=Tags
+Examples.save.tags.prompt=Tags for the example
+Examples.save.tags.title=Taginput
+Exception.BagIsEmpty=Ooops! Robbi can't place its item. The bag is empty.
+Exception.BagIsFull=Ooops! Robbi can't pick up an item. His bag is full.
+Exception.HollowAhead=Ooops! Robbi can't move forward. There is a hollow ahead.
+Exception.NoItem=Ooops! There is no item, robbi could pick up.
+Exception.NoPileOfScrapAhead=Ooops! Robbi can't find a pile to push.
+Exception.TileBlocked=Ooops! Robbi can't push this pile of scrap. The next tile is blocked.
+Exception.TileIsFull=Ooops! There is already an item on the tile. Robbi can't place anything here.
+Execution.information.bag=bag full: {0}
+Execution.information.hollow=Hollow ahead: {0}
+Execution.information.itemPresent=Item present: {0}
+Execution.information.pileOfScrap=Pile of scrap ahead: {0}
+Execution.information.result=The call's result is:
+Execution.information.stockpile=Is stockpile: {0}
+Init.error.header=Initialization error
+Init.error.message=Could not initialize Program Controller.
+Init.error.title=Error
+Main.title=Robbi Simulator
+Menu.editor=_Editor
+Menu.editor.compile=_Compile
+Menu.editor.format=format
+Menu.editor.new=_New
+Menu.editor.open=_Open
+Menu.editor.print=_Print
+Menu.editor.quit=_Quit
+Menu.editor.save=_Save
+Menu.examples=Examples
+Menu.examples.load=Load
+Menu.examples.save=Save
+Menu.robbi=_Robbi
+Menu.robbi.hollowAhead=hollow ahead
+Menu.robbi.isBagFull=is Bag full
+Menu.robbi.isStockpile=is stockpile
+Menu.robbi.itemPresent=item present
+Menu.robbi.move=move
+Menu.robbi.pileOfScrapAhead=Pile of scrap ahead
+Menu.robbi.pushPileOfScrap=push pile of scrap
+Menu.robbi.put=put
+Menu.robbi.take=take
+Menu.robbi.turnLeft=turn left
+Menu.simulation=_Simulation
+Menu.simulation.pause=Pause
+Menu.simulation.reset=Reset
+Menu.simulation.start=Start/Continue
+Menu.simulation.stop=Stop
+Menu.territory=_Territory
+Menu.territory.delete=clear tile
+Menu.territory.load=_Load
+Menu.territory.load.deserialize=_Deserialize
+Menu.territory.load.jaxb=_JAXB
+Menu.territory.load.xml=_XML
+Menu.territory.place.accu=Place accu
+Menu.territory.place.hollow=place Hollow
+Menu.territory.place.nut=place nut
+Menu.territory.place.pileOfScrap=Place pile of scrap
+Menu.territory.place.robbi=Place robbi
+Menu.territory.place.screw=Place screw
+Menu.territory.place.stockpile=Place Stockpile
+Menu.territory.print=_Print
+Menu.territory.print.error=Could no initialize printer.
+Menu.territory.save=_Save
+Menu.territory.save.jaxb=_JAXB
+Menu.territory.save.serialize=_Serialize
+Menu.territory.save.xml=_XML
+Menu.territory.saveAsPic=Save as Pi_cture
+Menu.territory.saveAsPic.error=Could not save the territory in the given format.
+Menu.territory.saveAsPic.gif=Save as GIF
+Menu.territory.saveAsPic.png=Save as PNG
+Menu.territory.saveAsPic.png.descripion=png-Imagefiles
+Menu.territory.saveAsPic.png.extension=png
+Menu.territory.size=change si_ze
+Menu.tutor=Tutor\n
+Menu.tutor.loadRequest=Load request
+Menu.tutor.loadRequest.success=Request #{0} successfully loaded.
+Menu.tutor.loadRequest.warning=There are no requests available.
+Menu.tutor.receiveAnswer=Fetch tutor-answer
+Menu.tutor.receiveAnswer.error=Failed to fetch an answer from the tutor.
+Menu.tutor.receiveAnswer.information=There is no answer yet.
+Menu.tutor.saveAnswer=Answer request.
+Menu.tutor.saveAnswer.information=The editing has been saved.
+Menu.tutor.sendRequest=Send tutor-request
+Menu.tutor.sendRequest.error=Failed to send the request.
+Menu.tutor.sendRequest.information=The request has been sent.
+Menu.window=Window
+Menu.window.changeCursor=Custom Cursor
+Menu.window.darkmode=Darkmode
+Menu.window.enableSounds=enable sounds
+Menu.window.info=Info
+Menu.window.info.content=This program was written by JayPi4c.\nThe Robbi-Simulator is inspired by the Hamster-Simulator by Dibo.
+Menu.window.info.header=Information for Robbi-Simulator
+Menu.window.info.title=Information
+Menu.window.language=Language
+Menu.window.language.english=English
+Menu.window.language.german=Deutsch
+Menu.window.libraries=Libraries
+Menu.window.libraries.content=Java Version: {0}\nJavaFX Version: {1}\nMonacoFX Version: {3}\nDerby Version: {4}\nJAXB Version: {5}\nHibernate Version: {6}\nLog4J Version: {7}\nLombok Version: {8}
+Menu.window.libraries.header=Used libraries
+Menu.window.libraries.title=Libraries
+New.dialog.header=Create new Program
+New.dialog.name=Name:
+New.dialog.prompt=filename
+New.dialog.title=New file
+Open.dialog.filter=Java Files
+Open.dialog.title=Open Program
+Territory.load.dialog.filter=Serializationfiles
+Territory.load.dialog.filter.deserial=Serializationfiles
+Territory.load.dialog.filter.jaxb=JAXB-Files
+Territory.load.dialog.filter.xml=XML-Files
+Territory.load.dialog.title=Load territory
+Territory.load.failure=Failed to load territory.
+Territory.save.dialog.filter.jaxb=JAXB-Files
+Territory.save.dialog.filter.serial=Serializationfiles
+Territory.save.dialog.filter.xml=XML-Files
+Territory.save.dialog.title=Save territory
+Territory.xml.error.dtd=Could not laod the dtd-file.
+Toolbar.action.pause=pause the simulation
+Toolbar.action.reset=Reset
+Toolbar.action.speed=adjust speed of simulation
+Toolbar.action.start=start the simulation
+Toolbar.action.stop=stop the simulation
+Toolbar.control.compile=compile the current code
+Toolbar.control.load=load a saved simulator
+Toolbar.control.new=load a new simulator
+Toolbar.control.save=save the current simulator
+Toolbar.robbi.move=Move Robbi one tile forward in the direction of view
+Toolbar.robbi.put=Place the item from the bag in the tile
+Toolbar.robbi.take=Take the item from the tile
+Toolbar.robbi.turnLeft=Rotate Robbi 90 degrees clockwise
+Toolbar.territory.delete=Remove all elements from a tile
+Toolbar.territory.placeAccu=Place a bettery in the junkyard
+Toolbar.territory.placeHollow=Place a hollow in the junkyard
+Toolbar.territory.placeNut=Place a nut in the junkyard
+Toolbar.territory.placePileOfScrap=Place a pile of Scrap in the junkyard
+Toolbar.territory.placeRobbi=Place Robbi in the junkyard
+Toolbar.territory.placeScrew=Place a screw in the junkyard
+Toolbar.territory.placeStockpile=Place a stockpile in the junkyard
+Toolbar.territory.size=configure the size of the territory
+language.changed=Langauge changed!
+not.implemented=Not yet implemented!
+Snackbar.message.startup=Started successfully!
+Snackbar.message.compile.success=Compilation