From 8f3a4ef2ee2b5da6585b5fe78994f5b3e5c07590 Mon Sep 17 00:00:00 2001
From: arnaudlabourel <arnaud.labourel@univ-amu.fr>
Date: Mon, 23 Oct 2023 17:23:10 +0200
Subject: [PATCH] new template for project
---
build.gradle | 2 +-
src/main/java/App.java | 51 -------
src/main/java/FirefighterApplication.java | 55 +++++++
src/main/java/Grid.java | 60 --------
src/main/java/Model.java | 105 -------------
src/main/java/controller/Controller.java | 126 ++++++++++++++++
.../controller/PersistentToggleGroup.java | 34 +++++
src/main/java/model/Board.java | 11 ++
src/main/java/model/FirefighterBoard.java | 134 +++++++++++++++++
src/main/java/model/ModelElement.java | 5 +
src/main/java/model/Position.java | 5 +
src/main/java/view/FirefighterGrid.java | 73 +++++++++
src/main/java/view/Grid.java | 14 ++
src/main/java/view/ViewElement.java | 11 ++
src/main/resources/view/DarkTheme.css | 142 ++++++++++++++++++
src/main/resources/view/view.fxml | 27 ++++
16 files changed, 638 insertions(+), 217 deletions(-)
delete mode 100644 src/main/java/App.java
create mode 100644 src/main/java/FirefighterApplication.java
delete mode 100644 src/main/java/Grid.java
delete mode 100644 src/main/java/Model.java
create mode 100644 src/main/java/controller/Controller.java
create mode 100644 src/main/java/controller/PersistentToggleGroup.java
create mode 100644 src/main/java/model/Board.java
create mode 100644 src/main/java/model/FirefighterBoard.java
create mode 100644 src/main/java/model/ModelElement.java
create mode 100644 src/main/java/model/Position.java
create mode 100644 src/main/java/view/FirefighterGrid.java
create mode 100644 src/main/java/view/Grid.java
create mode 100644 src/main/java/view/ViewElement.java
create mode 100644 src/main/resources/view/DarkTheme.css
create mode 100644 src/main/resources/view/view.fxml
diff --git a/build.gradle b/build.gradle
index 8ab23f1..ba8d575 100644
--- a/build.gradle
+++ b/build.gradle
@@ -28,5 +28,5 @@ test {
}
application {
- mainClass.set("App")
+ mainClass.set("FirefighterApplication")
}
\ No newline at end of file
diff --git a/src/main/java/App.java b/src/main/java/App.java
deleted file mode 100644
index 10dda1d..0000000
--- a/src/main/java/App.java
+++ /dev/null
@@ -1,51 +0,0 @@
-import javafx.application.Application;
-import javafx.scene.Group;
-import javafx.scene.Scene;
-import javafx.scene.control.Button;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.VBox;
-import javafx.stage.Stage;
-
-import static java.lang.Thread.sleep;
-
-
-public class App extends Application {
-
- public static void main(String[] args) {
- launch(args);
- }
-
- @Override
- public void start(Stage primaryStage) throws InterruptedException {
- Group root = new Group();
- Button restart = new Button("Restart");
- VBox buttons = new VBox();
- HBox total = new HBox();
- Grid grid = new Grid(1000,1000,20,20);
-
- root.getChildren().add(total);
- total.getChildren().add(buttons);
- total.getChildren().add(grid);
- buttons.getChildren().add(restart);
- restart.setOnMouseClicked(grid::restart);
- primaryStage.setScene(new Scene(root));
- primaryStage.show();
- grid.repaint();
- new Thread(new Runnable() {
- @Override
- public void run() {
- while(true){
- try {
- sleep(50);
- grid.model.activation();
- grid.repaint();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- }
- }).start();
- }
-}
-
diff --git a/src/main/java/FirefighterApplication.java b/src/main/java/FirefighterApplication.java
new file mode 100644
index 0000000..b666b63
--- /dev/null
+++ b/src/main/java/FirefighterApplication.java
@@ -0,0 +1,55 @@
+import controller.Controller;
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+import model.FirefighterBoard;
+
+import java.io.IOException;
+import java.net.URL;
+
+public class FirefighterApplication extends Application {
+ private static final String VIEW_RESOURCE_PATH = "/view/view.fxml";
+ private static final String APP_NAME = "Firefighter simulator";
+ private static final int ROW_COUNT = 50;
+ private static final int COLUMN_COUNT = 50;
+ private static final int SQUARE_WIDTH = 20;
+ private static final int SQUARE_HEIGHT = 20;
+ public static final int INITIAL_FIRE_COUNT = 3;
+ public static final int INITIAL_FIREFIGHTER_COUNT = 6;
+
+ private Stage primaryStage;
+ private Parent view;
+ private void initializePrimaryStage(Stage primaryStage) {
+ this.primaryStage = primaryStage;
+ this.primaryStage.setTitle(APP_NAME);
+ this.primaryStage.setOnCloseRequest(event -> Platform.exit());
+ this.primaryStage.setResizable(false);
+ this.primaryStage.sizeToScene();
+ }
+
+ @Override
+ public void start(Stage primaryStage) throws IOException {
+ initializePrimaryStage(primaryStage);
+ initializeView();
+ showScene();
+ }
+
+ private void initializeView() throws IOException {
+ FXMLLoader loader = new FXMLLoader();
+ URL location = FirefighterApplication.class.getResource(VIEW_RESOURCE_PATH);
+ loader.setLocation(location);
+ view = loader.load();
+ Controller controller = loader.getController();
+ controller.initialize(SQUARE_WIDTH, SQUARE_HEIGHT, COLUMN_COUNT, ROW_COUNT,
+ INITIAL_FIRE_COUNT, INITIAL_FIREFIGHTER_COUNT);
+ }
+
+ private void showScene() {
+ Scene scene = new Scene(view);
+ primaryStage.setScene(scene);
+ primaryStage.show();
+ }
+}
diff --git a/src/main/java/Grid.java b/src/main/java/Grid.java
deleted file mode 100644
index 23fb50d..0000000
--- a/src/main/java/Grid.java
+++ /dev/null
@@ -1,60 +0,0 @@
-import javafx.scene.canvas.Canvas;
-import javafx.scene.canvas.GraphicsContext;
-import javafx.scene.input.MouseEvent;
-import javafx.scene.paint.Color;
-
-public class Grid extends Canvas{
- int width, height, colCount, rowCount;
- Model model;
-
-
- public Grid(int width, int height, int colCount, int rowCount) {
- super(width,height);
- this.width = width;
- this.height = height;
- this.colCount = colCount;
- this.rowCount = rowCount;
- setFocusTraversable(true);
- setOnMousePressed(this::mousePressed);
- model = new Model(this);
- model.initialisation(3,8);
- }
-
- public void restart(MouseEvent mouseEvent){
- model = new Model(this);
- model.initialisation(3,6);
- getGraphicsContext2D().clearRect(0,0,width,height);
- repaint();
- }
- private void mousePressed(MouseEvent mouseEvent) {
- model.activation();
- repaint();
- /*double x = mouseEvent.getX();
- double y = mouseEvent.getY();
- model.click((int)x*rowCount/height,(int)y*colCount/width);*/
- }
-
- void repaint(){
- for(int col=0; col<colCount; col++)
- getGraphicsContext2D().strokeLine(0, col*width/colCount,height, col*width/colCount);
- for(int row=0; row<rowCount;row++)
- getGraphicsContext2D().strokeLine(row*height/rowCount,0,row*height/rowCount,width);
-
- }
-
- void paint(int row, int col){
- getGraphicsContext2D().setFill(Color.WHITE);
- getGraphicsContext2D().fillRect(row*height/rowCount,col*width/colCount,height/rowCount,width/colCount);
- }
-
- public void paintFF(int row, int col) {
- getGraphicsContext2D().setFill(Color.BLUE);
- getGraphicsContext2D().fillRect(row*height/rowCount,col*width/colCount,height/rowCount,width/colCount);
- }
-
- public void paintFire(int row, int col) {
- getGraphicsContext2D().setFill(Color.RED);
- getGraphicsContext2D().fillRect(row*height/rowCount,col*width/colCount,height/rowCount,width/colCount);
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/Model.java b/src/main/java/Model.java
deleted file mode 100644
index f23d0d1..0000000
--- a/src/main/java/Model.java
+++ /dev/null
@@ -1,105 +0,0 @@
-import java.util.*;
-
-
-public class Model {
- Grid grid;
- int colCount, rowCount;
- List<Position> firefighters = new ArrayList<>();
- Set<Position> fires = new HashSet<>();
- List<Position> ffNewPositions;
- int step = 0;
-
- public Model(Grid grid) {
- this.grid = grid;
- colCount = grid.colCount;
- rowCount = grid.rowCount;
- }
-
-
- public void initialisation(int fireNumber, int fireFighterNumber){
- for(int index=0; index<fireNumber;index++)
- fires.add(randomPosition());
- for(int index=0; index<fireFighterNumber;index++)
- firefighters.add(randomPosition());
- }
-
- private Position randomPosition() {
- return new Position((int) (Math.random()*rowCount), (int) (Math.random()*colCount));
- }
-
-
- public void activation(){
- ffNewPositions = new ArrayList<>();
- for(Position ff : firefighters){
- Position newPosition = activateFirefighter(ff);
- grid.paint(ff.row,ff.col);
- grid.paintFF(newPosition.row, newPosition.col);
- ffNewPositions.add(newPosition);
- }
- firefighters = ffNewPositions;
- if(step%2==0){
- List<Position> newFires = new ArrayList<>();
- for(Position fire : fires){
- newFires.addAll(activateFire(fire));
- }
- for(Position newFire : newFires)
- grid.paintFire(newFire.row, newFire.col);
-
- fires.addAll(newFires);}
- step++;
-
- }
-
- private List<Position> activateFire(Position position) {
- return next(position);
- }
-
-
-
- private Position activateFirefighter(Position position) {
- Position randomPosition = aStepTowardFire(position);
- //next(position).get((int) (Math.random()*next(position).size()));
- List<Position> nextFires = next(randomPosition).stream().filter(fires::contains).toList();
- extinguish(randomPosition);
- for (Position fire : nextFires)
- extinguish(fire);
- return randomPosition;
- }
-
- private void extinguish(Position position) {
- fires.remove(position);
- grid.paint(position.row, position.col);
- }
-
- private List<Position> next(Position position){
- List<Position> list = new ArrayList<>();
- if(position.row>0) list.add(new Position(position.row-1, position.col));
- if(position.col>0) list.add(new Position(position.row, position.col-1));
- if(position.row<rowCount-1) list.add(new Position(position.row+1, position.col));
- if(position.col<colCount-1) list.add(new Position(position.row, position.col+1));
- return list;
- }
-
- private Position aStepTowardFire(Position position){
- Queue<Position> toVisit = new LinkedList<>();
- Set<Position> seen = new HashSet<>();
- HashMap<Position,Position> firstMove = new HashMap<>();
- toVisit.addAll(next(position));
- for(Position initialMove : toVisit)
- firstMove.put(initialMove,initialMove);
- while(!toVisit.isEmpty()){
- Position current = toVisit.poll();
- if(fires.contains(current))
- return firstMove.get(current);
- for(Position adjacent : next(current)){
- if(seen.contains(adjacent)) continue;
- toVisit.add(adjacent);
- seen.add(adjacent);
- firstMove.put(adjacent, firstMove.get(current));
- }
- }
- return position;
- }
-
- public record Position(int row, int col){}
-}
\ No newline at end of file
diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java
new file mode 100644
index 0000000..16e9b0d
--- /dev/null
+++ b/src/main/java/controller/Controller.java
@@ -0,0 +1,126 @@
+package controller;
+
+import javafx.animation.Animation;
+import javafx.animation.KeyFrame;
+import javafx.animation.Timeline;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.ToggleButton;
+import javafx.scene.control.ToggleGroup;
+import javafx.util.Duration;
+import javafx.util.Pair;
+import model.Board;
+import model.ModelElement;
+import model.FirefighterBoard;
+import model.Position;
+import view.FirefighterGrid;
+import view.ViewElement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Objects.requireNonNull;
+
+public class Controller {
+
+ public static final int PERIOD_IN_MILLISECONDS = 50;
+ @FXML
+ private Button restartButton;
+ @FXML
+ private ToggleButton pauseToggleButton;
+ @FXML
+ private ToggleButton playToggleButton;
+ @FXML
+ private FirefighterGrid grid;
+ private Timeline timeline;
+ private Board<List<ModelElement>> board;
+
+ @FXML
+ private void initialize() {
+ initializePlayAndPauseToggleButtons();
+ initializeTimeline();
+ }
+
+ private void initializePlayAndPauseToggleButtons() {
+ ToggleGroup toggleGroup = new PersistentToggleGroup();
+ toggleGroup.getToggles().addAll(playToggleButton, pauseToggleButton);
+ pauseToggleButton.setSelected(true);
+ }
+
+ private void setModel(FirefighterBoard firefighterBoard) {
+ this.board = requireNonNull(firefighterBoard, "model is null");
+ }
+
+ private void updateBoard(){
+ List<Position> updatedPositions = board.updateToNextGeneration();
+ List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>();
+ for(Position updatedPosition : updatedPositions){
+ List<ModelElement> squareState = board.getState(updatedPosition);
+ ViewElement viewElement = getViewElement(squareState);
+ updatedSquares.add(new Pair<>(updatedPosition, viewElement));
+ }
+ grid.repaint(updatedSquares);
+ }
+
+ private void repaintBoard(){
+ int columnCount = board.columnCount();
+ int rowCount = board.rowCount();
+ ViewElement[][] viewElements = new ViewElement[rowCount][columnCount];
+ for(int column = 0; column < columnCount; column++)
+ for(int row = 0; row < rowCount; row++)
+ viewElements[row][column] = getViewElement(board.getState(new Position(row, column)));
+ grid.repaint(viewElements);
+ }
+
+ private ViewElement getViewElement(List<ModelElement> squareState) {
+ if(squareState.contains(ModelElement.FIREFIGHTER)){
+ return ViewElement.FIREFIGHTER;
+ }
+ if (squareState.contains(ModelElement.FIRE)){
+ return ViewElement.FIRE;
+ }
+ return ViewElement.EMPTY;
+ }
+
+ private void initializeTimeline() {
+ Duration duration = new Duration(Controller.PERIOD_IN_MILLISECONDS);
+ EventHandler<ActionEvent> eventHandler =
+ event -> updateBoard();
+ KeyFrame keyFrame = new KeyFrame(duration, eventHandler);
+ timeline = new Timeline(keyFrame);
+ timeline.setCycleCount(Animation.INDEFINITE);
+ }
+
+ public void play() {
+ timeline.play();
+ }
+
+ public void pause() {
+ timeline.pause();
+ }
+
+ public void pauseToggleButtonAction(ActionEvent actionEvent) {
+ this.pause();
+ }
+
+ public void playToggleButtonAction(ActionEvent actionEvent) {
+ this.play();
+ }
+
+ public void restartButtonAction(ActionEvent actionEvent) {
+ this.pause();
+ board.reset();
+ pauseToggleButton.setSelected(true);
+ repaintBoard();
+ }
+
+ public void initialize(int squareWidth, int squareHeight, int columnCount,
+ int rowCount, int initialFireCount, int initialFirefighterCount) {
+ grid.initialize(squareWidth, squareHeight, columnCount, rowCount);
+ this.setModel(new FirefighterBoard(columnCount, rowCount, initialFireCount, initialFirefighterCount));
+ repaintBoard();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/controller/PersistentToggleGroup.java b/src/main/java/controller/PersistentToggleGroup.java
new file mode 100644
index 0000000..7c2c4b5
--- /dev/null
+++ b/src/main/java/controller/PersistentToggleGroup.java
@@ -0,0 +1,34 @@
+package controller;
+
+import javafx.collections.ListChangeListener.Change;
+import javafx.scene.control.Toggle;
+import javafx.scene.control.ToggleButton;
+import javafx.scene.control.ToggleGroup;
+import javafx.scene.input.MouseEvent;
+
+/**
+ * An extension of {@link ToggleGroup} that ensures that a {@link Toggle} in a group must always be
+ * selected.
+ *
+ */
+class PersistentToggleGroup extends ToggleGroup {
+
+ /**
+ * Creates a new {@code PersistentToggleGroup}.
+ */
+ PersistentToggleGroup() {
+ getToggles().addListener((Change<? extends Toggle> change) -> {
+ while (change.next()) {
+ for (Toggle toggle : change.getAddedSubList()) {
+ ToggleButton toggleButton = (ToggleButton) toggle;
+ toggleButton.addEventFilter(MouseEvent.MOUSE_RELEASED, mouseEvent -> {
+ if (toggleButton.equals(getSelectedToggle())) {
+ mouseEvent.consume();
+ }
+ });
+ }
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/model/Board.java b/src/main/java/model/Board.java
new file mode 100644
index 0000000..5e24f47
--- /dev/null
+++ b/src/main/java/model/Board.java
@@ -0,0 +1,11 @@
+package model;
+
+import java.util.List;
+
+public interface Board<S> {
+ S getState(Position position);
+ int rowCount();
+ int columnCount();
+ List<Position> updateToNextGeneration();
+ void reset();
+}
diff --git a/src/main/java/model/FirefighterBoard.java b/src/main/java/model/FirefighterBoard.java
new file mode 100644
index 0000000..2586fe8
--- /dev/null
+++ b/src/main/java/model/FirefighterBoard.java
@@ -0,0 +1,134 @@
+package model;
+
+import java.util.*;
+
+
+public class FirefighterBoard implements Board<List<ModelElement>> {
+ private final int columnCount;
+ private final int rowCount;
+ private final int initialFireCount;
+ private final int initialFirefighterCount;
+ List<Position> firefighterPositions;
+ Set<Position> firePositions;
+ List<Position> firefighterNewPositions;
+ int step = 0;
+
+ public FirefighterBoard(int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount) {
+ this.columnCount = columnCount;
+ this.rowCount = rowCount;
+ this.initialFireCount = initialFireCount;
+ this.initialFirefighterCount = initialFirefighterCount;
+ initializeElements();
+ }
+
+ public void initializeElements() {
+ firefighterPositions = new ArrayList<>();
+ firePositions = new HashSet<>();
+ for (int index = 0; index < initialFireCount; index++)
+ firePositions.add(randomPosition());
+ for (int index = 0; index < initialFirefighterCount; index++)
+ firefighterPositions.add(randomPosition());
+ }
+
+ private Position randomPosition() {
+ return new Position((int) (Math.random() * rowCount), (int) (Math.random() * columnCount));
+ }
+
+ @Override
+ public List<ModelElement> getState(Position position) {
+ List<ModelElement> result = new ArrayList<>();
+ for(Position firefighterPosition : firefighterPositions)
+ if (firefighterPosition.equals(position))
+ result.add(ModelElement.FIREFIGHTER);
+ if(firePositions.contains(position))
+ result.add(ModelElement.FIRE);
+ return result;
+ }
+
+ @Override
+ public int rowCount() {
+ return rowCount;
+ }
+
+ @Override
+ public int columnCount() {
+ return columnCount;
+ }
+
+ public List<Position> updateToNextGeneration() {
+ List<Position> result = activateFirefighters();
+ result.addAll(activateFires());
+ step++;
+ return result;
+ }
+
+ private List<Position> activateFires() {
+ List<Position> result = new ArrayList<>();
+ if (step % 2 == 0) {
+ List<Position> newFirePositions = new ArrayList<>();
+ for (Position fire : firePositions) {
+ newFirePositions.addAll(neighbors(fire));
+ }
+ firePositions.addAll(newFirePositions);
+ result.addAll(newFirePositions);
+ }
+ return result;
+
+ }
+
+ private List<Position> activateFirefighters() {
+ List<Position> result = new ArrayList<>();
+ firefighterNewPositions = new ArrayList<>();
+ for (Position firefighterPosition : firefighterPositions) {
+ Position newFirefighterPosition = neighborClosestToFire(firefighterPosition);
+ result.add(firefighterPosition);
+ result.add(newFirefighterPosition);
+ firefighterNewPositions.add(newFirefighterPosition);
+ extinguish(newFirefighterPosition);
+ List<Position> neighborFirePositions = neighbors(newFirefighterPosition).stream().filter(firePositions::contains).toList();
+ for(Position firePosition : neighborFirePositions)
+ extinguish(firePosition);
+ result.addAll(firePositions);
+ }
+ firefighterPositions = firefighterNewPositions;
+ return result;
+ }
+
+ @Override
+ public void reset() {
+ initializeElements();
+ }
+
+ private void extinguish(Position position) {
+ firePositions.remove(position);
+ }
+
+ private List<Position> neighbors(Position position) {
+ List<Position> list = new ArrayList<>();
+ if (position.row() > 0) list.add(new Position(position.row() - 1, position.column()));
+ if (position.column() > 0) list.add(new Position(position.row(), position.column() - 1));
+ if (position.row() < rowCount - 1) list.add(new Position(position.row() + 1, position.column()));
+ if (position.column() < columnCount - 1) list.add(new Position(position.row(), position.column() + 1));
+ return list;
+ }
+
+ private Position neighborClosestToFire(Position position) {
+ Set<Position> seen = new HashSet<>();
+ HashMap<Position, Position> firstMove = new HashMap<>();
+ Queue<Position> toVisit = new LinkedList<>(neighbors(position));
+ for (Position initialMove : toVisit)
+ firstMove.put(initialMove, initialMove);
+ while (!toVisit.isEmpty()) {
+ Position current = toVisit.poll();
+ if (firePositions.contains(current))
+ return firstMove.get(current);
+ for (Position adjacent : neighbors(current)) {
+ if (seen.contains(adjacent)) continue;
+ toVisit.add(adjacent);
+ seen.add(adjacent);
+ firstMove.put(adjacent, firstMove.get(current));
+ }
+ }
+ return position;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/model/ModelElement.java b/src/main/java/model/ModelElement.java
new file mode 100644
index 0000000..759eee5
--- /dev/null
+++ b/src/main/java/model/ModelElement.java
@@ -0,0 +1,5 @@
+package model;
+
+public enum ModelElement {
+ FIREFIGHTER, FIRE
+}
diff --git a/src/main/java/model/Position.java b/src/main/java/model/Position.java
new file mode 100644
index 0000000..08c95ad
--- /dev/null
+++ b/src/main/java/model/Position.java
@@ -0,0 +1,5 @@
+package model;
+
+public record Position(int row, int column) {
+
+}
diff --git a/src/main/java/view/FirefighterGrid.java b/src/main/java/view/FirefighterGrid.java
new file mode 100644
index 0000000..085ad2c
--- /dev/null
+++ b/src/main/java/view/FirefighterGrid.java
@@ -0,0 +1,73 @@
+package view;
+
+import javafx.scene.canvas.Canvas;
+import javafx.scene.paint.Color;
+import javafx.util.Pair;
+import model.Position;
+
+import java.util.List;
+
+public class FirefighterGrid extends Canvas implements Grid<ViewElement>{
+
+ private void paintElementAtPosition(ViewElement element, Position position) {
+ paintSquare(position.row(), position.column(), element.color);
+ }
+
+ private int squareWidth;
+ private int squareHeight;
+ private int columnCount;
+ private int rowCount;
+
+ @Override
+ public void repaint(List<Pair<Position, ViewElement>> positionedElements) {
+ for(Pair<Position, ViewElement> pair : positionedElements){
+ paintElementAtPosition(pair.getValue(), pair.getKey());
+ }
+ paintLines();
+ }
+
+ @Override
+ public void repaint(ViewElement[][] elements) {
+ for(int column = 0; column < columnCount; column++)
+ for(int row = 0; row < rowCount; row++){
+ paintElementAtPosition(elements[row][column], new Position(row, column));
+ }
+ paintLines();
+ }
+
+ public int getColumnCount() {
+ return columnCount;
+ }
+
+ public int getRowCount() {
+ return rowCount;
+ }
+
+ public FirefighterGrid(){
+ }
+
+ public void initialize(int squareWidth,
+ int squareHeight,
+ int columnCount,
+ int rowCount) {
+ this.squareWidth = squareWidth;
+ this.squareHeight = squareHeight;
+ this.columnCount = columnCount;
+ this.rowCount = rowCount;
+ }
+
+ private void paintLines(){
+ for(int column=0; column<columnCount; column++)
+ getGraphicsContext2D().strokeLine(0, column*squareHeight, getWidth(), column*squareWidth);
+ for(int row=0; row<rowCount;row++)
+ getGraphicsContext2D().strokeLine(row*squareHeight, 0,row*squareHeight, getHeight());
+ }
+
+ private void paintSquare(int row, int column, Color color){
+ getGraphicsContext2D().setFill(color);
+ getGraphicsContext2D().fillRect(row*squareHeight,column*squareWidth,squareHeight,squareWidth);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/view/Grid.java b/src/main/java/view/Grid.java
new file mode 100644
index 0000000..ee8a612
--- /dev/null
+++ b/src/main/java/view/Grid.java
@@ -0,0 +1,14 @@
+package view;
+
+import javafx.scene.paint.Color;
+import javafx.util.Pair;
+import model.Position;
+
+import java.util.List;
+
+public interface Grid<E> {
+ void repaint(List<Pair<Position,E>> elements);
+ void repaint(E[][] elements);
+ int getColumnCount();
+ int getRowCount();
+}
diff --git a/src/main/java/view/ViewElement.java b/src/main/java/view/ViewElement.java
new file mode 100644
index 0000000..ffb7611
--- /dev/null
+++ b/src/main/java/view/ViewElement.java
@@ -0,0 +1,11 @@
+package view;
+
+import javafx.scene.paint.Color;
+
+public enum ViewElement {
+ FIREFIGHTER(Color.BLUE), FIRE(Color.RED), EMPTY(Color.WHITE);
+ final Color color;
+ ViewElement(Color color) {
+ this.color = color;
+ }
+}
diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css
new file mode 100644
index 0000000..46b78aa
--- /dev/null
+++ b/src/main/resources/view/DarkTheme.css
@@ -0,0 +1,142 @@
+.background {
+ -fx-background-color: #1d1d1d;
+}
+
+.label {
+ -fx-font-size: 11pt;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-text-fill: white;
+ -fx-opacity: 0.6;
+}
+
+.label-bright {
+ -fx-font-size: 11pt;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-text-fill: white;
+ -fx-opacity: 1;
+}
+
+.label-header {
+ -fx-font-size: 32pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-opacity: 1;
+}
+
+.table-view {
+ -fx-base: #1d1d1d;
+ -fx-control-inner-background: #1d1d1d;
+ -fx-background-color: #1d1d1d;
+ -fx-table-cell-border-color: transparent;
+ -fx-table-header-border-color: transparent;
+ -fx-padding: 5;
+}
+
+.table-view .column-header-background {
+ -fx-background-color: transparent;
+}
+
+.table-view .column-header, .table-view .filler {
+ -fx-border-width: 0 0 1 0;
+ -fx-background-color: transparent;
+ -fx-border-color:
+ transparent
+ transparent
+ derive(-fx-base, 80%)
+ transparent;
+ -fx-border-insets: 0 10 1 0;
+}
+
+.table-view .column-header .label {
+ -fx-font-size: 20pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-alignment: center-left;
+ -fx-opacity: 1;
+}
+
+.table-view:focused .table-row-cell:filled:focused:selected {
+ -fx-background-color: -fx-focus-color;
+}
+
+.split-pane:horizontal > .split-pane-divider {
+ -fx-border-color: transparent #1d1d1d transparent #1d1d1d;
+ -fx-background-color: transparent, derive(#1d1d1d,20%);
+}
+
+.split-pane {
+ -fx-padding: 1 0 0 0;
+}
+
+.menu-bar {
+ -fx-background-color: derive(#1d1d1d,20%);
+}
+
+.context-menu {
+ -fx-background-color: derive(#1d1d1d,50%);
+}
+
+.menu-bar .label {
+ -fx-font-size: 14pt;
+ -fx-font-family: "Segoe UI Light";
+ -fx-text-fill: white;
+ -fx-opacity: 0.9;
+}
+
+.menu .left-container {
+ -fx-background-color: black;
+}
+
+.text-field {
+ -fx-font-size: 12pt;
+ -fx-font-family: "Segoe UI Semibold";
+}
+
+/*
+ * Metro style Push Button
+ * Author: Pedro Duque Vieira
+ * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
+ */
+.button {
+ -fx-padding: 5 22 5 22;
+ -fx-border-color: #e2e2e2;
+ -fx-border-width: 2;
+ -fx-background-radius: 0;
+ -fx-background-color: #1d1d1d;
+ -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+ -fx-font-size: 11pt;
+ -fx-text-fill: #d8d8d8;
+ -fx-background-insets: 0 0 0 0, 0, 1, 2;
+}
+
+.button:hover {
+ -fx-background-color: #3a3a3a;
+}
+
+.button:pressed, .button:default:hover:pressed {
+ -fx-background-color: white;
+ -fx-text-fill: #1d1d1d;
+}
+
+.button:focused {
+ -fx-border-color: white, white;
+ -fx-border-width: 1, 1;
+ -fx-border-style: solid;
+ -fx-border-radius: 0, 0;
+ -fx-border-insets: 1 1 1 1, 0;
+}
+
+.button:disabled, .button:default:disabled {
+ -fx-opacity: 0.4;
+ -fx-background-color: #1d1d1d;
+ -fx-text-fill: white;
+}
+
+.button:default {
+ -fx-background-color: -fx-focus-color;
+ -fx-text-fill: #ffffff;
+}
+
+.button:default:hover {
+ -fx-background-color: derive(-fx-focus-color,30%);
+}
\ No newline at end of file
diff --git a/src/main/resources/view/view.fxml b/src/main/resources/view/view.fxml
new file mode 100644
index 0000000..73d4c93
--- /dev/null
+++ b/src/main/resources/view/view.fxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.VBox?>
+<?import view.FirefighterGrid?>
+
+<?import javafx.scene.control.ToggleButton?>
+<HBox styleClass="background" stylesheets="@DarkTheme.css"
+ xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
+ fx:controller="controller.Controller">
+ <VBox>
+ <Button fx:id="restartButton" maxHeight="-Infinity" maxWidth="-Infinity"
+ mnemonicParsing="false" onAction="#restartButtonAction" prefHeight="24.0" prefWidth="200.0"
+ text="Restart"/>
+ <ToggleButton fx:id="playToggleButton" maxHeight="-Infinity" maxWidth="-Infinity"
+ mnemonicParsing="false" onAction="#playToggleButtonAction" prefHeight="24.0"
+ prefWidth="200.0" styleClass="button" text="Play"/>
+ <ToggleButton fx:id="pauseToggleButton" maxHeight="-Infinity" maxWidth="-Infinity"
+ mnemonicParsing="false" onAction="#pauseToggleButtonAction" prefHeight="24.0"
+ prefWidth="200.0" styleClass="button" text="Pause"/>
+ </VBox>
+ <FirefighterGrid fx:id="grid" width="1000.0" height="1000.0"
+ xmlns="http://javafx.com/javafx"
+ xmlns:fx="http://javafx.com/fxml">
+ </FirefighterGrid>
+</HBox>
--
GitLab