From 3a3db7ba8111a34c17692f260daa81fdf29ddd28 Mon Sep 17 00:00:00 2001 From: jez04 <david.jezek@post.cz> Date: Mon, 28 Apr 2025 01:29:44 +0200 Subject: [PATCH] feat: lab 10 assignment --- pom.xml | 4 +- scores.csv | 3 + src/main/java/lab/data/Level.java | 12 ++- src/main/java/lab/gui/App.java | 29 ++++++++ src/main/java/lab/gui/EditController.java | 87 ++++++++++++++++++++++ src/main/java/lab/gui/GameController.java | 25 +++++++ src/main/java/lab/storage/FileStorage.java | 16 ++-- src/main/java/module-info.java | 1 + src/main/resources/lab/gui/application.css | 80 +++++++++++++++++++- src/main/resources/lab/gui/edit.fxml | 48 ++++++++++++ 10 files changed, 295 insertions(+), 10 deletions(-) create mode 100644 scores.csv create mode 100644 src/main/java/lab/gui/EditController.java create mode 100644 src/main/resources/lab/gui/edit.fxml diff --git a/pom.xml b/pom.xml index 8552fb2..223cbb4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,10 +3,10 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cz.vsb.fei.java2</groupId> - <artifactId>java2-lab09-v1</artifactId> + <artifactId>java2-lab10-v1</artifactId> <version>0.0.1-SNAPHOST</version> - <name>java2-lab09-v1</name> + <name>java2-lab10-v1</name> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/scores.csv b/scores.csv new file mode 100644 index 0000000..71c59b0 --- /dev/null +++ b/scores.csv @@ -0,0 +1,3 @@ +BugBuster;264;EASY +ClusterChampion;127;MEDIUM +BugBuster;264;EASY diff --git a/src/main/java/lab/data/Level.java b/src/main/java/lab/data/Level.java index fc4e031..3fbaed9 100644 --- a/src/main/java/lab/data/Level.java +++ b/src/main/java/lab/data/Level.java @@ -1,5 +1,15 @@ package lab.data; public enum Level { - EASY, MEDIUM, HARD; + EASY, MEDIUM, HARD; + + public static Level from(String s) { + for (Level l : values()) { + if (l.toString().equals(s)) { + return l; + } + } + return null; + } + } diff --git a/src/main/java/lab/gui/App.java b/src/main/java/lab/gui/App.java index 5dfe5cc..1e6d96e 100644 --- a/src/main/java/lab/gui/App.java +++ b/src/main/java/lab/gui/App.java @@ -1,5 +1,8 @@ package lab.gui; +import java.io.IOException; +import java.net.URL; + import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; @@ -7,9 +10,12 @@ import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.ButtonType; +import javafx.stage.Modality; import javafx.stage.Stage; +import javafx.stage.StageStyle; import javafx.stage.WindowEvent; import lab.Setting; +import lab.data.Score; import lab.storage.FileStorage; import lombok.extern.log4j.Log4j2; @@ -26,6 +32,8 @@ public class App extends Application { private boolean viewMode; + private Stage primaryStage; + public static void main(String[] args) { log.info("Application lauched"); Setting.configure(Setting.builder().scoreStorageInterface(new FileStorage()).build()); @@ -43,7 +51,9 @@ public class App extends Application { Parent root = gameLoader.load(); gameController = gameLoader.getController(); gameController.setViewMode(viewMode); + gameController.setApp(this); Scene scene = new Scene(root); + this.primaryStage = primaryStage; primaryStage.setScene(scene); primaryStage.setTitle("Java 2 - 2nd laboratory"); primaryStage.show(); @@ -54,6 +64,25 @@ public class App extends Application { } } + public Stage createDialogStage(Score score) throws IOException { + Stage dialog = new Stage(); + dialog.initStyle(StageStyle.UTILITY); + FXMLLoader editLoader = new FXMLLoader(getClass().getResource("/lab/gui/edit.fxml")); + Parent root = editLoader.load(); + EditController editController = editLoader.getController(); + editController.setStage(dialog); + editController.setObjectToEdit(score); + editController.setGameController(gameController); + Scene scene = new Scene(root); + URL cssUrl = getClass().getResource("application.css"); + scene.getStylesheets().add(cssUrl.toString()); + dialog.setScene(scene); + dialog.initModality(Modality.APPLICATION_MODAL); + dialog.initOwner(primaryStage); + return dialog; + + } + @Override public void stop() throws Exception { gameController.stop(); diff --git a/src/main/java/lab/gui/EditController.java b/src/main/java/lab/gui/EditController.java new file mode 100644 index 0000000..2d386b3 --- /dev/null +++ b/src/main/java/lab/gui/EditController.java @@ -0,0 +1,87 @@ +package lab.gui; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.geometry.HPos; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; +import javafx.stage.Stage; +import lab.data.Score; +import lombok.Setter; + +/** + * + */ +public class EditController { + + private static Logger log = LogManager.getLogger(EditController.class); + + @FXML + private Button btnOk; + + @FXML + private Button btnCancel; + + @FXML + private Label txtTitle; + + @FXML + private GridPane content; + + private Object data; + + private App app; + + private Map<String, TextField> nameToTextField = new HashMap<>(); + + @Setter + private Stage stage; + + @Setter + private GameController gameController; + + @FXML + void btnOkAction(ActionEvent event) { + //TODO: add code to read values from text fields + + gameController.updateData((Score)data); + stage.hide(); + } + + @FXML + void btnCancelAction(ActionEvent event) { + stage.hide(); + } + + @FXML + void initialize() { + log.info("Screen initialized."); + } + + public void setObjectToEdit(Object data) { + this.data = data; + log.info("data set {}", data); + content.getChildren().clear(); + + //TODO: code to detect properties and add rows to dialog + } + + private void addDialogRow(int rowNumber, String name, String descriptionName, String stringValue, + boolean editable) { + Label label = new Label(descriptionName); + TextField textField = new TextField(stringValue); + textField.setEditable(editable); + nameToTextField.put(name, textField); + content.addRow(rowNumber, label, textField); + GridPane.setHalignment(label, HPos.RIGHT); + } + +} diff --git a/src/main/java/lab/gui/GameController.java b/src/main/java/lab/gui/GameController.java index d16cd6a..758ff32 100644 --- a/src/main/java/lab/gui/GameController.java +++ b/src/main/java/lab/gui/GameController.java @@ -1,5 +1,6 @@ package lab.gui; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -15,9 +16,11 @@ import javafx.scene.control.Label; import javafx.scene.control.SelectionMode; import javafx.scene.control.Slider; import javafx.scene.control.TableColumn; +import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import lab.Setting; import lab.data.Level; @@ -26,6 +29,7 @@ import lab.game.BulletAnimated; import lab.game.DrawingThread; import lab.game.MyPoint; import lab.game.World; +import lombok.Setter; public class GameController { @@ -69,6 +73,9 @@ public class GameController { @FXML private Label hits; private int hitcount = 0; + + @Setter + private App app; @FXML void fire(ActionEvent event) { @@ -137,6 +144,11 @@ public class GameController { updateHits(); } + public void updateData(Score score) { + Setting.getInstance().getScoreStorageInterface().save(score); + updateScoreTable(Setting.getInstance().getScoreStorageInterface().getAll()); + } + @FXML void initialize() { assert angle != null : "fx:id=\"angle\" was not injected: check your FXML file 'gameWindow.fxml'."; @@ -154,6 +166,19 @@ public class GameController { levelColumn.setCellValueFactory(new PropertyValueFactory<>("level")); btnDelete.setDisable(true); + scores.setRowFactory(tableView -> { + TableRow<Score> row = new TableRow<>(); + row.setOnMouseClicked(event -> { + if (event.getClickCount() >= 2 && event.getButton() == MouseButton.PRIMARY && row.getItem() != null) { + try { + GameController.this.app.createDialogStage(row.getItem()).show(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + return row; + }); scores.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); scores.getSelectionModel().getSelectedItems() .addListener((ListChangeListener.Change<? extends Score> change) -> diff --git a/src/main/java/lab/storage/FileStorage.java b/src/main/java/lab/storage/FileStorage.java index 828ca06..6e11b3a 100644 --- a/src/main/java/lab/storage/FileStorage.java +++ b/src/main/java/lab/storage/FileStorage.java @@ -10,6 +10,7 @@ import java.util.Comparator; import java.util.List; import java.util.stream.Stream; +import lab.data.Level; import lab.data.Score; public class FileStorage implements ScoreStorageInterface { @@ -21,7 +22,8 @@ public class FileStorage implements ScoreStorageInterface { if (Files.exists(Paths.get(SCORE_FILE_NAME))) { try (Stream<String> lines = Files.lines(Paths.get(SCORE_FILE_NAME))) { List<Score> result = lines.map(line -> line.split(";")) - .map(parts -> new Score(null, parts[0], Integer.parseInt(parts[1]), null)).toList(); + .map(parts -> new Score(null, parts[0], Integer.parseInt(parts[1]), Level.from(parts[2]))) + .toList(); return new ArrayList<>(result); } catch (IOException e) { e.printStackTrace(); @@ -34,7 +36,7 @@ public class FileStorage implements ScoreStorageInterface { public List<Score> getFirstTen() { List<Score> all = getAll(); Collections.sort(all, Comparator.comparing(Score::getPoints).reversed()); - return all.subList(0, 10); + return all.subList(0, Math.min(all.size(), 10)); } @Override @@ -51,9 +53,11 @@ public class FileStorage implements ScoreStorageInterface { } private void storeAll(List<Score> all) { - List<String> lines = all.stream().map(s -> String.format("%s;%d", s.getName(), s.getPoints())).toList(); + List<String> lines = all.stream().map(s -> String.format("%s;%d;%s", s.getName(), s.getPoints(), s.getLevel())) + .toList(); try { - Files.write(Paths.get(SCORE_FILE_NAME), lines, StandardOpenOption.TRUNCATE_EXISTING); + Files.write(Paths.get(SCORE_FILE_NAME), lines, StandardOpenOption.TRUNCATE_EXISTING, + StandardOpenOption.CREATE); } catch (IOException e) { e.printStackTrace(); } @@ -64,12 +68,12 @@ public class FileStorage implements ScoreStorageInterface { List<Score> all = getAll(); all.removeAll(scores); storeAll(all); - + } @Override public void stop() { - /*nothing to do*/ + /* nothing to do */ } } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index fb40c01..d3090b7 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -8,6 +8,7 @@ module cz.vsb.fei.java2.lab05_module { requires jakarta.persistence; requires com.h2database; requires org.hibernate.orm.core; + requires java.desktop; opens lab.gui to javafx.fxml; opens lab.data; diff --git a/src/main/resources/lab/gui/application.css b/src/main/resources/lab/gui/application.css index 83d6f33..7f0e980 100644 --- a/src/main/resources/lab/gui/application.css +++ b/src/main/resources/lab/gui/application.css @@ -1 +1,79 @@ -/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */ \ No newline at end of file +/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */ + +Label { + -fx-font-size: 20.0px; + -fx-padding: 10.0px; + -fx-text-fill: white; + -fx-font-weight: 900; +} + +#name{ + -fx-font-weight: 900; + -fx-font-size: 20.0px; + -fx-padding: 10.0px; + -fx-background-color: RGBA(0.0,0.0,255.0,0.5); + -fx-background-insets:5.0px; +} +#panel { + -fx-background-image:url("game-background.jpg"); + -fx-background-size: stretch; +} +#gamePanel { + -fx-background-color:RGB(0.0,0.0,100.0); +} +#menuPanel { + -fx-background-image:url("lochness-background.jpg"); + -fx-background-size: stretch; +} + +#content { + -fx-grid-lines-visible: true; +} + +#btnOk { + -fx-background-color: RGBA(0.0,255.0,0.0,0.5); +} + +#btnCancel { + -fx-background-color: RGBA(150.0,150.0,0.0,0.5); +} + +.actionButton:hover { + -fx-text-fill: white; +} + +#playButton { + -fx-background-color: RGBA(0.0,0.0,255.0,0.5); +} +#playButton:hover { + -fx-background-color: RGBA(0.0,0.0,255.0,0.5); + -fx-text-fill: white; +} + +.difficultButton .radio{ + visibility: hidden; +} +.difficultButton .dot{ + -fx-background-color: red; +} + +.difficultButton { + -fx-background-color: RGBA(0.0,0.0,100.0,0.8); + -fx-border-color: RGBA(0.0,0.0,100.0,0.8); + -fx-border-width:3px; + -fx-border-radius:30.0px; + -fx-text-fill: white; + -fx-font-size: 20.0px; + -fx-background-radius:30.0px; +} + +.difficultButton:hover{ + -fx-effect: dropshadow(gaussian, rgba(255, 255, 0, 0.7), 50.0, 0.7, 0.0, 0.0); + -fx-background-color : RGBA(50,0,0,0.8); +} + +.difficultButton:selected{ + -fx-background-color : RGBA(0,0,100,0.9); + -fx-border-color:RGBA(255,255,0,0.9); +} + diff --git a/src/main/resources/lab/gui/edit.fxml b/src/main/resources/lab/gui/edit.fxml new file mode 100644 index 0000000..b80cc5b --- /dev/null +++ b/src/main/resources/lab/gui/edit.fxml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.ColumnConstraints?> +<?import javafx.scene.layout.GridPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.RowConstraints?> +<?import javafx.scene.text.Font?> + +<BorderPane fx:id="menuPanel" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="lab.gui.EditController"> + <bottom> + <HBox BorderPane.alignment="CENTER"> + <children> + <Button fx:id="btnCancel" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnCancelAction" styleClass="actionButton" text="Cancle" HBox.hgrow="ALWAYS"> + <font> + <Font name="System Bold" size="51.0" /> + </font> + </Button> + <Button fx:id="btnOk" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnOkAction" styleClass="actionButton" text="Ok" HBox.hgrow="ALWAYS"> + <font> + <Font name="System Bold" size="51.0" /> + </font> + </Button> + </children> + </HBox> + </bottom> + <center> + <GridPane fx:id="content" BorderPane.alignment="CENTER"> + <columnConstraints> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> + </columnConstraints> + <rowConstraints> + <RowConstraints minHeight="10.0" vgrow="NEVER" /> + </rowConstraints> + </GridPane> + </center> + <top> + <Label fx:id="txtTitle" text="Title" BorderPane.alignment="CENTER"> + <font> + <Font name="System Bold" size="48.0" /> + </font> + </Label> + </top> +</BorderPane> -- GitLab