diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java
index 90050c1..3053f88 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java
@@ -3,12 +3,17 @@
import edu.ntnu.idi.idatt2003.g40.mappe.model.Stock;
import edu.ntnu.idi.idatt2003.g40.mappe.service.FileConverter;
import edu.ntnu.idi.idatt2003.g40.mappe.service.FileParser;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.SaveGameService;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
import edu.ntnu.idi.idatt2003.g40.mappe.utils.ConfigValues;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewManager;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ingame.InGameView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.mainmenu.MainMenuController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.mainmenu.MainMenuView;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.playgame.PlayGameController;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.playgame.PlayGameView;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.settings.SettingsController;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.settings.SettingsView;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
@@ -26,6 +31,7 @@
*
Initializes the application through the javafx framework.
* */
public class Main extends Application {
+
static void main() {
FileParser parser1 = new FileParser("src/main/resources/dummydata.txt");
FileConverter converter1 = new FileConverter();
@@ -50,17 +56,37 @@ public void start(final Stage stage) throws Exception {
stage.setScene(scene);
stage.setWidth(ConfigValues.VIEWPORT_WIDTH.getValue());
stage.setHeight(ConfigValues.VIEWPORT_HEIGHT.getValue());
+
EventManager eventManager = new EventManager();
ViewManager viewManager = new ViewManager(stage, eventManager);
+ // Main menu
MainMenuView mainMenuView = new MainMenuView();
new MainMenuController(mainMenuView, eventManager);
+ // Play game (mellom hovedmeny og spillet)
+ PlayGameView playGameView = new PlayGameView();
+ new PlayGameController(playGameView, eventManager);
+
+ // Last lagrede spill fra disk.
+ SaveGameService saveGameService = new SaveGameService();
+ playGameView.setSaves(saveGameService.loadSaves());
+
+
+ // Settings
+ SettingsView settingsView = new SettingsView();
+ new SettingsController(settingsView, eventManager);
+
+ // In-game
InGameView inGameView = new InGameView();
+ // Registrer alle views og start på hovedmenyen
viewManager.addView(mainMenuView);
+ viewManager.addView(playGameView);
+ viewManager.addView(settingsView);
viewManager.addView(inGameView);
viewManager.setScene(mainMenuView);
+
stage.show();
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/SaveGame.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/SaveGame.java
new file mode 100644
index 0000000..e22273f
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/SaveGame.java
@@ -0,0 +1,47 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.model;
+
+/**
+ * Represents one save game entry.
+ *
+ *
+ * Holds the display name and the current balance for a single
+ * saved game.
+ *
+ */
+public class SaveGame {
+
+ /** Display name of the save. */
+ private final String name;
+
+ /** Current balance in the save. */
+ private final double balance;
+
+ /**
+ * Constructor.
+ *
+ * @param name the display name of the save.
+ * @param balance the current balance value.
+ */
+ public SaveGame(final String name, final double balance) {
+ this.name = name;
+ this.balance = balance;
+ }
+
+ /**
+ * Getter method for the name.
+ *
+ * @return the save name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Getter method for the balance.
+ *
+ * @return the balance value.
+ */
+ public double getBalance() {
+ return balance;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaveGameService.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaveGameService.java
new file mode 100644
index 0000000..82b310d
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaveGameService.java
@@ -0,0 +1,107 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.service;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.model.SaveGame;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Service for loading and saving {@link SaveGame} entries from disk.
+ *
+ *
+ * Save file format (one entry per line):
+ *
+ *
+ *
+ * # Comment lines start with hash
+ * SaveName, 1234567.89
+ *
+ *
+ *
+ * Lines that don't match the expected format are skipped.
+ *
+ */
+public class SaveGameService {
+
+ /** Default location of the save file. */
+ private static final String DEFAULT_PATH = "src/main/resources/saves.txt";
+
+ /** Path to the save file. */
+ private final String filePath;
+
+ /**
+ * Constructor with default path.
+ */
+ public SaveGameService() {
+ this(DEFAULT_PATH);
+ }
+
+ /**
+ * Constructor with custom path.
+ *
+ * @param filePath the path to the save file.
+ */
+ public SaveGameService(final String filePath) {
+ this.filePath = filePath;
+ }
+
+ /**
+ * Loads all save games from the file.
+ *
+ *
+ * Returns an empty list if the file cannot be read or is empty.
+ *
+ *
+ * @return the loaded {@link SaveGame} entries.
+ */
+ public List loadSaves() {
+ List saves = new ArrayList<>();
+ Path path = Paths.get(filePath);
+ try {
+ List lines = Files.readAllLines(path);
+ for (String line : lines) {
+ SaveGame save = parseLine(line);
+ if (save != null) {
+ saves.add(save);
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("Could not read save file: " + e.getMessage());
+ }
+ return saves;
+ }
+
+ /**
+ * Parses a single line into a {@link SaveGame}.
+ *
+ *
+ * Returns null for invalid lines, comment lines, and blank lines.
+ *
+ *
+ * @param line the raw line from the file.
+ * @return the parsed {@link SaveGame}, or null if the line is invalid.
+ */
+ private SaveGame parseLine(final String line) {
+ if (line == null || line.isBlank() || line.trim().startsWith("#")) {
+ return null;
+ }
+ String[] parts = line.split(",");
+ if (parts.length != 2) {
+ return null;
+ }
+ try {
+ String name = parts[0].trim();
+ double balance = Double.parseDouble(parts[1].trim());
+ if (name.isEmpty()) {
+ return null;
+ }
+ return new SaveGame(name, balance);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewElement.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewElement.java
index 554ccfc..aa0f941 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewElement.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewElement.java
@@ -146,4 +146,11 @@ public ArrayList getButtons() {
public void setData(final T2 data) {
setViewName(data.getSceneName());
}
+
+ /**
+ * Method called when updating a view.
+ * */
+ public void onUpdate() {
+
+ }
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuController.java
index 167079b..bf2f1c5 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuController.java
@@ -5,37 +5,50 @@
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventType;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewData;
+import javafx.application.Platform;
/**
* Controller for the {@link MainMenuView}.
*
- * Extends {@link ViewController}
- * */
+ *
+ * Extends {@link ViewController}
+ *
+ */
public class MainMenuController extends ViewController {
/**
* Constructor.
*
- * @param view The {@link MainMenuView} object to attach this controller to.
+ * @param view The {@link MainMenuView} object to attach this controller
+ * to.
* @param eventManager the active {@link EventManager}.
- * */
+ */
public MainMenuController(final MainMenuView view,
- final EventManager eventManager) {
+ final EventManager eventManager) {
super(view, eventManager);
}
/**
* {@inheritDoc}
*
- * Sets play game button functionality
- * */
+ *
+ * Sets play game, settings, and exit button functionality.
+ *
+ */
@Override
protected void initInteractions() {
getViewElement().getToGameButton().setOnAction(e -> {
- ViewData viewData = new ViewData("InGameView");
- EventData eventData =
- new EventData<>(EventType.SCENE_CHANGE, viewData);
+ ViewData viewData = new ViewData("PlayGameView");
+ EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
invoke(eventData, getEventManager());
});
+
+ getViewElement().getSettingsButton().setOnAction(e -> {
+ ViewData viewData = new ViewData("SettingsView");
+ EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
+ getEventManager().invokeEvent(eventData);
+ });
+
+ getViewElement().getExitButton().setOnAction(e -> Platform.exit());
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuView.java
index 68527f0..2ab0584 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuView.java
@@ -116,4 +116,5 @@ protected void initStyling() {
settingsButton.getStyleClass().add("menu-button");
exitButton.getStyleClass().add("menu-button");
}
+
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameController.java
new file mode 100644
index 0000000..0f8472c
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameController.java
@@ -0,0 +1,57 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.playgame;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventData;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventType;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewData;
+
+/**
+ * Controller for the {@link PlayGameView}.
+ *
+ *
+ * Extends {@link ViewController}
+ *
+ */
+public class PlayGameController extends ViewController {
+
+ /**
+ * Constructor.
+ *
+ * @param view The {@link PlayGameView} object to attach this controller
+ * to.
+ * @param eventManager the active {@link EventManager}.
+ */
+ public PlayGameController(final PlayGameView view,
+ final EventManager eventManager) {
+ super(view, eventManager);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ *
+ * Sets create new game, back, and save-row click functionality.
+ *
+ */
+ @Override
+ protected void initInteractions() {
+ getViewElement().getCreateNewGameButton().setOnAction(e -> {
+ ViewData viewData = new ViewData("InGameView");
+ EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
+ getEventManager().invokeEvent(eventData);
+ });
+
+ getViewElement().getBackButton().setOnAction(e -> {
+ ViewData viewData = new ViewData("MainMenu");
+ EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
+ getEventManager().invokeEvent(eventData);
+ });
+
+ getViewElement().setOnSaveSelected(save -> {
+ ViewData viewData = new ViewData("InGameView");
+ EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
+ getEventManager().invokeEvent(eventData);
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameView.java
new file mode 100644
index 0000000..ca8459b
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameView.java
@@ -0,0 +1,196 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.playgame;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.model.SaveGame;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Cursor;
+import javafx.scene.control.Button;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+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;
+import javafx.scene.text.Text;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ * View shown after the player clicks "Play" on the main menu.
+ *
+ *
+ * Displays a list of existing save games and two action buttons:
+ * "Create new game" and "Back".
+ *
+ *
+ *
+ * Extends {@link ViewElement} with a {@link StackPane} root so a
+ * background image can sit behind the central panel.
+ *
+ */
+public class PlayGameView extends ViewElement {
+
+ /** "Create new game" button. */
+ private Button createNewGameButton;
+
+ /** "Back" button. */
+ private Button backButton;
+
+ /** Vertical container holding the save rows. Rebuilt on every update. */
+ private VBox saveListContainer;
+
+ /** Bottom row with the two action buttons. */
+ private HBox bottomButtonRow;
+
+ /** Centered panel: save list + bottom buttons stacked. */
+ private VBox mainPanel;
+
+ /** Background image displayed behind the panel. */
+ private ImageView backgroundImage;
+
+ /** Current saves to display. Replaced via {@link #setSaves}. */
+ private List saves = new ArrayList<>();
+
+ /** Callback invoked when a save row is clicked. */
+ private Consumer onSaveSelected = save -> {
+ };
+
+ /**
+ * Constructor.
+ *
+ *
+ * Constructs with name "PlayGameView"
+ *
+ */
+ public PlayGameView() {
+ super(new StackPane(), "PlayGameView");
+ }
+
+ public Button getCreateNewGameButton() {
+ return createNewGameButton;
+ }
+
+ public Button getBackButton() {
+ return backButton;
+ }
+
+ /**
+ * Sets the list of saves to display and rebuilds the rows.
+ *
+ * @param saves saves to display.
+ */
+ public void setSaves(final List saves) {
+ this.saves = new ArrayList<>(saves);
+ rebuildSaveList();
+ }
+
+ /**
+ * Sets the handler called when a save row is clicked.
+ *
+ * @param handler callback receiving the selected save.
+ */
+ public void setOnSaveSelected(final Consumer handler) {
+ this.onSaveSelected = (handler != null) ? handler : save -> {
+ };
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void initLayout() {
+ backgroundImage = new ImageView(new Image(Objects.requireNonNull(
+ getClass().getResourceAsStream("/millionsbackground.png"))));
+ backgroundImage.setPreserveRatio(false);
+
+ saveListContainer = new VBox(8);
+ saveListContainer.setAlignment(Pos.TOP_CENTER);
+ saveListContainer.setPadding(new Insets(20));
+
+ createNewGameButton = new Button("Create new game");
+ backButton = new Button("Back");
+
+ bottomButtonRow = new HBox(40, createNewGameButton, backButton);
+ bottomButtonRow.setAlignment(Pos.CENTER);
+
+ mainPanel = new VBox(30, saveListContainer, bottomButtonRow);
+ mainPanel.setAlignment(Pos.CENTER);
+ mainPanel.setPadding(new Insets(40));
+ mainPanel.setMaxWidth(700);
+
+ getRootPane().getChildren().addAll(backgroundImage, mainPanel);
+
+ // Make the background fill the root pane.
+ backgroundImage.fitWidthProperty().bind(getRootPane().widthProperty());
+ backgroundImage.fitHeightProperty().bind(getRootPane().heightProperty());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void initStyling() {
+ getRootPane().getStyleClass().add("main-menu-bg");
+ saveListContainer.getStyleClass().add("save-list");
+ createNewGameButton.getStyleClass().add("menu-button");
+ backButton.getStyleClass().add("menu-button");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onUpdate() {
+ rebuildSaveList();
+ }
+
+ /**
+ * Clears and recreates all save rows from the {@link #saves} list.
+ */
+ private void rebuildSaveList() {
+ if (saveListContainer == null || saves == null) {
+ return;
+ }
+ saveListContainer.getChildren().clear();
+ for (SaveGame save : saves) {
+ saveListContainer.getChildren().add(buildSaveRow(save));
+ }
+ }
+
+ /**
+ * Builds a single row displaying the save name on the left and the
+ * balance (with sign and currency suffix) on the right.
+ */
+ private HBox buildSaveRow(final SaveGame save) {
+ Text nameText = new Text(save.getName());
+ nameText.getStyleClass().add("save-name");
+
+ Region spacer = new Region();
+ HBox.setHgrow(spacer, Priority.ALWAYS);
+
+ Text balanceText = new Text(formatBalance(save.getBalance()));
+ balanceText.getStyleClass().add(
+ save.getBalance() >= 0 ? "save-balance-positive" : "save-balance-negative");
+
+ HBox row = new HBox(20, nameText, spacer, balanceText);
+ row.setAlignment(Pos.CENTER_LEFT);
+ row.setPadding(new Insets(12, 24, 12, 24));
+ row.getStyleClass().add("save-row");
+ row.setCursor(Cursor.HAND);
+ row.setOnMouseClicked(e -> onSaveSelected.accept(save));
+ return row;
+ }
+
+ /**
+ * Formats a balance value as Norwegian currency, e.g. "+1.000.650.901,43kr"
+ * or "-1.000.000.000,00kr".
+ */
+ private String formatBalance(final double balance) {
+ DecimalFormatSymbols symbols = new DecimalFormatSymbols();
+ symbols.setGroupingSeparator('.');
+ symbols.setDecimalSeparator(',');
+ DecimalFormat df = new DecimalFormat("+#,##0.00;-#,##0.00", symbols);
+ return df.format(balance) + "kr";
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsController.java
new file mode 100644
index 0000000..c364624
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsController.java
@@ -0,0 +1,50 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.settings;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventData;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventType;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewData;
+
+/**
+ * Controller for {@link SettingsView}.
+ *
+ *
+ * Wires up the category buttons to switch the right-hand content,
+ * and the Back button to return to the main menu.
+ *
+ */
+public class SettingsController extends ViewController {
+
+ /**
+ * Constructor.
+ *
+ * @param view the {@link SettingsView} this controller is attached to.
+ * @param eventManager the active {@link EventManager}.
+ */
+ public SettingsController(final SettingsView view,
+ final EventManager eventManager) {
+ super(view, eventManager);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void initInteractions() {
+ getViewElement().getAudioButton().setOnAction(e -> getViewElement().showAudioSection());
+
+ getViewElement().getVideoButton().setOnAction(e -> getViewElement().showVideoSection());
+
+ getViewElement().getHotKeysButton().setOnAction(e -> getViewElement().showHotKeysSection());
+
+ getViewElement().getBackButton().setOnAction(e -> changeScene("MainMenu"));
+ }
+
+ /**
+ * Helper that fires a SCENE_CHANGE event toward the given scene name.
+ */
+ private void changeScene(final String sceneName) {
+ ViewData viewData = new ViewData(sceneName);
+ EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
+ getEventManager().invokeEvent(eventData);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsView.java
new file mode 100644
index 0000000..c5b2d21
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsView.java
@@ -0,0 +1,195 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.settings;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.Slider;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+
+import java.util.Objects;
+
+/**
+ * View shown when the player clicks "Settings" on the main menu.
+ *
+ *
+ * Layout: left sidebar with category buttons (audio, video, hot keys)
+ * and a Back button at the bottom. Right pane shows the content for the
+ * currently selected category.
+ *
+ */
+public class SettingsView extends ViewElement {
+
+ /** Category buttons on the left side. */
+ private Button audioButton;
+ private Button videoButton;
+ private Button hotKeysButton;
+
+ /** Bottom-left back button. */
+ private Button backButton;
+
+ /** The currently displayed content pane on the right side. */
+ private StackPane contentArea;
+
+ /** Master volume slider for the audio section. */
+ private Slider masterVolumeSlider;
+
+ /** Background image displayed behind the panel. */
+ private ImageView backgroundImage;
+
+ /** Main border layout containing the sidebar and content area. */
+ private BorderPane mainPanel;
+
+ /**
+ * Constructor.
+ *
+ *
+ * Constructs with name "SettingsView"
+ *
+ */
+ public SettingsView() {
+ super(new StackPane(), "SettingsView");
+ }
+
+ public Button getAudioButton() {
+ return audioButton;
+ }
+
+ public Button getVideoButton() {
+ return videoButton;
+ }
+
+ public Button getHotKeysButton() {
+ return hotKeysButton;
+ }
+
+ public Button getBackButton() {
+ return backButton;
+ }
+
+ public Slider getMasterVolumeSlider() {
+ return masterVolumeSlider;
+ }
+
+ /**
+ * Replaces the content area with the audio section (master volume).
+ */
+ public void showAudioSection() {
+ Label title = new Label("master volume");
+ title.getStyleClass().add("settings-title");
+
+ masterVolumeSlider = new Slider(0, 100, 50);
+ masterVolumeSlider.setMaxWidth(360);
+ masterVolumeSlider.getStyleClass().add("settings-slider");
+
+ VBox audioBox = new VBox(20, title, masterVolumeSlider);
+ audioBox.setAlignment(Pos.TOP_CENTER);
+ audioBox.setPadding(new Insets(30));
+
+ contentArea.getChildren().setAll(audioBox);
+ }
+
+ /**
+ * Replaces the content area with the video section placeholder.
+ */
+ public void showVideoSection() {
+ Label title = new Label("video");
+ title.getStyleClass().add("settings-title");
+ Label placeholder = new Label("(video settings coming soon)");
+ placeholder.getStyleClass().add("settings-placeholder");
+
+ VBox videoBox = new VBox(20, title, placeholder);
+ videoBox.setAlignment(Pos.TOP_CENTER);
+ videoBox.setPadding(new Insets(30));
+
+ contentArea.getChildren().setAll(videoBox);
+ }
+
+ /**
+ * Replaces the content area with the hot keys section placeholder.
+ */
+ public void showHotKeysSection() {
+ Label title = new Label("hot keys");
+ title.getStyleClass().add("settings-title");
+ Label placeholder = new Label("(hot key bindings coming soon)");
+ placeholder.getStyleClass().add("settings-placeholder");
+
+ VBox hotKeysBox = new VBox(20, title, placeholder);
+ hotKeysBox.setAlignment(Pos.TOP_CENTER);
+ hotKeysBox.setPadding(new Insets(30));
+
+ contentArea.getChildren().setAll(hotKeysBox);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void initLayout() {
+ backgroundImage = new ImageView(new Image(Objects.requireNonNull(
+ getClass().getResourceAsStream("/millionsbackground.png"))));
+ backgroundImage.setPreserveRatio(false);
+
+ audioButton = new Button("audio");
+ videoButton = new Button("video");
+ hotKeysButton = new Button("hot keys");
+ backButton = new Button("Back");
+
+ // Spacer pushes the Back button to the bottom of the sidebar.
+ Region spacer = new Region();
+ VBox.setVgrow(spacer, javafx.scene.layout.Priority.ALWAYS);
+
+ VBox sidebar = new VBox(15,
+ audioButton, videoButton, hotKeysButton, spacer, backButton);
+ sidebar.setAlignment(Pos.TOP_LEFT);
+ sidebar.setPadding(new Insets(30));
+ sidebar.setPrefWidth(180);
+
+ contentArea = new StackPane();
+ contentArea.setPadding(new Insets(30));
+
+ mainPanel = new BorderPane();
+ mainPanel.setLeft(sidebar);
+ mainPanel.setCenter(contentArea);
+ mainPanel.setMaxWidth(800);
+ mainPanel.setMaxHeight(500);
+
+ // Center the BorderPane on top of the background.
+ HBox centerWrapper = new HBox(mainPanel);
+ centerWrapper.setAlignment(Pos.CENTER);
+
+ getRootPane().getChildren().addAll(backgroundImage, centerWrapper);
+
+ // Make the background fill the root pane.
+ backgroundImage.fitWidthProperty().bind(getRootPane().widthProperty());
+ backgroundImage.fitHeightProperty().bind(getRootPane().heightProperty());
+
+ // Default section shown when settings opens.
+ showAudioSection();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void initStyling() {
+ getRootPane().getStyleClass().add("main-menu-bg");
+ mainPanel.getStyleClass().add("settings-panel");
+ audioButton.getStyleClass().add("settings-tab-button");
+ videoButton.getStyleClass().add("settings-tab-button");
+ hotKeysButton.getStyleClass().add("settings-tab-button");
+ backButton.getStyleClass().add("settings-tab-button");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onUpdate() {
+ // Reset til audio-section hver gang viewet vises.
+ if (contentArea != null) {
+ showAudioSection();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/saves.txt b/src/main/resources/saves.txt
new file mode 100644
index 0000000..fec18df
--- /dev/null
+++ b/src/main/resources/saves.txt
@@ -0,0 +1,5 @@
+# Save file format: name, balance
+# Lines starting with # are comments
+
+fuck, -1000000000.00
+Halleluja, 1000650901.43
\ No newline at end of file
diff --git a/src/main/resources/styles.css b/src/main/resources/styles.css
index ee0886f..7fc3640 100644
--- a/src/main/resources/styles.css
+++ b/src/main/resources/styles.css
@@ -10,7 +10,8 @@
/* Base button styling */
.menu-button {
- -fx-background-color: rgba(255, 255, 255, 0.7); /* Translucent white */
+ -fx-background-color: rgba(255, 255, 255, 0.7);
+ /* Translucent white */
-fx-background-radius: 15;
-fx-min-width: 350;
-fx-min-height: 60;
@@ -30,11 +31,114 @@
/* Background image styling */
.main-menu-bg {
- -fx-background-image: url("millionsbackground.png"); /* Replace with your image path */
+ -fx-background-image: url("millionsbackground.png");
+ /* Replace with your image path */
-fx-background-size: cover;
-fx-background-position: center;
}
+
+/* The translucent grey panel containing all save rows */
+.save-list {
+ -fx-background-color: rgba(220, 220, 220, 0.85);
+ -fx-background-radius: 12;
+ -fx-min-width: 600;
+ -fx-spacing: 8;
+}
+
+/* Each clickable save row */
+.save-row {
+ -fx-background-color: rgba(173, 216, 230, 0.85);
+ /* Light blue */
+ -fx-background-radius: 8;
+ -fx-cursor: hand;
+}
+
+.save-row:hover {
+ -fx-background-color: rgba(135, 206, 235, 0.95);
+}
+
+/* Save name (left side of the row) */
+.save-name {
+ -fx-font-family: "System";
+ -fx-font-weight: bold;
+ -fx-font-style: italic;
+ -fx-font-size: 18px;
+ -fx-fill: black;
+}
+
+/* Save balance, color-coded by sign */
+.save-balance-positive {
+ -fx-font-family: "System";
+ -fx-font-weight: bold;
+ -fx-font-style: italic;
+ -fx-font-size: 18px;
+ -fx-fill: black;
+}
+
+.save-balance-negative {
+ -fx-font-family: "System";
+ -fx-font-weight: bold;
+ -fx-font-style: italic;
+ -fx-font-size: 18px;
+ -fx-fill: black;
+}
+
+
+
+/* The translucent main panel containing sidebar + content */
+.settings-panel {
+ -fx-background-color: rgba(220, 220, 220, 0.85);
+ -fx-background-radius: 12;
+ -fx-border-color: rgba(135, 206, 235, 0.9);
+ -fx-border-width: 3;
+ -fx-border-radius: 12;
+}
+
+/* Sidebar buttons (audio, video, hot keys, back) */
+.settings-tab-button {
+ -fx-background-color: transparent;
+ -fx-font-family: "System";
+ -fx-font-weight: bold;
+ -fx-font-style: italic;
+ -fx-font-size: 22px;
+ -fx-text-fill: black;
+ -fx-cursor: hand;
+ -fx-padding: 4 8 4 8;
+}
+
+.settings-tab-button:hover {
+ -fx-text-fill: #1976d2;
+}
+
+/* Title in the right content area, e.g. "master volume" */
+.settings-title {
+ -fx-font-family: "System";
+ -fx-font-weight: bold;
+ -fx-font-style: italic;
+ -fx-font-size: 22px;
+ -fx-text-fill: black;
+}
+
+/* Placeholder text in incomplete sections */
+.settings-placeholder {
+ -fx-font-family: "System";
+ -fx-font-style: italic;
+ -fx-font-size: 14px;
+ -fx-text-fill: #555;
+}
+
+/* Slider styling to match the cyan thumb */
+.settings-slider .thumb {
+ -fx-background-color: #4dd0e1;
+ -fx-background-radius: 50%;
+ -fx-padding: 8;
+}
+
+.settings-slider .track {
+ -fx-background-color: rgba(0, 0, 0, 0.4);
+ -fx-pref-height: 2;
+
.title-text {
-fx-font-size: 100px;
}
\ No newline at end of file