From e4f6b42ae4d5b75f6d781810d1912ad72e7492d6 Mon Sep 17 00:00:00 2001 From: MatiPl01 Date: Tue, 28 Dec 2021 15:22:33 +0100 Subject: [PATCH] Finished GUI controls --- .../AbstractContainerController.java | 176 +++++++++++++++-- .../controllers/ContainerLeftController.java | 56 +++++- .../controllers/ContainerRightController.java | 51 ++++- .../gui/controllers/MainController.java | 9 +- .../enums/SimulationState.java | 2 +- .../gui/enums/TrackingButtonState.java | 7 + .../simulation/grid/AbstractGridBuilder.java | 21 +- .../simulation/grid/FencedMapGridBuilder.java | 1 + .../grid/FoldingMapGridBuilder.java | 1 + .../project/gui/simulation/grid/IBuilder.java | 3 + .../simulation/sprites/GuiAnimalSprite.java | 13 +- .../visualization/SimulationVisualizer.java | 79 ++------ .../my/project/simulation/engine/IEngine.java | 2 +- .../simulation/engine/SimulationEngine.java | 14 +- .../project/simulation/maps/AbstractMap.java | 44 ++++- .../my/project/simulation/maps/FencedMap.java | 2 +- .../project/simulation/maps/FoldingMap.java | 2 +- .../java/my/project/simulation/maps/IMap.java | 13 +- .../simulation/sprites/AbstractSprite.java | 11 ++ .../my/project/simulation/sprites/Animal.java | 13 +- .../my/project/simulation/sprites/Bush.java | 2 +- .../my/project/simulation/sprites/Grass.java | 2 +- .../project/simulation/sprites/ISprite.java | 2 + .../project/simulation/stats/StatsMeter.java | 49 ++++- .../simulation/utils/AnimalTracker.java | 43 +++-- src/main/resources/css/style.css | 4 +- src/main/resources/fxml/ContainerLeft.fxml | 172 ++++++++++++----- src/main/resources/fxml/ContainerRight.fxml | 180 +++++++++++++----- 28 files changed, 709 insertions(+), 265 deletions(-) rename src/main/java/my/project/{simulation => gui}/enums/SimulationState.java (65%) create mode 100644 src/main/java/my/project/gui/enums/TrackingButtonState.java diff --git a/src/main/java/my/project/gui/controllers/AbstractContainerController.java b/src/main/java/my/project/gui/controllers/AbstractContainerController.java index 121b249..82e1664 100644 --- a/src/main/java/my/project/gui/controllers/AbstractContainerController.java +++ b/src/main/java/my/project/gui/controllers/AbstractContainerController.java @@ -5,27 +5,50 @@ import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.VBox; import my.project.gui.charts.ChartDrawer; +import my.project.gui.enums.TrackingButtonState; import my.project.gui.simulation.visualization.SimulationVisualizer; import my.project.simulation.engine.IEngine; import my.project.simulation.engine.SimulationEngine; -import my.project.simulation.enums.SimulationState; +import my.project.gui.enums.SimulationState; +import my.project.simulation.maps.AbstractMap; import my.project.simulation.maps.IMap; +import my.project.simulation.sprites.Animal; +import my.project.simulation.stats.StatsMeter; +import my.project.simulation.utils.AnimalTracker; +import my.project.simulation.utils.Vector2D; -import java.util.concurrent.atomic.AtomicReference; +import java.util.Set; +import java.util.stream.Collectors; public class AbstractContainerController { private static final int DEFAULT_REFRESH_INTERVAL = 300; // ms private static final int MIN_REFRESH_INTERVAL = 1; // ms private static final int MAX_REFRESH_INTERVAL = 1000; // ms - private AnchorPane simulationBox; - private AnchorPane chartBox; private Slider refreshSlider; private Label refreshLabel; protected Side legendSide; + private Button pauseButton; + private Button trackButton; + private Button dominantGenomesButton; + private AnchorPane simulationBox; + private AnchorPane chartBox; + private VBox dominantGenomesBox; + private VBox trackedAnimalBox; + private Label trackedAnimalID; + private Label trackedAnimalChildren; + private Label trackedAnimalDescendants; + private Label trackedAnimalDeath; + private IMap map; private IEngine engine; + private SimulationVisualizer simulationVisualizer; + + private boolean isShowingDominantGenomesAnimals = false; + private boolean isShowingAnimalsPicker = false; + private TrackingButtonState trackingButtonState = TrackingButtonState.CHOOSE; public void setSimulationBox(AnchorPane simulationBox) { this.simulationBox = simulationBox; @@ -35,6 +58,10 @@ public void setChartBox(AnchorPane chartBox) { this.chartBox = chartBox; } + public void setPauseButton(Button pauseButton) { + this.pauseButton = pauseButton; + } + public void setRefreshSlider(Slider refreshSlider) { this.refreshSlider = refreshSlider; } @@ -43,23 +70,42 @@ public void setRefreshLabel(Label refreshLabel) { this.refreshLabel = refreshLabel; } + public void setDominantGenomesBox(VBox dominantGenomesBox) { + this.dominantGenomesBox = dominantGenomesBox; + } + + public void setTrackButton(Button trackButton) { + this.trackButton = trackButton; + } + + public void setDominantGenomesButton(Button dominantGenomesButton) { + this.dominantGenomesButton = dominantGenomesButton; + } + + public void setTrackedAnimalBoxes(VBox trackedAnimalBox, + Label trackedAnimalID, + Label trackedAnimalChildren, + Label trackedAnimalDescendants, + Label trackedAnimalDeath) { + this.trackedAnimalBox = trackedAnimalBox; + this.trackedAnimalID = trackedAnimalID; + this.trackedAnimalChildren = trackedAnimalChildren; + this.trackedAnimalDescendants = trackedAnimalDescendants; + this.trackedAnimalDeath = trackedAnimalDeath; + } + public void launch(IMap map) { - map.setChartDrawer(new ChartDrawer(this.chartBox, null, "Day", "Count", legendSide)); - SimulationVisualizer simulationVisualizer = new SimulationVisualizer(map, simulationBox); - this.engine = new SimulationEngine(map, simulationVisualizer); - Thread engineThread = new Thread((Runnable) this.engine); + this.map = map; + StatsMeter statsMeter = map.getStatsMeter(); + statsMeter.setChartDrawer(new ChartDrawer(chartBox, null, "Day", "Count", legendSide)); + statsMeter.setDominantGenomesBox(dominantGenomesBox); + simulationVisualizer = new SimulationVisualizer(map, simulationBox); + engine = new SimulationEngine(map, simulationVisualizer); + Thread engineThread = new Thread((Runnable) engine); setupRefreshInterval(); engineThread.start(); - } - - protected void pauseButtonClicked(Button pauseButton) { - if (engine.getState() == SimulationState.PAUSED) { - engine.start(); - pauseButton.setText("Pause"); - } else { - engine.pause(); - pauseButton.setText("Start"); - } + map.getGridBuilder().setEventsController(this); + System.out.println(map.getGridBuilder()); } private void setupRefreshInterval() { @@ -67,13 +113,103 @@ private void setupRefreshInterval() { / (MAX_REFRESH_INTERVAL - MIN_REFRESH_INTERVAL); refreshSlider.setValue(100. * (1 - ratio)); refreshLabel.setText(String.valueOf(DEFAULT_REFRESH_INTERVAL)); - this.engine.setRefreshInterval(DEFAULT_REFRESH_INTERVAL); + engine.setRefreshInterval(DEFAULT_REFRESH_INTERVAL); refreshSlider.valueProperty().addListener((observable, oldValue, newValue) -> { int refreshInterval = (int) ((1 - refreshSlider.getValue() / 100) * (MAX_REFRESH_INTERVAL - MIN_REFRESH_INTERVAL) + MIN_REFRESH_INTERVAL); refreshLabel.setText(String.valueOf(refreshInterval)); - this.engine.setRefreshInterval(refreshInterval); + engine.setRefreshInterval(refreshInterval); }); } + + protected void pauseButtonClicked() { + if (engine.getState() == SimulationState.PAUSED) { + engine.start(); + pauseButton.setText("Pause"); + dominantGenomesButton.setDisable(true); + trackButton.setDisable(true); + } else { + engine.pause(); + pauseButton.setText("Start"); + dominantGenomesButton.setDisable(false); + trackButton.setDisable(false); + } + } + + protected void dominantButtonClicked() { + if (isShowingDominantGenomesAnimals) { + simulationVisualizer.hideDominantGenomesAnimals(); + dominantGenomesButton.setText("Show"); + trackButton.setDisable(false); + pauseButton.setDisable(false); + } else { + simulationVisualizer.showDominantGenomesAnimals(); + dominantGenomesButton.setText("Hide"); + trackButton.setDisable(true); + pauseButton.setDisable(true); + } + isShowingDominantGenomesAnimals = !isShowingDominantGenomesAnimals; + } + + protected void trackButtonClicked() { + System.out.println("State " + trackingButtonState); + switch (trackingButtonState) { + case CHOOSE -> { + enableAnimalPicker(); + pauseButton.setDisable(true); + dominantGenomesButton.setDisable(true); + trackButton.setText("Cancel"); + trackingButtonState = TrackingButtonState.CANCEL; + } + case CANCEL -> { + disableAnimalsPicker(); + pauseButton.setDisable(false); + dominantGenomesButton.setDisable(false); + trackButton.setText("Choose"); + trackingButtonState = TrackingButtonState.CHOOSE; + } + case STOP -> { + map.removeAnimalTracker(); + trackButton.setText("Choose"); + trackingButtonState = TrackingButtonState.CHOOSE; + } + } + } + + private void enableAnimalPicker() { + isShowingAnimalsPicker = true; + Set maxEnergyAnimals = map.getMaxEnergyFieldAnimals(); + simulationVisualizer.bringAnimalsToTop(maxEnergyAnimals); + simulationVisualizer.showAnimalsIDs(map.getMaxEnergyFieldAnimals()); + } + + private void disableAnimalsPicker() { + isShowingAnimalsPicker = false; + simulationVisualizer.hideAnimalsIDs(map.getMaxEnergyFieldAnimals()); + } + + private void setAnimalTracker(Animal animal) { + map.setAnimalTracker(new AnimalTracker(animal, trackedAnimalID, + trackedAnimalChildren, + trackedAnimalDescendants, + trackedAnimalDeath)); + } + + public void notifyClick(Vector2D position) { + if (trackingButtonState == TrackingButtonState.CANCEL) { + Animal animal = map.getMaxEnergyFieldAnimal(position); + if (animal == null) return; + setAnimalTracker(animal); + disableAnimalsPicker(); + pauseButton.setDisable(false); + dominantGenomesButton.setDisable(false); + trackingButtonState = TrackingButtonState.STOP; + trackButton.setText("Stop"); + } + } + + protected void saveStatsFile() { + map.getStatsMeter().generateCSVFile(); + } } diff --git a/src/main/java/my/project/gui/controllers/ContainerLeftController.java b/src/main/java/my/project/gui/controllers/ContainerLeftController.java index d39c9b5..acc4ca9 100644 --- a/src/main/java/my/project/gui/controllers/ContainerLeftController.java +++ b/src/main/java/my/project/gui/controllers/ContainerLeftController.java @@ -5,14 +5,19 @@ import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Slider; +import javafx.scene.control.TitledPane; import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.VBox; public class ContainerLeftController extends AbstractContainerController { @FXML - private AnchorPane simulationBox; + protected AnchorPane simulationBox; @FXML - private AnchorPane chartBox; + protected AnchorPane chartBox; + + @FXML + private VBox dominantGenomesBox; @FXML private Slider refreshSlider; @@ -23,17 +28,62 @@ public class ContainerLeftController extends AbstractContainerController { @FXML private Label refreshLabel; + @FXML + private Button dominantGenomesButton; + + @FXML + private Button trackButton; + + @FXML + private VBox trackedAnimalBox; + + @FXML + private Label trackedAnimalID; + + @FXML + private Label trackedAnimalChildren; + + @FXML + private Label trackedAnimalDescendants; + + @FXML + private Label trackedAnimalDeath; + @FXML private void initialize() { this.legendSide = Side.LEFT; setSimulationBox(simulationBox); setChartBox(chartBox); + setPauseButton(pauseButton); setRefreshSlider(refreshSlider); setRefreshLabel(refreshLabel); + setDominantGenomesBox(dominantGenomesBox); + setDominantGenomesButton(dominantGenomesButton); + setTrackButton(trackButton); + setTrackedAnimalBoxes(trackedAnimalBox, + trackedAnimalID, + trackedAnimalChildren, + trackedAnimalDescendants, + trackedAnimalDeath); } @FXML private void onPause() { - pauseButtonClicked(pauseButton); + pauseButtonClicked(); + } + + @FXML + private void onDominantShow() { + dominantButtonClicked(); + } + + @FXML + private void onTrackChoose() { + trackButtonClicked(); + } + + @FXML + private void onStatsFileSave() { + saveStatsFile(); } } diff --git a/src/main/java/my/project/gui/controllers/ContainerRightController.java b/src/main/java/my/project/gui/controllers/ContainerRightController.java index dc661b8..8656105 100644 --- a/src/main/java/my/project/gui/controllers/ContainerRightController.java +++ b/src/main/java/my/project/gui/controllers/ContainerRightController.java @@ -6,6 +6,7 @@ import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.VBox; public class ContainerRightController extends AbstractContainerController { @FXML @@ -14,6 +15,9 @@ public class ContainerRightController extends AbstractContainerController { @FXML protected AnchorPane chartBox; + @FXML + private VBox dominantGenomesBox; + @FXML private Slider refreshSlider; @@ -23,17 +27,62 @@ public class ContainerRightController extends AbstractContainerController { @FXML private Label refreshLabel; + @FXML + private Button dominantGenomesButton; + + @FXML + private Button trackButton; + + @FXML + private VBox trackedAnimalBox; + + @FXML + private Label trackedAnimalID; + + @FXML + private Label trackedAnimalChildren; + + @FXML + private Label trackedAnimalDescendants; + + @FXML + private Label trackedAnimalDeath; + @FXML private void initialize() { this.legendSide = Side.RIGHT; setSimulationBox(simulationBox); setChartBox(chartBox); + setPauseButton(pauseButton); setRefreshSlider(refreshSlider); setRefreshLabel(refreshLabel); + setDominantGenomesBox(dominantGenomesBox); + setDominantGenomesButton(dominantGenomesButton); + setTrackButton(trackButton); + setTrackedAnimalBoxes(trackedAnimalBox, + trackedAnimalID, + trackedAnimalChildren, + trackedAnimalDescendants, + trackedAnimalDeath); } @FXML private void onPause() { - pauseButtonClicked(pauseButton); + pauseButtonClicked(); + } + + @FXML + private void onDominantShow() { + dominantButtonClicked(); + } + + @FXML + private void onTrackChoose() { + trackButtonClicked(); + } + + @FXML + private void onStatsFileSave() { + saveStatsFile(); } } diff --git a/src/main/java/my/project/gui/controllers/MainController.java b/src/main/java/my/project/gui/controllers/MainController.java index ba8c2fe..dc7e12a 100644 --- a/src/main/java/my/project/gui/controllers/MainController.java +++ b/src/main/java/my/project/gui/controllers/MainController.java @@ -1,7 +1,6 @@ package my.project.gui.controllers; import javafx.fxml.FXML; -import javafx.scene.layout.AnchorPane; import my.project.simulation.enums.MapStrategy; import my.project.simulation.maps.FencedMap; import my.project.simulation.maps.FoldingMap; @@ -17,8 +16,12 @@ public class MainController { @FXML private void initialize() { System.out.println("IN INIT"); - IMap foldingMap = new FoldingMap(30, 20, .5, 100, - 5, 500, 50, 50); +// IMap foldingMap = new FoldingMap(30, 20, .5, 100, +// 5, 500, 50, 50); +// foldingMap.setStrategy(MapStrategy.MAGIC); + + IMap foldingMap = new FoldingMap(2, 2, 1, 5, 5, 5, + 3, 2); foldingMap.setStrategy(MapStrategy.MAGIC); IMap fencedMap = new FencedMap(10, 10, .5, 100, diff --git a/src/main/java/my/project/simulation/enums/SimulationState.java b/src/main/java/my/project/gui/enums/SimulationState.java similarity index 65% rename from src/main/java/my/project/simulation/enums/SimulationState.java rename to src/main/java/my/project/gui/enums/SimulationState.java index 2fcd46f..286ca06 100644 --- a/src/main/java/my/project/simulation/enums/SimulationState.java +++ b/src/main/java/my/project/gui/enums/SimulationState.java @@ -1,4 +1,4 @@ -package my.project.simulation.enums; +package my.project.gui.enums; public enum SimulationState { RUNNING, diff --git a/src/main/java/my/project/gui/enums/TrackingButtonState.java b/src/main/java/my/project/gui/enums/TrackingButtonState.java new file mode 100644 index 0000000..e2caa3b --- /dev/null +++ b/src/main/java/my/project/gui/enums/TrackingButtonState.java @@ -0,0 +1,7 @@ +package my.project.gui.enums; + +public enum TrackingButtonState { + CHOOSE, + CANCEL, + STOP +} diff --git a/src/main/java/my/project/gui/simulation/grid/AbstractGridBuilder.java b/src/main/java/my/project/gui/simulation/grid/AbstractGridBuilder.java index 0a123d0..32dc903 100644 --- a/src/main/java/my/project/gui/simulation/grid/AbstractGridBuilder.java +++ b/src/main/java/my/project/gui/simulation/grid/AbstractGridBuilder.java @@ -9,6 +9,7 @@ import javafx.scene.layout.*; import javafx.scene.text.Font; import my.project.gui.components.ZoomableScrollPane; +import my.project.gui.controllers.AbstractContainerController; import my.project.gui.simulation.sprites.IGuiSprite; import my.project.simulation.maps.IMap; import my.project.simulation.sprites.AbstractPlant; @@ -35,8 +36,10 @@ public abstract class AbstractGridBuilder implements IBuilder { protected final List> spritesGridHelper = new ArrayList<>(); protected final GridPane wrapperGrid = new GridPane(); protected final GridPane spritesGrid = new GridPane(); + protected final GridPane linesGrid = new GridPane(); protected final StackPane backgroundPane = new StackPane(); protected final AnchorPane parentContainer; + protected AbstractContainerController controller; protected int gridWidth; protected int gridHeight; @@ -68,8 +71,8 @@ public int getCellSize() { @Override public void initialize() { setupSpritesGrid(); + setupLinesGrid(); buildGrid(); - displayGridLines(spritesGrid); } @Override @@ -86,10 +89,19 @@ private void setupSpritesGrid() { StackPane stackPane = new StackPane(); spritesGridHelper.get(x).add(stackPane); spritesGrid.add(stackPane, x, mapHeight - y - 1, 1, 1); + + // Add an event handler + Vector2D position = new Vector2D(x, y); + stackPane.setOnMouseClicked(event -> this.controller.notifyClick(position)); } } } + private void setupLinesGrid() { + setupGrid(linesGrid, mapWidth, mapHeight); + displayGridLines(linesGrid); + } + private void setupGrid(GridPane gridPane, int width, int height) { for (int i = 0; i < height; i++) gridPane.getRowConstraints().add(new RowConstraints(CELL_SIZE)); for (int i = 0; i < width; i++) gridPane.getColumnConstraints().add(new ColumnConstraints(CELL_SIZE)); @@ -134,7 +146,7 @@ protected void renderGrid(int renderedWidth, int renderedHeight) { } @Override - public void addSprite(IGuiSprite guiSprite) throws IllegalArgumentException { + public void addSprite(IGuiSprite guiSprite) { Vector2D position = guiSprite.getPosition(); spritesGridHelper.get(position.getX()).get(position.getY()).getChildren().add(guiSprite.getNode()); } @@ -145,6 +157,11 @@ public void removeSprite(IGuiSprite guiSprite) { spritesGridHelper.get(position.getX()).get(position.getY()).getChildren().remove(guiSprite.getNode()); } + @Override + public void setEventsController(AbstractContainerController controller) { + this.controller = controller; + } + private void displayGridLines(GridPane gridPane) { gridPane.setGridLinesVisible(true); gridPane.getStyleClass().add(LINES_GRID_CLASS); diff --git a/src/main/java/my/project/gui/simulation/grid/FencedMapGridBuilder.java b/src/main/java/my/project/gui/simulation/grid/FencedMapGridBuilder.java index 668f2ee..7ac0d3a 100644 --- a/src/main/java/my/project/gui/simulation/grid/FencedMapGridBuilder.java +++ b/src/main/java/my/project/gui/simulation/grid/FencedMapGridBuilder.java @@ -53,6 +53,7 @@ public void buildGrid() { addRowsNumbers(); // Add grids to the wrapper grid wrapperGrid.add(backgroundPane, 2, 1, mapWidth, mapHeight); + wrapperGrid.add(linesGrid, 2, 1, mapWidth, mapHeight); wrapperGrid.add(spritesGrid, 2, 1, mapWidth, mapHeight); // Load fence textures loadFenceTextures(); diff --git a/src/main/java/my/project/gui/simulation/grid/FoldingMapGridBuilder.java b/src/main/java/my/project/gui/simulation/grid/FoldingMapGridBuilder.java index 0191dc3..e5934a7 100644 --- a/src/main/java/my/project/gui/simulation/grid/FoldingMapGridBuilder.java +++ b/src/main/java/my/project/gui/simulation/grid/FoldingMapGridBuilder.java @@ -28,6 +28,7 @@ public void buildGrid() { addRowsNumbers(); // Add grids to the wrapper grid wrapperGrid.add(backgroundPane, 1, 0, mapWidth, mapHeight); + wrapperGrid.add(linesGrid, 1, 0, mapWidth, mapHeight); wrapperGrid.add(spritesGrid, 1, 0, mapWidth, mapHeight); } diff --git a/src/main/java/my/project/gui/simulation/grid/IBuilder.java b/src/main/java/my/project/gui/simulation/grid/IBuilder.java index b3cb012..9234760 100644 --- a/src/main/java/my/project/gui/simulation/grid/IBuilder.java +++ b/src/main/java/my/project/gui/simulation/grid/IBuilder.java @@ -1,5 +1,6 @@ package my.project.gui.simulation.grid; +import my.project.gui.controllers.AbstractContainerController; import my.project.gui.simulation.sprites.IGuiSprite; public interface IBuilder { @@ -12,4 +13,6 @@ public interface IBuilder { void initialize(); void render(); + + void setEventsController(AbstractContainerController controller); } diff --git a/src/main/java/my/project/gui/simulation/sprites/GuiAnimalSprite.java b/src/main/java/my/project/gui/simulation/sprites/GuiAnimalSprite.java index 09183e8..428792f 100644 --- a/src/main/java/my/project/gui/simulation/sprites/GuiAnimalSprite.java +++ b/src/main/java/my/project/gui/simulation/sprites/GuiAnimalSprite.java @@ -10,7 +10,6 @@ import my.project.gui.utils.ImageLoader; import my.project.simulation.sprites.Animal; import my.project.simulation.sprites.ISprite; -import my.project.simulation.utils.AnimalTracker; public class GuiAnimalSprite extends AbstractGuiSprite { private static final double OPACITY = .3; @@ -57,11 +56,6 @@ Image getImage() { return IMAGE; } - // TODO - add some event which fires this method - public void setupAnimalTracker() { - sprite.getMap().setAnimalTracker(new AnimalTracker((Animal) sprite)); - } - public void setTransparent(boolean isSet) { if (isSet) mainBox.setOpacity(OPACITY); else mainBox.setOpacity(1); @@ -72,12 +66,13 @@ public void showID() { if (overlayBox == null) { overlayBox = new VBox(); overlayBox.setAlignment(Pos.BOTTOM_LEFT); - Label idLabel = new Label(String.valueOf(((Animal) sprite).getID())); + String value = String.valueOf(((Animal) sprite).getID()); + Label idLabel = new Label(value); idLabel.setFont(new Font(ID_FONT_SIZE)); VBox idBox = new VBox(idLabel); idBox.setAlignment(Pos.TOP_CENTER); idBox.getStyleClass().add(ID_BOX_CLASS); -// idBox.setMaxWidth(ID_FONT_SIZE * 2); + idBox.setMaxWidth(ID_FONT_SIZE * value.length()); idBox.setMaxHeight(ID_FONT_SIZE * 2); overlayBox.getChildren().add(idBox); } @@ -106,7 +101,7 @@ private String getEnergyBarColor() { } private void updateEnergyBar() { - energyBar.setProgress(getEnergyRatio()); + energyBar.setProgress(Math.max(0, getEnergyRatio())); energyBar.setStyle("-fx-accent: " + getEnergyBarColor()); } } diff --git a/src/main/java/my/project/gui/simulation/visualization/SimulationVisualizer.java b/src/main/java/my/project/gui/simulation/visualization/SimulationVisualizer.java index 7b8b6d0..6a0ff70 100644 --- a/src/main/java/my/project/gui/simulation/visualization/SimulationVisualizer.java +++ b/src/main/java/my/project/gui/simulation/visualization/SimulationVisualizer.java @@ -7,22 +7,16 @@ import my.project.gui.simulation.grid.IBuilder; import my.project.gui.simulation.sprites.GuiAnimalSprite; import my.project.gui.simulation.sprites.IGuiSprite; -import my.project.simulation.engine.IEngine; -import my.project.simulation.enums.SimulationState; import my.project.simulation.maps.FencedMap; import my.project.simulation.maps.FoldingMap; import my.project.simulation.maps.IMap; import my.project.simulation.sprites.Animal; -import java.util.List; import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; public class SimulationVisualizer { private final IBuilder gridBuilder; private final IMap map; - private boolean isShowingDominantGenomesAnimals = false; public SimulationVisualizer(IMap map, AnchorPane parentContainer) throws IllegalArgumentException { this.map = map; @@ -33,88 +27,37 @@ public SimulationVisualizer(IMap map, AnchorPane parentContainer) throws Illegal } else throw new IllegalArgumentException("There is no GridBuilder defined for map: " + map.getClass()); } -// public void startVisualization() { -// if (!isShowingDominantGenomesAnimals) isPaused = false; -// else { -// // TODO - display some message saying that there is no possibility to start animation when dominant genotypes animals are displayed -// System.out.println("Cannot start visualization as dominant genomes are shown"); -// } -// } -// -// public void pauseVisualization() { -// isPaused = true; -// } -// -// public boolean isPaused() { -// return isPaused; -// } - public void drawGrid() { gridBuilder.initialize(); gridBuilder.render(); } public void showDominantGenomesAnimals() { -// if (simulationEngine.getState() == SimulationState.RUNNING) { -// // TODO - disable using this method in a gui when a simulation is not paused -// System.out.println("Cannot show animals with dominant genomes while simulation is running"); -// } else { - isShowingDominantGenomesAnimals = true; - // Bring to top animals which have dominant genomes - FutureTask future = new FutureTask<>(() -> { + Platform.runLater(() -> { Set animals = map.getDominantGenomesAnimals(); bringAnimalsToTop(animals); setFocusOnAnimals(animals); showAnimalsIDs(animals); - - System.out.println("==== Dominant genomes ===="); - - for (List genome: map.getDominantGenomes()) { - // TODO - display genomes with animals IDs in GUI (instead of this code below) - System.out.println("Genome: " + genome); - for (Animal animal: map.getAnimalsWithGenome(genome)) { - System.out.println(" > " + animal.getID() + " at position: " + animal.getPosition()); - } - } - }, null); - - Platform.runLater(future); - - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } -// } + }); } public void hideDominantGenomesAnimals() { - FutureTask future = new FutureTask<>(() -> { - isShowingDominantGenomesAnimals = false; + Platform.runLater(() -> { Set animals = map.getDominantGenomesAnimals(); bringAnimalsToTop(map.getMaxEnergyFieldAnimals()); disableFocusOnAnimals(animals); hideAnimalsIDs(animals); - }, null); - - Platform.runLater(future); - - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } + }); } - private void bringAnimalsToTop(Set animals) { + public void bringAnimalsToTop(Set animals) { for (Animal animal: animals) { - IGuiSprite guiSprite = animal.getGuiSprite(); - gridBuilder.removeSprite(guiSprite); - gridBuilder.addSprite(guiSprite); + System.out.println(">>> Bring " + animal + " with energy " + animal.getEnergy() + " to front "); + animal.getGuiSprite().getNode().toFront(); } } - private void setFocusOnAnimals(Set animals) { + public void setFocusOnAnimals(Set animals) { for (Animal animal: map.getAllAnimals()) { if (!animals.contains(animal)) { ((GuiAnimalSprite) animal.getGuiSprite()).setTransparent(true); @@ -122,7 +65,7 @@ private void setFocusOnAnimals(Set animals) { } } - private void disableFocusOnAnimals(Set animals) { + public void disableFocusOnAnimals(Set animals) { for (Animal animal: map.getAllAnimals()) { if (!animals.contains(animal)) { ((GuiAnimalSprite) animal.getGuiSprite()).setTransparent(false); @@ -130,11 +73,11 @@ private void disableFocusOnAnimals(Set animals) { } } - private void showAnimalsIDs(Set animals) { + public void showAnimalsIDs(Set animals) { for (Animal animal: animals) ((GuiAnimalSprite) animal.getGuiSprite()).showID(); } - private void hideAnimalsIDs(Set animals) { + public void hideAnimalsIDs(Set animals) { for (Animal animal: animals) ((GuiAnimalSprite) animal.getGuiSprite()).hideID(); } } diff --git a/src/main/java/my/project/simulation/engine/IEngine.java b/src/main/java/my/project/simulation/engine/IEngine.java index 04ce244..58be21e 100644 --- a/src/main/java/my/project/simulation/engine/IEngine.java +++ b/src/main/java/my/project/simulation/engine/IEngine.java @@ -1,6 +1,6 @@ package my.project.simulation.engine; -import my.project.simulation.enums.SimulationState; +import my.project.gui.enums.SimulationState; public interface IEngine { void run(); diff --git a/src/main/java/my/project/simulation/engine/SimulationEngine.java b/src/main/java/my/project/simulation/engine/SimulationEngine.java index 5f13027..af93960 100644 --- a/src/main/java/my/project/simulation/engine/SimulationEngine.java +++ b/src/main/java/my/project/simulation/engine/SimulationEngine.java @@ -2,7 +2,7 @@ import javafx.application.Platform; import my.project.gui.simulation.visualization.SimulationVisualizer; -import my.project.simulation.enums.SimulationState; +import my.project.gui.enums.SimulationState; import my.project.simulation.maps.IMap; import java.util.concurrent.ExecutionException; @@ -49,24 +49,12 @@ public void run() { System.out.println("Initialized successfully? " + wasInitializationSuccessful); if (!wasInitializationSuccessful) return; - // TODO - remove code below - int i = 0; - // TODO - remove code above - // Start rendering simulation frames while (true) { switch (simulationState) { case RUNNING -> { boolean wasFrameRendered = renderNewFrame(); if (!wasFrameRendered) return; -// TODO - remove code below - i++; - if (i % 2000 == 0) { - visualizer.showDominantGenomesAnimals(); - sleep(10000); - visualizer.hideDominantGenomesAnimals(); - } -// TODO - remove code above } case PAUSED -> sleep(SLEEP_TIME); case FINISHED -> { diff --git a/src/main/java/my/project/simulation/maps/AbstractMap.java b/src/main/java/my/project/simulation/maps/AbstractMap.java index 9baf81e..b0ec0bb 100644 --- a/src/main/java/my/project/simulation/maps/AbstractMap.java +++ b/src/main/java/my/project/simulation/maps/AbstractMap.java @@ -1,6 +1,5 @@ package my.project.simulation.maps; -import my.project.gui.charts.ChartDrawer; import my.project.gui.simulation.grid.IBuilder; import my.project.simulation.enums.MapStrategy; import my.project.simulation.stats.StatsMeter; @@ -17,6 +16,8 @@ public abstract class AbstractMap implements IMap, IObserver { private static final int MAGIC_STRATEGY_RESPAWN_THRESHOLD = 5; private static final int MAX_MAGIC_RESPAWNS_COUNT = 3; + private final int width; + private final int height; private final int moveEnergy; private final int startEnergy; private final int bushEnergy; @@ -27,7 +28,7 @@ public abstract class AbstractMap implements IMap, IObserver { protected final Vector2D jungleLowerleft; protected final Vector2D jungleUpperRight; - protected final Map> mapAnimals = new HashMap<>(); + public final Map> mapAnimals = new HashMap<>(); protected final Map mapPlants = new HashMap<>(); protected final Set eatenPlants = new HashSet<>(); protected final PrefixTree genomesTree = new PrefixTree<>(Animal.getPossibleGenes()); @@ -52,6 +53,8 @@ public abstract class AbstractMap implements IMap, IObserver { int startEnergy, int moveEnergy, int bushEnergy, int grassEnergy, int animalsCount) { // Store initial values + this.width = width; + this.height = height; this.initialAnimalsCount = animalsCount; this.startEnergy = startEnergy; this.moveEnergy = moveEnergy; @@ -130,6 +133,16 @@ public MapArea getAreaType(Vector2D position) { return null; } + @Override + public int getWidth() { + return width; + } + + @Override + public int getHeight() { + return height; + } + @Override public void setGridBuilder(IBuilder gridBuilder) { this.gridBuilder = gridBuilder; @@ -182,11 +195,10 @@ public boolean areAnimalsAlive() { public void setAnimalTracker(AnimalTracker tracker) { // TODO - add a possibility tu setup trackers if (animalTracker != null) animalTracker.remove(); animalTracker = tracker; - tracker.setStatsMeter(statsMeter); } @Override - public void removeAnimalTracker() { // TODO - add a possibility to unlink tracker from an animal + public void removeAnimalTracker() { if (animalTracker != null) { animalTracker.remove(); animalTracker = null; @@ -194,6 +206,11 @@ public void removeAnimalTracker() { // TODO - add a possibility to unlink tracke else throw new NoSuchElementException("There is no AnimalTracker set up in a map"); } + @Override + public AnimalTracker getAnimalTracker() { + return animalTracker; + } + @Override public long getCurrentDayNum() { return dayNum; @@ -225,15 +242,24 @@ public Set getAllAnimals() { @Override public Set getMaxEnergyFieldAnimals() { Set animals = new HashSet<>(); - for (SortedSet currAnimals: mapAnimals.values()) { - animals.add(currAnimals.first()); +// System.out.println("Map animals values: " + mapAnimals.values()); + for (Vector2D position: mapAnimals.keySet()) { +// System.out.println("Animals at: " + position + " " + mapAnimals.get(position)); +// System.out.println("First animal " + mapAnimals.get(position).first()); + Animal animal = getMaxEnergyFieldAnimal(position); + if (animal != null) animals.add(animal); } return animals; } @Override - public void setChartDrawer(ChartDrawer chartDrawer) { - this.statsMeter.setChartDrawer(chartDrawer); + public Animal getMaxEnergyFieldAnimal(Vector2D position) { + return mapAnimals.get(position) != null ? mapAnimals.get(position).first() : null; + } + + @Override + public Set getAllFieldAnimals(Vector2D position) { + return mapAnimals.get(position) != null ? mapAnimals.get(position) : new TreeSet<>(new MaxEnergyComparator()); } public List getMapBoundingRect() { @@ -575,7 +601,7 @@ private void handleMagicRespawn() { // TODO - add some information in gui that t while (i < remainingEmptyFields && animalsIt.hasNext()) { Animal currAnimal = animalsIt.next(); Vector2D position = Vector2D.randomVector(mapLowerLeft.getX(), mapUpperRight.getX(), - mapLowerLeft.getY(), mapUpperRight.getY()); + mapLowerLeft.getY(), mapUpperRight.getY()); position = getSegmentEmptyFieldVector(position, mapLowerLeft, mapUpperRight, true); (new Animal(this, position, startEnergy, currAnimal.getGenome())).add(); } diff --git a/src/main/java/my/project/simulation/maps/FencedMap.java b/src/main/java/my/project/simulation/maps/FencedMap.java index ffcd03b..4cccaae 100644 --- a/src/main/java/my/project/simulation/maps/FencedMap.java +++ b/src/main/java/my/project/simulation/maps/FencedMap.java @@ -10,7 +10,7 @@ public FencedMap(int width, int height, double jungleRatio, int startEnergy, int moveEnergy, int bushEnergy, int grassEnergy, int animalsCount) { super(width, height, jungleRatio, startEnergy, moveEnergy, bushEnergy, grassEnergy, animalsCount); - statsMeter = new StatsMeter(STATISTICS_FILE_NAME); + statsMeter = new StatsMeter(this, STATISTICS_FILE_NAME); } @Override diff --git a/src/main/java/my/project/simulation/maps/FoldingMap.java b/src/main/java/my/project/simulation/maps/FoldingMap.java index e0f8e20..80fd8b9 100644 --- a/src/main/java/my/project/simulation/maps/FoldingMap.java +++ b/src/main/java/my/project/simulation/maps/FoldingMap.java @@ -10,7 +10,7 @@ public FoldingMap(int width, int height, double jungleRatio, int startEnergy, int moveEnergy, int bushEnergy, int grassEnergy, int animalsCount) { super(width, height, jungleRatio, startEnergy, moveEnergy, bushEnergy, grassEnergy, animalsCount); - statsMeter = new StatsMeter(STATISTICS_FILE_NAME); + statsMeter = new StatsMeter(this, STATISTICS_FILE_NAME); } @Override diff --git a/src/main/java/my/project/simulation/maps/IMap.java b/src/main/java/my/project/simulation/maps/IMap.java index a1bd6d6..d2df63a 100644 --- a/src/main/java/my/project/simulation/maps/IMap.java +++ b/src/main/java/my/project/simulation/maps/IMap.java @@ -1,6 +1,5 @@ package my.project.simulation.maps; -import my.project.gui.charts.ChartDrawer; import my.project.gui.simulation.grid.IBuilder; import my.project.simulation.enums.MapArea; import my.project.simulation.enums.MapStrategy; @@ -13,6 +12,10 @@ import java.util.Set; public interface IMap { + int getHeight(); + + int getWidth(); + MapArea getAreaType(Vector2D position); Vector2D getNextPosition(Vector2D currPosition, Vector2D moveVector); @@ -45,6 +48,8 @@ public interface IMap { void removeAnimalTracker(); + AnimalTracker getAnimalTracker(); + long getCurrentDayNum(); void setStrategy(MapStrategy strategy); @@ -55,9 +60,11 @@ public interface IMap { Set getAnimalsWithGenome(List genome); + Animal getMaxEnergyFieldAnimal(Vector2D position); + + Set getAllFieldAnimals(Vector2D position); + Set getMaxEnergyFieldAnimals(); Set getDominantGenomesAnimals(); - - void setChartDrawer(ChartDrawer chartDrawer); } diff --git a/src/main/java/my/project/simulation/sprites/AbstractSprite.java b/src/main/java/my/project/simulation/sprites/AbstractSprite.java index e29b50a..4e25e30 100644 --- a/src/main/java/my/project/simulation/sprites/AbstractSprite.java +++ b/src/main/java/my/project/simulation/sprites/AbstractSprite.java @@ -26,6 +26,17 @@ public Vector2D getPosition() { return position; } + @Override + public Vector2D getDisplayedPosition() { + int width = map.getWidth(); + int height = map.getHeight(); + int x = position.getX() - width / 2; + int y = position.getY() - height / 2; + if (width % 2 == 1 && position.getX() >= width / 2) x += 1; + if (height % 2 == 1 && position.getY() >= height / 2) y += 1; + return new Vector2D(x, y); + } + @Override public IMap getMap() { return map; diff --git a/src/main/java/my/project/simulation/sprites/Animal.java b/src/main/java/my/project/simulation/sprites/Animal.java index 68abb2c..d45f55b 100644 --- a/src/main/java/my/project/simulation/sprites/Animal.java +++ b/src/main/java/my/project/simulation/sprites/Animal.java @@ -73,7 +73,7 @@ public String toString() { case SOUTHWEST -> "SW"; case WEST -> "W"; case NORTHWEST -> "NW"; - }; + } + " " + ID + " " + getDisplayedPosition(); } public Vector2D getPrevPosition() { @@ -246,13 +246,14 @@ public void breed(Animal other) { private void handleTracking(Animal other, Animal child) { // Enable child tracking if one of parents is tracked - if (tracker != null || other.tracker != null) { - child.setTracker(tracker); - tracker.addToTrackedList(child); + AnimalTracker animalTracker = tracker != null ? tracker : other.tracker; + if (animalTracker != null) { + child.setTracker(animalTracker); + animalTracker.addToTrackedList(child); // Increment a number of children of the tracked animal if one // of created animal's parents is tracked - Animal trackedAnimal = tracker.getTrackedAnimal(); - if (trackedAnimal == this || trackedAnimal == other) tracker.incrementChildrenCount(); + Animal trackedAnimal = animalTracker.getTrackedAnimal(); + if (trackedAnimal == this || trackedAnimal == other) animalTracker.incrementChildrenCount(); } } } diff --git a/src/main/java/my/project/simulation/sprites/Bush.java b/src/main/java/my/project/simulation/sprites/Bush.java index e5f08fa..448e437 100644 --- a/src/main/java/my/project/simulation/sprites/Bush.java +++ b/src/main/java/my/project/simulation/sprites/Bush.java @@ -12,6 +12,6 @@ public Bush(IMap map, Vector2D position, int plantEnergy) { @Override public String toString() { - return sign; + return sign + " " + getDisplayedPosition(); } } diff --git a/src/main/java/my/project/simulation/sprites/Grass.java b/src/main/java/my/project/simulation/sprites/Grass.java index 9572db7..90a514f 100644 --- a/src/main/java/my/project/simulation/sprites/Grass.java +++ b/src/main/java/my/project/simulation/sprites/Grass.java @@ -12,6 +12,6 @@ public Grass(IMap map, Vector2D position, int plantEnergy) { @Override public String toString() { - return sign; + return sign + " " + getDisplayedPosition(); } } diff --git a/src/main/java/my/project/simulation/sprites/ISprite.java b/src/main/java/my/project/simulation/sprites/ISprite.java index fcfa941..8340931 100644 --- a/src/main/java/my/project/simulation/sprites/ISprite.java +++ b/src/main/java/my/project/simulation/sprites/ISprite.java @@ -15,6 +15,8 @@ public interface ISprite { Vector2D getPosition(); + Vector2D getDisplayedPosition(); + IMap getMap(); void add(); diff --git a/src/main/java/my/project/simulation/stats/StatsMeter.java b/src/main/java/my/project/simulation/stats/StatsMeter.java index 174a2d8..735dafc 100644 --- a/src/main/java/my/project/simulation/stats/StatsMeter.java +++ b/src/main/java/my/project/simulation/stats/StatsMeter.java @@ -1,12 +1,19 @@ package my.project.simulation.stats; import javafx.application.Platform; +import javafx.scene.control.Label; +import javafx.scene.control.Separator; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.VBox; import my.project.gui.charts.ChartDrawer; +import my.project.simulation.maps.IMap; +import my.project.simulation.sprites.Animal; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; public class StatsMeter { private static final String DEFAULT_PATH = "./output/"; @@ -17,14 +24,18 @@ public class StatsMeter { private static final String AVERAGE_LIFESPAN_SERIES_NAME = "Average lifespan"; private static final String AVERAGE_CHILDREN_SERIES_NAME = "Average number of children"; + private final IMap map; private final String defaultFileName; private final List dailyStatistics = new ArrayList<>(); private StatsRecord statsSum = new StatsRecord(0, 0, 0, 0, 0); private int dayNum = 0; + private ChartDrawer chartDrawer; + private VBox dominantGenomesBox; - public StatsMeter(String defaultFileName) { + public StatsMeter(IMap map, String defaultFileName) { + this.map = map; this.defaultFileName = defaultFileName; } @@ -37,6 +48,10 @@ public void setChartDrawer(ChartDrawer chartDrawer) { AVERAGE_CHILDREN_SERIES_NAME); } + public void setDominantGenomesBox(VBox dominantGenomesBox) { + this.dominantGenomesBox = dominantGenomesBox; + } + public void updateStatistics(long aliveAnimalsCount, long diedAnimalsCount, long plantsCount, @@ -44,6 +59,7 @@ public void updateStatistics(long aliveAnimalsCount, double averageAliveEnergy, double averageDiedLifespan, double averageAliveChildren) { + // Update the chart chartDrawer.update(dayNum, aliveAnimalsCount, plantsCount, @@ -51,6 +67,9 @@ public void updateStatistics(long aliveAnimalsCount, averageDiedLifespan, averageAliveChildren); + // Update the dominant genomes box + this.updateDominantGenomes(dominantGenomes); + // Save daily statistics StatsRecord record = new StatsRecord(aliveAnimalsCount, plantsCount, @@ -65,16 +84,32 @@ public void updateStatistics(long aliveAnimalsCount, dayNum++; } - public void updateTrackedAnimalDeath(long dayNum) { - // TODO - send updates to GUI components (to implement) + private void updateDominantGenomes(Set> dominantGenomes) { + dominantGenomesBox.getChildren().clear(); + for (List genome: dominantGenomes) { + VBox genomeBox = createGenomeBox(genome); + dominantGenomesBox.getChildren().add(genomeBox); + } } - public void updateTrackedAnimalDescendants(long descendantsCount) { - // TODO - send updates to GUI components (to implement) + private VBox createGenomeBox(List genome) { + VBox vBox = new VBox(); + Label genomeLabel = new Label(genomeToString(genome)); + Separator separator = new Separator(); + Label textLabel = new Label("Animals wih this genome"); + FlowPane flowPane = new FlowPane(); + flowPane.setVgap(10); + flowPane.setHgap(10); + vBox.getChildren().addAll(genomeLabel, separator, textLabel, flowPane); + + for (Animal animal: map.getAnimalsWithGenome(genome)) { + flowPane.getChildren().add(new Label(String.valueOf(animal.getID()))); + } + return vBox; } - public void updateTrackedAnimalChildren(int childrenCount) { - // TODO - send updates to GUI components (to implement) + private String genomeToString(List genome) { + return genome.stream().map(Object::toString).collect(Collectors.joining("")); } private void writeLinesFromArray(BufferedWriter bw) throws IOException { diff --git a/src/main/java/my/project/simulation/utils/AnimalTracker.java b/src/main/java/my/project/simulation/utils/AnimalTracker.java index d00bdc8..0478dbe 100644 --- a/src/main/java/my/project/simulation/utils/AnimalTracker.java +++ b/src/main/java/my/project/simulation/utils/AnimalTracker.java @@ -1,5 +1,7 @@ package my.project.simulation.utils; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; import my.project.simulation.sprites.Animal; import my.project.simulation.stats.StatsMeter; @@ -9,39 +11,56 @@ public class AnimalTracker { private final Animal animal; private final List descendants = new ArrayList<>(); + private final Label trackedAnimalID; + private final Label trackedAnimalChildren; + private final Label trackedAnimalDescendants; + private final Label trackedAnimalDeath; private int childrenCount = 0; - private StatsMeter statsMeter; - public AnimalTracker(Animal animal) { + public AnimalTracker(Animal animal, Label trackedAnimalID, + Label trackedAnimalChildren, + Label trackedAnimalDescendants, + Label trackedAnimalDeath) { + + this.trackedAnimalID = trackedAnimalID; + this.trackedAnimalChildren = trackedAnimalChildren; + this.trackedAnimalDescendants = trackedAnimalDescendants; + this.trackedAnimalDeath = trackedAnimalDeath; this.animal = animal; - animal.setTracker(this); - } - public void setStatsMeter(StatsMeter statsMeter) { - this.statsMeter = statsMeter; + trackedAnimalID.setText(String.valueOf(animal.getID())); + trackedAnimalChildren.setText("0"); + trackedAnimalDescendants.setText("0"); + trackedAnimalDeath.setText("-"); + animal.setTracker(this); } public Animal getTrackedAnimal() { return animal; } - public void recordAnimalDeath() { - statsMeter.updateTrackedAnimalDeath(animal.getMap().getCurrentDayNum()); + public void incrementChildrenCount() { + childrenCount++; + trackedAnimalChildren.setText(String.valueOf(childrenCount)); } public void addToTrackedList(Animal descendant) { descendants.add(descendant); - statsMeter.updateTrackedAnimalDescendants(descendants.size()); + trackedAnimalDescendants.setText(String.valueOf(descendants.size())); } - public void incrementChildrenCount() { - childrenCount++; - statsMeter.updateTrackedAnimalChildren(childrenCount); + public void recordAnimalDeath() { + trackedAnimalDeath.setText(String.valueOf(animal.getMap().getCurrentDayNum())); } public void remove() { animal.removeTracker(); descendants.forEach(Animal::removeTracker); descendants.clear(); + + trackedAnimalID.setText("-"); + trackedAnimalChildren.setText("-"); + trackedAnimalDescendants.setText("-"); + trackedAnimalDeath.setText("-"); } } diff --git a/src/main/resources/css/style.css b/src/main/resources/css/style.css index c95dba7..c9649cb 100644 --- a/src/main/resources/css/style.css +++ b/src/main/resources/css/style.css @@ -26,8 +26,8 @@ .animalIDBox { -fx-border-width: 2px; - -fx-border-radius: 50%; - -fx-background-radius: 50%; + -fx-border-radius: 100px; + -fx-background-radius: 100px; -fx-background-color: #333; -fx-border-color: #000; -fx-background-insets: 1px; diff --git a/src/main/resources/fxml/ContainerLeft.fxml b/src/main/resources/fxml/ContainerLeft.fxml index 583feb1..97d7cad 100644 --- a/src/main/resources/fxml/ContainerLeft.fxml +++ b/src/main/resources/fxml/ContainerLeft.fxml @@ -9,7 +9,6 @@ - @@ -18,19 +17,19 @@ - + - + - + @@ -40,43 +39,82 @@ - + + - - - - + + + + - - + + + + + + + - -