diff --git a/.gitignore b/.gitignore index e4a159670c17c260446ba6a3b5e10d6ae7adf2b0..3a516dda874e5a18113855e318fdab8da99860b6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ .project .classpath *.mv.db -*.trace.db \ No newline at end of file +*.trace.db +.idea/ diff --git a/pom.xml b/pom.xml index 1d7427f6f5769e146e5f4022e4d914c38e992b18..4fa51e1ba3f37f49f3dbe079e3d03b6d074f1ff3 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-v3</artifactId> + <artifactId>java2-lab10-v3</artifactId> <version>0.0.1-SNAPHOST</version> <packaging>jar</packaging> - <name>java2-lab09-v3</name> + <name>java2-lab10-v3</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>21</maven.compiler.source> diff --git a/scores.csv b/scores.csv new file mode 100644 index 0000000000000000000000000000000000000000..1ed1b37d391570a7e589bc3b6c42ca305f4a5207 --- /dev/null +++ b/scores.csv @@ -0,0 +1,6 @@ +StackSultan;66;MEDIUM +SnapMaster;167;MEDIUM +TikTokTornado;210;EASY +ScriptSensei;158;EASY +SnapMasteraaa;167000;null +ScriptSenseidddd;1580000;null diff --git a/src/main/java/lab/data/Level.java b/src/main/java/lab/data/Level.java index 4c8e6bdc522cf341b1a20515853f8f019484998d..46f7b950f00ace764c4bc0bee406424a08e023bc 100644 --- a/src/main/java/lab/data/Level.java +++ b/src/main/java/lab/data/Level.java @@ -2,4 +2,13 @@ package lab.data; public enum Level { 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 b2e58576f7e70d69b9e08bc2fdb10b5f8d8045be..7d8ea2a7d39fb03949ec4d065e7daf0764cd5da1 100644 --- a/src/main/java/lab/gui/App.java +++ b/src/main/java/lab/gui/App.java @@ -13,9 +13,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.Setup; +import lab.data.Score; import lab.storage.FileStorage; /** @@ -28,7 +31,7 @@ public class App extends Application { private static Logger log = LogManager.getLogger(App.class); private GameController gameController; - + private MainScreenController menuController; private boolean viewMode; private Stage primaryStage; @@ -74,13 +77,32 @@ public class App extends Application { // Construct a main window with a canvas. FXMLLoader menuLoader = new FXMLLoader(getClass().getResource("/lab/gui/mainScreen.fxml")); Parent root = menuLoader.load(); - MainScreenController menuController = menuLoader.getController(); + menuController = menuLoader.getController(); menuController.setApp(this); Scene scene = new Scene(root); URL cssUrl = getClass().getResource("application.css"); scene.getStylesheets().add(cssUrl.toString()); primaryStage.setScene(scene); } + + 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.setMainScreenController(menuController); + 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 { diff --git a/src/main/java/lab/gui/EditController.java b/src/main/java/lab/gui/EditController.java new file mode 100644 index 0000000000000000000000000000000000000000..e5ad2fe3575de6cac89a019f8a9390acaf96e004 --- /dev/null +++ b/src/main/java/lab/gui/EditController.java @@ -0,0 +1,112 @@ +package lab.gui; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javafx.collections.ListChangeListener; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.geometry.HPos; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.SelectionMode; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableRow; +import javafx.scene.control.TableView; +import javafx.scene.control.TextField; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.ToggleGroup; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.GridPane; +import javafx.scene.text.Text; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import lab.Setup; +import lab.data.Score; +import lab.game.Difficult; +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 MainScreenController mainScreenController; + + @FXML + void btnOkAction(ActionEvent event) { + //TODO: add code to read values from text fields + + mainScreenController.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/MainScreenController.java b/src/main/java/lab/gui/MainScreenController.java index 07d483b025f89473b3c8b282d89c33a9aaab87cd..1c969131c6fe9d9164484ec6e974df0f02d1afe1 100644 --- a/src/main/java/lab/gui/MainScreenController.java +++ b/src/main/java/lab/gui/MainScreenController.java @@ -10,14 +10,23 @@ import org.apache.logging.log4j.Logger; import javafx.collections.ListChangeListener; import javafx.event.ActionEvent; import javafx.fxml.FXML; +import javafx.scene.Group; +import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; +import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import javafx.scene.control.TextField; import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleGroup; import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.text.Text; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.StageStyle; import lab.Setup; import lab.data.Score; import lab.game.Difficult; @@ -41,7 +50,6 @@ public class MainScreenController { @FXML private Button btnDelete; - @FXML private TableView<Score> scores; @@ -97,7 +105,7 @@ public class MainScreenController { void btnLoadFirstTenAction(ActionEvent event) { updateScoreTable(Setup.getInstance().getScoreStorageInterface().getFirstTen()); } - + @FXML void btnDeleteAction(ActionEvent event) { List<Score> selectedScores = new ArrayList<>(scores.getSelectionModel().getSelectedItems()); @@ -110,6 +118,11 @@ public class MainScreenController { this.scores.getItems().addAll(scores); } + public void updateData(Score score) { + Setup.getInstance().getScoreStorageInterface().save(score); + updateScoreTable(Setup.getInstance().getScoreStorageInterface().getAll()); + } + @FXML void initialize() { assert difficult != null : "fx:id=\"difficult\" was not injected: check your FXML file 'mainScreen.fxml'."; @@ -123,10 +136,23 @@ public class MainScreenController { difficultColumn.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 { + MainScreenController.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) -> - btnDelete.setDisable(change.getList().isEmpty())); + .addListener((ListChangeListener.Change<? extends Score> change) -> btnDelete + .setDisable(change.getList().isEmpty())); initStorage(); log.info("Screeen initialized."); diff --git a/src/main/java/lab/storage/FileStorage.java b/src/main/java/lab/storage/FileStorage.java index 828ca068af9f5b7539ab0dec4c62fedf417d4fc4..71f3c3eb91ff348533eedcb25478b32b74101889 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,7 @@ 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 +35,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 +52,9 @@ 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(); } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index abec1388d0a3157f5921212a8964fbb36fed1e4d..4839703376012335f8d4ec899d2ed839b46d18f1 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -8,6 +8,7 @@ module lab05_module { requires com.h2database; requires jakarta.persistence; requires org.hibernate.orm.core; + requires java.desktop; opens lab.gui to javafx.fxml; opens lab.data to javafx.base,org.hibernate.orm.core; diff --git a/src/main/resources/lab/gui/application.css b/src/main/resources/lab/gui/application.css index 0ef5f16d2f48ec78d47f3fb51574fd4d86e33022..7f0e980478ac54ba9285d55c081a99e94305ece5 100644 --- a/src/main/resources/lab/gui/application.css +++ b/src/main/resources/lab/gui/application.css @@ -26,6 +26,22 @@ Label { -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); } diff --git a/src/main/resources/lab/gui/edit.fxml b/src/main/resources/lab/gui/edit.fxml new file mode 100644 index 0000000000000000000000000000000000000000..b80cc5b9bc0c2831d0b37d36f9be472e3dcd02eb --- /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>