diff --git a/src/main/java/edu/ntnu/idi/idatt/Launcher.java b/src/main/java/edu/ntnu/idi/idatt/Launcher.java index b77e8d8..18a6b15 100644 --- a/src/main/java/edu/ntnu/idi/idatt/Launcher.java +++ b/src/main/java/edu/ntnu/idi/idatt/Launcher.java @@ -2,7 +2,8 @@ import edu.ntnu.idi.idatt.storage.CSVtoJSON; import edu.ntnu.idi.idatt.view.SceneManager; -import edu.ntnu.idi.idatt.view.primary.MainView; +import edu.ntnu.idi.idatt.view.primary.PrimaryController; +import edu.ntnu.idi.idatt.view.primary.PrimaryModel; import edu.ntnu.idi.idatt.view.primary.PrimaryView; import javafx.application.Application; import javafx.stage.Stage; @@ -23,7 +24,15 @@ public void start(Stage stage) { stage.setWidth(1200); stage.setHeight(700); stage.setTitle("Stock Game"); - SceneManager.init(stage, new MainView().getInstance()); + + PrimaryModel model = new PrimaryModel(); + PrimaryView view = new PrimaryView(); + PrimaryController controller = new PrimaryController(model); + + view.setModel(model); + view.setController(controller); + + SceneManager.init(stage, view.getInstance()); stage.show(); CSVtoJSON ja = new CSVtoJSON(); ja.csvFile(); diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractController.java b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractController.java new file mode 100644 index 0000000..a334769 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractController.java @@ -0,0 +1,11 @@ +package edu.ntnu.idi.idatt.view.components; + +public abstract class AbstractController { + + protected final M model; + + public AbstractController(M model) { + this.model = model; + } + +} diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/Model.java b/src/main/java/edu/ntnu/idi/idatt/view/components/Model.java new file mode 100644 index 0000000..2465fd7 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/Model.java @@ -0,0 +1,4 @@ +package edu.ntnu.idi.idatt.view.components; + +public interface Model { +} diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryController.java new file mode 100644 index 0000000..2fe27fa --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryController.java @@ -0,0 +1,51 @@ +package edu.ntnu.idi.idatt.view.primary; + +import java.io.File; +import java.math.BigDecimal; + +import edu.ntnu.idi.idatt.view.components.AbstractController; +import javafx.stage.FileChooser; + +public class PrimaryController extends AbstractController { + + private File csv; + + public PrimaryController(PrimaryModel model) { + super(model); + } + + public void obtainCSVFile() { + csv = new FileChooser().showOpenDialog(null); + if (csv != null) { + model.getFileName().set(csv.getName()); + } + } + + public void initializeGame() { + model.getError().set(" "); // Empty buffers + + if (model.getName().get() == null || model.getBalance().get() == null) { + model.getError().set("Name and/or balance fields can't be empty"); + return; + } + + if (model.getName().get().isBlank() || + model.getBalance().get().isBlank()) { + model.getError().set("Name and/or balance fields can't be empty"); + return; + } + + try { + BigDecimal balance = new BigDecimal(model.getBalance().get()); + } catch (NumberFormatException e) { + model.getError().set("The balance must be a number format!"); + return; + } + + if (csv == null) { + model.getError().set("Specify the stocks .csv file!"); + return; + } + } + +} diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryModel.java new file mode 100644 index 0000000..440ea91 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryModel.java @@ -0,0 +1,30 @@ +package edu.ntnu.idi.idatt.view.primary; + +import edu.ntnu.idi.idatt.view.components.Model; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + +public class PrimaryModel implements Model { + + private final StringProperty name = new SimpleStringProperty(); + private final StringProperty balance = new SimpleStringProperty(); + private final StringProperty error = new SimpleStringProperty(); + private final StringProperty fileName = new SimpleStringProperty(); + + public StringProperty getName() { + return name; + } + + public StringProperty getBalance() { + return balance; + } + + public StringProperty getError() { + return error; + } + + public StringProperty getFileName() { + return fileName; + } + +} diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryView.java index 7e94df1..c107572 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryView.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryView.java @@ -6,12 +6,27 @@ import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Parent; +import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; public class PrimaryView extends AbstractView { + // Globlal variables for model implementation + private TextField nameField; + private TextField balanceField; + private Label fileLabel; + private Label errorLabel; + + // Global buttons for controller implementation + private Button csvButton; + private Button startButton; + public PrimaryView() { super(new StackPane()); this.getInstance().getStyleClass().add("dark"); @@ -19,27 +34,88 @@ public PrimaryView() { @Override public Parent createContent() { - StackPane root = new StackPane(); + VBox root = new VBox(); root.getStyleClass().add("light"); - StackPane.setAlignment(root, Pos.CENTER); + root.setAlignment(Pos.TOP_CENTER); StackPane.setMargin(root, new Insets(40.0)); Label title = new Label("Millions"); title.getStyleClass().add("title"); - StackPane.setAlignment(title, Pos.TOP_CENTER); + // Create and style wrappers VBox wrapper = new VBox(); + HBox playerWrapper = new HBox(); + HBox balanceWrapper = new HBox(); + playerWrapper.setAlignment(Pos.CENTER_LEFT); + balanceWrapper.setAlignment(Pos.CENTER_LEFT); + // Player name label and input field Label playerName = new Label("Player name:"); playerName.getStyleClass().add("big-text-32"); + nameField = new TextField(); + nameField.setPromptText("Leonardo Dicaprio"); + nameField.setFocusTraversable(false); + nameField.getStyleClass().add("button"); + playerWrapper.getChildren().addAll(List.of(playerName, nameField)); + + // Start balance label and input field Label startBalance = new Label("Start balance:"); startBalance.getStyleClass().add("big-text-32"); - wrapper.getChildren().addAll(List.of(playerName, startBalance)); + balanceField = new TextField(); + balanceField.setPromptText("2500"); + balanceField.setFocusTraversable(false); + balanceField.getStyleClass().add("button"); + balanceWrapper.getChildren().addAll(List.of(startBalance, balanceField)); + + // CSV import button and label + + HBox csvWrapper = new HBox(); + csvWrapper.setAlignment(Pos.CENTER_LEFT); + + csvButton = new Button("Import CSV"); + csvButton.getStyleClass().add("button"); + + fileLabel = new Label(); + fileLabel.getStyleClass().add("med-text-16"); + + csvWrapper.getChildren().addAll(csvButton, fileLabel); + VBox.setMargin(csvWrapper, new Insets(0.0, 0.0, 0.0, 50.0)); + + // Start game button and error log + startButton = new Button("Start Game"); + startButton.getStyleClass().add("button"); + startButton.setMaxWidth(200); + VBox.setMargin(startButton, new Insets(40.0)); + + errorLabel = new Label(); + errorLabel.getStyleClass().add("med-text-16"); + errorLabel.setStyle("-fx-text-fill: red;"); + + // Region filler + Region filler = new Region(); + VBox.setVgrow(filler, Priority.ALWAYS); + + // Wrap components together and adjust positioning + wrapper.getChildren().addAll(List.of(playerWrapper, balanceWrapper, csvWrapper)); + wrapper.setAlignment(Pos.BASELINE_LEFT); + + root.getChildren().addAll(List.of(title, wrapper, filler, errorLabel, startButton)); - root.getChildren().addAll(List.of(title, wrapper)); return root; } + public void setModel(PrimaryModel model) { + this.nameField.textProperty().bindBidirectional(model.getName()); + this.balanceField.textProperty().bindBidirectional(model.getBalance()); + this.errorLabel.textProperty().bind(model.getError()); + this.fileLabel.textProperty().bind(model.getFileName()); + } + + public void setController(PrimaryController controller) { + this.csvButton.setOnAction(e -> controller.obtainCSVFile()); + this.startButton.setOnAction(e -> controller.initializeGame()); + } + } diff --git a/src/main/resources/themes/default.css b/src/main/resources/themes/default.css index a50ca96..2e79159 100644 --- a/src/main/resources/themes/default.css +++ b/src/main/resources/themes/default.css @@ -26,3 +26,28 @@ -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 10, 0.5, 0, 5); } +.med-text-16{ + -fx-font-size: 16px; + -fx-font-weight: 700; + -fx-text-fill: #EEEEEE; + -fx-padding: 30px; +} + +/* ======================= + BUTTON STYLE + ======================= */ +.button { + -fx-font-size: 16px; + -fx-text-fill: black; + -fx-background-color: #FFFFFF; + -fx-background-radius: 20; + -fx-border-radius: 20; + -fx-padding: 10 20 10 20; + -fx-cursor: hand; + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 6, 0.3, 0, 2); +} + +.button:hover { + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.4), 8, 0.4, 0, 4); + -fx-translate-y: 1; +}