From 8851393c6d9d103b1eee7809337efa93f3946aa3 Mon Sep 17 00:00:00 2001
From: =
Date: Tue, 12 May 2026 17:24:00 +0200
Subject: [PATCH 1/9] Feat: Updated View structure to use enums for easier
usage.
---
.../g40/mappe/view/ViewController.java | 15 +-
.../idatt2003/g40/mappe/view/ViewData.java | 8 +-
.../idatt2003/g40/mappe/view/ViewElement.java | 60 +++-
.../idatt2003/g40/mappe/view/ViewEnum.java | 26 ++
.../idatt2003/g40/mappe/view/ViewManager.java | 12 +-
.../mappe/view/mainmenu/MainMenuActions.java | 7 +
.../view/mainmenu/MainMenuController.java | 25 +-
.../g40/mappe/view/mainmenu/MainMenuView.java | 35 +-
.../mappe/view/playgame/PlayGameActions.java | 6 +
.../view/playgame/PlayGameController.java | 69 ++--
.../g40/mappe/view/playgame/PlayGameView.java | 16 +-
.../mappe/view/settings/SettingsActions.java | 8 +
.../view/settings/SettingsController.java | 57 ++-
.../g40/mappe/view/settings/SettingsView.java | 326 +++++++++---------
.../mappe/service/event/EventManagerTest.java | 3 +-
.../g40/mappe/view/ViewControllerTest.java | 12 +-
.../g40/mappe/view/ViewManagerTest.java | 15 +-
17 files changed, 364 insertions(+), 336 deletions(-)
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewEnum.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuActions.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameActions.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsActions.java
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewController.java
index 61fb506..3284e51 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewController.java
@@ -3,6 +3,7 @@
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.EventPublisher;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventType;
/**
* Handles logic and event publishing for {@link ViewElement} objects.
@@ -18,7 +19,7 @@
* @see EventManager
*
*/
-public abstract class ViewController>
+public abstract class ViewController>
implements EventPublisher {
/**
@@ -26,6 +27,7 @@ public abstract class ViewController>
*
*/
private final T1 viewElement;
+
/**
* The {@link EventManager} object to send events to.
*
@@ -84,4 +86,15 @@ public final void invoke(final EventData data,
final EventManager eventManager) {
eventManager.invokeEvent(data);
}
+
+ /**
+ * Basic method for invoking an event to change to a specific view.
+ *
+ * @param viewName the view to set to.
+ * */
+ protected void changeScene(final ViewEnum viewName) {
+ ViewData viewData = new ViewData(viewName);
+ EventData eventData = new EventData(EventType.SCENE_CHANGE, viewData);
+ invoke(eventData, eventManager);
+ }
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewData.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewData.java
index 33fca3c..5f66e88 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewData.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewData.java
@@ -17,7 +17,7 @@ public class ViewData {
* Name of the scene.
*
*/
- private final String sceneName;
+ private final ViewEnum sceneName;
/**
* Constructor.
@@ -26,8 +26,8 @@ public class ViewData {
*
* @throws IllegalArgumentException if sceneName is empty or null.
*/
- public ViewData(final String sceneName) throws IllegalArgumentException {
- if (Validator.NOT_EMPTY.isValid(sceneName)) {
+ public ViewData(final ViewEnum sceneName) throws IllegalArgumentException {
+ if (Validator.NOT_EMPTY.isValid(sceneName.toString())) {
this.sceneName = sceneName;
} else {
throw new IllegalArgumentException(Validator.NOT_EMPTY.getErrorMessage());
@@ -40,7 +40,7 @@ public ViewData(final String sceneName) throws IllegalArgumentException {
* @return scene name.
*
*/
- public String getSceneName() {
+ public ViewEnum getSceneName() {
return sceneName;
}
}
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 aa0f941..a0b0f1c 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
@@ -1,7 +1,8 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view;
import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator;
-import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.Map;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
@@ -12,15 +13,16 @@
* Extends {@link Pane}
*
* @param the type of pane this view element represents.
+ * @param an enum representing all interactable actions found in the view.
*
*/
-public abstract class ViewElement {
+public abstract class ViewElement> {
/**
* List of buttons in this view.
*
*/
- private final ArrayList buttons = new ArrayList<>();
+ private final Map buttonMap;
/**
* The {@link Pane} element the view element has as a root.
@@ -36,18 +38,18 @@ public abstract class ViewElement {
* Used as identification by the {@link ViewManager}.
*
*/
- private String viewName;
+ private ViewEnum viewName;
/**
* Constructor with a name.
*
* @param rootPane an instance of type T (defined in the class).
- * @param viewName The name of the view.
+ * @param viewName The name of the view as an {@link ViewEnum}.
*
*/
- protected ViewElement(final T rootPane, final String viewName) {
- this(rootPane);
- if (Validator.NOT_EMPTY.isValid(viewName)) {
+ protected ViewElement(final T rootPane, final ViewEnum viewName, final Class actionEnum) {
+ this(rootPane, actionEnum);
+ if (Validator.NOT_EMPTY.isValid(viewName.name())) {
this.viewName = viewName;
} else {
throw new IllegalArgumentException(Validator.NOT_EMPTY.getErrorMessage());
@@ -60,9 +62,10 @@ protected ViewElement(final T rootPane, final String viewName) {
* @param rootPane the root of this view.
*
*/
- protected ViewElement(final T rootPane) {
+ protected ViewElement(final T rootPane, final Class actionEnum) {
if (rootPane != null) {
setRootPane(rootPane);
+ this.buttonMap = new EnumMap<>(actionEnum);
initLayout();
initStyling();
} else {
@@ -76,7 +79,7 @@ protected ViewElement(final T rootPane) {
* @return the name of this view.
*
*/
- public String getViewName() {
+ public ViewEnum getViewName() {
return viewName;
}
@@ -86,7 +89,7 @@ public String getViewName() {
* @param name the new name to set this view element to.
*
*/
- protected void setViewName(final String name) {
+ protected void setViewName(final ViewEnum name) {
viewName = name;
}
@@ -116,12 +119,12 @@ protected void setRootPane(final T pane) {
* Gotten by the associated {@link ViewController} object that hooks
* the buttons to functionality.
*
- * @return {@link ArrayList} object containing all buttons
+ * @return {@link Map} object containing all buttons
* in this view element.
*
*/
- public ArrayList getButtons() {
- return buttons;
+ public Map getButtons() {
+ return buttonMap;
}
/**
@@ -136,6 +139,35 @@ public ArrayList getButtons() {
*/
protected abstract void initStyling();
+ /**
+ * Connects an action to a button.
+ *
+ * @param action the enum of type A to put the button to.
+ * @param button the button to assign the action to.
+ *
+ * */
+ protected void registerButton(final A action, final Button button) {
+ buttonMap.put(action, button);
+ }
+
+ /**
+ * Method for assigning logic to a button by referencing the action.
+ *
+ * @param action the action to assign logic to.
+ * @param logic the {@link Runnable} code defining the logic.
+ *
+ * @throws IllegalArgumentException if Action is not in map.
+ * */
+ public void setOnAction(final A action, final Runnable logic)
+ throws IllegalArgumentException {
+ Button btn = buttonMap.get(action);
+ if (btn == null) {
+ throw new IllegalArgumentException("Invalid button");
+ } else {
+ btn.setOnAction(e -> logic.run());
+ }
+ }
+
/**
* Method that defines how view elements set data.
*
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewEnum.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewEnum.java
new file mode 100644
index 0000000..b411d57
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewEnum.java
@@ -0,0 +1,26 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view;
+
+/**
+ * Enum representing different views in the system.
+ * */
+public enum ViewEnum {
+ /**
+ * {@link edu.ntnu.idi.idatt2003.g40.mappe.view.mainmenu.MainMenuView}.
+ * */
+ MAIN_MENU,
+
+ /**
+ * {@link edu.ntnu.idi.idatt2003.g40.mappe.view.settings.SettingsView}.
+ * */
+ SETTINGS,
+
+ /**
+ * {@link edu.ntnu.idi.idatt2003.g40.mappe.view.playgame.PlayGameView}.
+ * */
+ PLAY_GAME,
+
+ /**
+ * {@link edu.ntnu.idi.idatt2003.g40.mappe.view.ingame.InGameView}.
+ * */
+ IN_GAME;
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManager.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManager.java
index d7a3711..183fb64 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManager.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManager.java
@@ -26,7 +26,7 @@ public final class ViewManager implements EventSubscriber {
* A map with String keys and {@link ViewElement} objects as values.
*
*/
- private final Map> viewMap;
+ private final Map> viewMap;
/**
* The main stage of the application.
@@ -38,7 +38,7 @@ public final class ViewManager implements EventSubscriber {
* Current view. Used for testing and debugging purposes.
*
*/
- private ViewElement> currentView;
+ private ViewElement, ?> currentView;
/**
* Constructor.
@@ -68,7 +68,7 @@ public ViewManager(final Stage stage, final EventManager eventManager)
* @throws IllegalArgumentException if view is already in map, or if
* view does not have view name (widget).
*/
- public void addView(final ViewElement> view)
+ public void addView(final ViewElement, ?> view)
throws IllegalArgumentException {
if (view.getViewName() == null) {
throw new IllegalArgumentException("Cannot add widget"
@@ -91,7 +91,7 @@ public void addView(final ViewElement> view)
*
* @throws IllegalArgumentException if view is not in view map.
*/
- public void setScene(final ViewElement> viewElement)
+ public void setScene(final ViewElement, ?> viewElement)
throws IllegalArgumentException {
if (viewElement == null
|| !viewMap.containsKey(viewElement.getViewName())) {
@@ -129,7 +129,7 @@ public void setScene(final ViewData data) throws IllegalArgumentException {
if (data == null) {
throw new IllegalArgumentException("Data is null!");
} else {
- ViewElement> viewElement = viewMap.get(data.getSceneName());
+ ViewElement, ?> viewElement = viewMap.get(data.getSceneName());
viewElement.setData(data);
setScene(viewElement);
currentView = viewElement;
@@ -144,7 +144,7 @@ public void setScene(final ViewData data) throws IllegalArgumentException {
* @return the view element currently active.
*
*/
- public ViewElement> getCurrentView() {
+ public ViewElement, ?> getCurrentView() {
return currentView;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuActions.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuActions.java
new file mode 100644
index 0000000..37ad15c
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/mainmenu/MainMenuActions.java
@@ -0,0 +1,7 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.mainmenu;
+
+public enum MainMenuActions {
+ START_GAME,
+ SETTINGS,
+ EXIT;
+}
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 bf2f1c5..a9343a1 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,14 +5,13 @@
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 edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
import javafx.application.Platform;
/**
* Controller for the {@link MainMenuView}.
*
- *
- * Extends {@link ViewController}
- *
+ * Extends {@link ViewController}
*/
public class MainMenuController extends ViewController {
@@ -31,24 +30,20 @@ public MainMenuController(final MainMenuView view,
/**
* {@inheritDoc}
*
- *
- * Sets play game, settings, and exit button functionality.
- *
+ * Sets play game, settings, and exit button functionality.
*/
@Override
protected void initInteractions() {
- getViewElement().getToGameButton().setOnAction(e -> {
- ViewData viewData = new ViewData("PlayGameView");
- EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
- invoke(eventData, getEventManager());
+
+ getViewElement().setOnAction(MainMenuActions.START_GAME, () -> {
+ changeScene(ViewEnum.PLAY_GAME);
});
- getViewElement().getSettingsButton().setOnAction(e -> {
- ViewData viewData = new ViewData("SettingsView");
- EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
- getEventManager().invokeEvent(eventData);
+ getViewElement().setOnAction(MainMenuActions.SETTINGS, () -> {
+ changeScene(ViewEnum.SETTINGS);
});
- getViewElement().getExitButton().setOnAction(e -> Platform.exit());
+ getViewElement().setOnAction(MainMenuActions.EXIT, 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 2ab0584..c2fd089 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
@@ -1,6 +1,7 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.mainmenu;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
@@ -13,7 +14,7 @@
* Extends {@link ViewElement},
* with a root pane of {@link StackPane}
* */
-public class MainMenuView extends ViewElement {
+public class MainMenuView extends ViewElement {
/**
* Game title.
@@ -46,34 +47,7 @@ public class MainMenuView extends ViewElement {
* Constructs with name "MainMenu"
* */
public MainMenuView() {
- super(new StackPane(), "MainMenu");
- }
-
- /**
- * Getter method for "Play" button.
- *
- * @return Play game button.
- * */
- public Button getToGameButton() {
- return toGameButton;
- }
-
- /**
- * Getter method for "Settings" button.
- *
- * @return Settings button.
- * */
- public Button getSettingsButton() {
- return settingsButton;
- }
-
- /**
- * Getter method for "Exit" button.
- *
- * @return Exit button.
- * */
- public Button getExitButton() {
- return exitButton;
+ super(new StackPane(), ViewEnum.MAIN_MENU, MainMenuActions.class);
}
/**
@@ -102,6 +76,9 @@ protected void initLayout() {
);
getRootPane().getChildren().add(buttonContainer);
StackPane.setAlignment(buttonContainer, Pos.CENTER);
+ registerButton(MainMenuActions.START_GAME, toGameButton);
+ registerButton(MainMenuActions.SETTINGS, settingsButton);
+ registerButton(MainMenuActions.EXIT, exitButton);
}
/**
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameActions.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameActions.java
new file mode 100644
index 0000000..03053e3
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/playgame/PlayGameActions.java
@@ -0,0 +1,6 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.playgame;
+
+public enum PlayGameActions {
+ NEW_GAME,
+ BACK,
+}
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
index 0f8472c..22d9db4 100644
--- 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
@@ -1,57 +1,42 @@
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;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
/**
* Controller for the {@link PlayGameView}.
*
- *
- * Extends {@link ViewController}
- *
+ * 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);
- }
+ /**
+ * 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);
- });
+ /**
+ * {@inheritDoc}-
+ *
+ * Sets create new game, back, and save-row click functionality.
+ */
+ @Override
+ protected void initInteractions() {
+ getViewElement().setOnAction(PlayGameActions.NEW_GAME, () ->
+ changeScene(ViewEnum.IN_GAME));
- getViewElement().getBackButton().setOnAction(e -> {
- ViewData viewData = new ViewData("MainMenu");
- EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
- getEventManager().invokeEvent(eventData);
- });
+ getViewElement().setOnAction(PlayGameActions.BACK, () ->
+ changeScene(ViewEnum.MAIN_MENU));
- getViewElement().setOnSaveSelected(save -> {
- ViewData viewData = new ViewData("InGameView");
- EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
- getEventManager().invokeEvent(eventData);
- });
- }
+ getViewElement().setOnSaveSelected(save ->
+ changeScene(ViewEnum.IN_GAME));
+ }
}
\ 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
index ca8459b..f4f5691 100644
--- 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
@@ -2,6 +2,7 @@
import edu.ntnu.idi.idatt2003.g40.mappe.model.SaveGame;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
@@ -35,7 +36,7 @@
* background image can sit behind the central panel.
*
*/
-public class PlayGameView extends ViewElement {
+public class PlayGameView extends ViewElement {
/** "Create new game" button. */
private Button createNewGameButton;
@@ -70,15 +71,7 @@ public class PlayGameView extends ViewElement {
*
*/
public PlayGameView() {
- super(new StackPane(), "PlayGameView");
- }
-
- public Button getCreateNewGameButton() {
- return createNewGameButton;
- }
-
- public Button getBackButton() {
- return backButton;
+ super(new StackPane(), ViewEnum.PLAY_GAME, PlayGameActions.class);
}
/**
@@ -128,6 +121,9 @@ protected void initLayout() {
// Make the background fill the root pane.
backgroundImage.fitWidthProperty().bind(getRootPane().widthProperty());
backgroundImage.fitHeightProperty().bind(getRootPane().heightProperty());
+
+ registerButton(PlayGameActions.NEW_GAME, createNewGameButton);
+ registerButton(PlayGameActions.BACK, backButton);
}
/** {@inheritDoc} */
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsActions.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsActions.java
new file mode 100644
index 0000000..b319a02
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsActions.java
@@ -0,0 +1,8 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.settings;
+
+public enum SettingsActions {
+ AUDIO,
+ VIDEO,
+ HOTKEYS,
+ BACK;
+}
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
index c364624..12fde41 100644
--- 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
@@ -5,46 +5,33 @@
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 edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
/**
* 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.
- *
+ * 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);
- }
+ /**
+ * 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().setOnAction(SettingsActions.AUDIO, () -> getViewElement().showAudioSection());
+ getViewElement().setOnAction(SettingsActions.VIDEO, () -> getViewElement().showVideoSection());
+ getViewElement().setOnAction(SettingsActions.HOTKEYS, () -> getViewElement().showHotKeysSection());
+ getViewElement().setOnAction(SettingsActions.BACK, () -> changeScene(ViewEnum.MAIN_MENU));
+ }
}
\ 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
index c5b2d21..beb310d 100644
--- 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
@@ -1,6 +1,7 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.settings;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
@@ -19,177 +20,162 @@
/**
* View shown when the player clicks "Settings" on the main menu.
*
- *
- * Layout: left sidebar with category buttons (audio, video, hot keys)
+ *
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.
- *
+ * 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();
- }
+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(), ViewEnum.SETTINGS, SettingsActions.class);
+ }
+
+ 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();
+
+ registerButton(SettingsActions.AUDIO, audioButton);
+ registerButton(SettingsActions.VIDEO, videoButton);
+ registerButton(SettingsActions.HOTKEYS, hotKeysButton);
+ registerButton(SettingsActions.BACK, backButton);
+ }
+
+ /** {@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/test/java/edu/ntnu/idi/idatt2003/g40/mappe/service/event/EventManagerTest.java b/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/service/event/EventManagerTest.java
index 58d6d0e..716e96e 100644
--- a/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/service/event/EventManagerTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/service/event/EventManagerTest.java
@@ -1,6 +1,7 @@
package edu.ntnu.idi.idatt2003.g40.mappe.service.event;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewData;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -72,7 +73,7 @@ private class GenericEventPublisher implements EventPublisher {
private final EventManager eventManager;
public GenericEventPublisher(final EventManager eventManager, final TestEventTypes eventType) {
- viewData = new ViewData("Test");
+ viewData = new ViewData(ViewEnum.IN_GAME);
eventData = new EventData(eventType, viewData);
this.eventManager = eventManager;
}
diff --git a/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewControllerTest.java b/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewControllerTest.java
index abf0158..e105cdf 100644
--- a/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewControllerTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewControllerTest.java
@@ -29,18 +29,22 @@ void controllerElementSetsButtonBehavior() {
assertTrue(testViewElement.buttonPressed);
}
- private class GenericViewElement extends ViewElement {
+ private enum GenericViewActions {
+ TEST_ACTION;
+ }
+
+ private class GenericViewElement extends ViewElement {
public Boolean buttonPressed = false;
private Button interactableButton;
protected GenericViewElement(final Pane rootPane) {
- super(rootPane);
+ super(rootPane, GenericViewActions.class);
}
@Override
protected void initLayout() {
interactableButton = new Button("Click me!");
- getButtons().add(interactableButton);
+ registerButton(GenericViewActions.TEST_ACTION, interactableButton);
}
public Button getInteractableButton() {
@@ -61,7 +65,7 @@ protected GenericViewController(final ViewControllerTest.GenericViewElement view
@Override
protected void initInteractions() {
- getViewElement().getInteractableButton().setOnAction(e -> {
+ getViewElement().setOnAction(GenericViewActions.TEST_ACTION, () -> {
getViewElement().buttonPressed = true;
});
}
diff --git a/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManagerTest.java b/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManagerTest.java
index 1f9aeb3..b5edcfe 100644
--- a/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManagerTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManagerTest.java
@@ -64,22 +64,27 @@ void throwsErrorWhenAddingWidgetWithNoViewName() {
});
}
- private class GenericViewElement extends ViewElement {
+ private enum GenericActions {
+ ACTION_1;
+ }
+
+
+ private class GenericViewElement extends ViewElement {
public Boolean buttonPressed = false;
private Button interactableButton;
protected GenericViewElement(final Pane rootPane, final String viewName) {
- super(rootPane, viewName);
+ super(rootPane, viewName, GenericActions.class);
}
protected GenericViewElement(final Pane rootPane) {
- super(rootPane);
+ super(rootPane, GenericActions.class);
}
@Override
protected void initLayout() {
interactableButton = new Button("Click me!");
- getButtons().add(interactableButton);
+ registerButton(GenericActions.ACTION_1, interactableButton);
}
public Button getInteractableButton() {
@@ -100,7 +105,7 @@ protected GenericViewController(final ViewManagerTest.GenericViewElement viewEle
@Override
protected void initInteractions() {
- getViewElement().getInteractableButton().setOnAction(e -> {
+ getViewElement().setOnAction(GenericActions.ACTION_1, () -> {
getViewElement().buttonPressed = true;
});
}
From 5359e6c16c7fb0f0f2cf01adc7c35a3a1e32c1e4 Mon Sep 17 00:00:00 2001
From: =
Date: Tue, 12 May 2026 17:24:16 +0200
Subject: [PATCH 2/9] Feat: Added top bar with graph and navigation row
---
.../ntnu/idi/idatt2003/g40/mappe/Main.java | 17 ++-
.../g40/mappe/view/ingame/InGameActions.java | 4 +
.../g40/mappe/view/ingame/InGameView.java | 15 ++-
.../financialsummary/SummaryActions.java | 5 +
.../financialsummary/SummaryController.java | 23 ++++
.../widgets/financialsummary/SummaryView.java | 106 ++++++++++++++++++
.../view/widgets/topbar/TopBarActions.java | 8 ++
.../view/widgets/topbar/TopBarController.java | 21 ++++
.../mappe/view/widgets/topbar/TopBarView.java | 56 +++++++++
src/main/resources/styles.css | 85 ++++++++++++++
10 files changed, 333 insertions(+), 7 deletions(-)
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameActions.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryActions.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarActions.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarController.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarView.java
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 3053f88..4d9aa72 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
@@ -17,6 +17,11 @@
import java.io.IOException;
import java.util.List;
import java.util.Objects;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryController;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryView;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar.TopBarController;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar.TopBarView;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
@@ -77,10 +82,18 @@ public void start(final Stage stage) throws Exception {
SettingsView settingsView = new SettingsView();
new SettingsController(settingsView, eventManager);
+ // Summary section of the top bar
+ SummaryView summaryView = new SummaryView();
+ new SummaryController(summaryView, eventManager);
+
+ // Top bar
+ TopBarView topBarView = new TopBarView(summaryView);
+ new TopBarController(topBarView, eventManager);
+
// In-game
- InGameView inGameView = new InGameView();
+ InGameView inGameView = new InGameView(topBarView);
- // Registrer alle views og start på hovedmenyen
+ // Register all views
viewManager.addView(mainMenuView);
viewManager.addView(playGameView);
viewManager.addView(settingsView);
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameActions.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameActions.java
new file mode 100644
index 0000000..cae5ce2
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameActions.java
@@ -0,0 +1,4 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.ingame;
+
+public enum InGameActions {
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameView.java
index 9ce3bfc..0096e48 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameView.java
@@ -1,18 +1,23 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.ingame;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar.TopBarView;
import javafx.scene.layout.VBox;
-import javafx.scene.text.Text;
-public class InGameView extends ViewElement {
+public class InGameView extends ViewElement {
+
+ TopBarView topBarView;
+
+ public InGameView(final TopBarView topBarView) {
+ this.topBarView = topBarView;
+ super(new VBox(), ViewEnum.IN_GAME, InGameActions.class);
- public InGameView() {
- super(new VBox(), "InGameView");
}
@Override
protected void initLayout() {
- getRootPane().getChildren().add(new Text("This is the game view!"));
+ getRootPane().getChildren().add(topBarView.getRootPane());
}
@Override
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryActions.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryActions.java
new file mode 100644
index 0000000..a9c93c7
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryActions.java
@@ -0,0 +1,5 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary;
+
+public enum SummaryActions {
+ NEXT_WEEK;
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
new file mode 100644
index 0000000..fecc2ae
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
@@ -0,0 +1,23 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
+
+public class SummaryController extends ViewController {
+
+ /**
+ * {@inheritDoc}.
+ */
+ public SummaryController(final SummaryView viewElement,
+ final EventManager eventManager)
+ throws IllegalArgumentException {
+ super(viewElement, eventManager);
+ }
+
+ @Override
+ protected void initInteractions() {
+ getViewElement().setOnAction(SummaryActions.NEXT_WEEK, () -> {
+ System.out.println("Next week!");
+ });
+ }
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
new file mode 100644
index 0000000..402a3bf
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
@@ -0,0 +1,106 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import javafx.geometry.Pos;
+import javafx.scene.chart.LineChart;
+import javafx.scene.chart.NumberAxis;
+import javafx.scene.chart.XYChart;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+
+public class SummaryView extends ViewElement {
+ private Label balanceLabel;
+ private Label weekLabel;
+ private Label titleLabel;
+ private LineChart chart;
+ private XYChart.Series dataSeries;
+ private Button nextBtn;
+
+ public SummaryView() {
+ super(new HBox(), SummaryActions.class);
+ }
+
+ @Override
+ protected void initLayout() {
+ getRootPane().setSpacing(20);
+ getRootPane().setAlignment(Pos.BOTTOM_CENTER);
+ getRootPane().setFillHeight(false);
+
+ VBox balanceInfo = new VBox();
+
+ titleLabel = new Label("balance/investments");
+ balanceLabel = new Label("200$/2394$");
+
+ balanceInfo.getChildren().addAll(titleLabel, balanceLabel);
+
+ NumberAxis xAxis = new NumberAxis(1, 22, 1);
+ xAxis.setMinorTickVisible(false);
+ xAxis.setTickMarkVisible(true);
+ xAxis.setTickLabelsVisible(true);
+
+ NumberAxis yAxis = new NumberAxis();
+ yAxis.setTickLabelsVisible(false);
+ yAxis.setTickMarkVisible(false);
+ yAxis.setMinorTickVisible(false);
+
+ chart = new LineChart<>(xAxis, yAxis);
+ chart.setCreateSymbols(false);
+ chart.setLegendVisible(false);
+ chart.setHorizontalGridLinesVisible(false);
+ chart.setVerticalGridLinesVisible(false);
+ chart.setAlternativeRowFillVisible(false);
+ chart.setAnimated(false);
+ chart.setPrefHeight(100);
+ chart.setMinHeight(100);
+ chart.setMaxHeight(100);
+
+ Region spacer = new Region();
+ HBox.setHgrow(spacer, Priority.ALWAYS);
+ HBox.setHgrow(chart, Priority.ALWAYS);
+
+ Region leftSpacer = new Region();
+ HBox.setHgrow(leftSpacer, Priority.SOMETIMES);
+
+ dataSeries = new XYChart.Series<>();
+ chart.prefHeightProperty().bind(getRootPane().heightProperty().divide(5));
+ chart.minHeightProperty().set(50);
+ chart.getData().add(dataSeries);
+
+ VBox navInfo = new VBox();
+ navInfo.setAlignment(Pos.BOTTOM_RIGHT);
+
+ nextBtn = new Button("next");
+
+ weekLabel = new Label("week: 0");
+ weekLabel.getStyleClass().add("week-label");
+
+ navInfo.getChildren().addAll(nextBtn, weekLabel);
+
+ getRootPane().getChildren().addAll(balanceInfo, chart, navInfo);
+ registerButton(SummaryActions.NEXT_WEEK, nextBtn);
+ }
+
+ @Override
+ protected void initStyling() {
+ getRootPane().getStyleClass().add("summary-container");
+ titleLabel.getStyleClass().add("balance-title");
+ balanceLabel.getStyleClass().add("balance-value");
+ nextBtn.getStyleClass().add("next-button");
+ }
+
+ public void setBalance(final String text) {
+ balanceLabel.setText(text);
+ }
+
+ public void setWeek(int week) {
+ weekLabel.setText("week: " + week);
+ }
+
+ public void updateChart(double x, double y) {
+ dataSeries.getData().add(new XYChart.Data<>(x, y));
+ }
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarActions.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarActions.java
new file mode 100644
index 0000000..08f84fb
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarActions.java
@@ -0,0 +1,8 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar;
+
+public enum TopBarActions {
+ EXIT,
+ STATS,
+ MARKET,
+ SETTINGS;
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarController.java
new file mode 100644
index 0000000..542c2b3
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarController.java
@@ -0,0 +1,21 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
+
+public class TopBarController extends ViewController {
+
+ /**
+ * {@inheritDoc}.
+ */
+ public TopBarController(final TopBarView viewElement, final EventManager eventManager)
+ throws IllegalArgumentException {
+ super(viewElement, eventManager);
+ }
+
+ @Override
+ protected void initInteractions() {
+ getViewElement().setOnAction(TopBarActions.EXIT, () -> changeScene(ViewEnum.MAIN_MENU));
+ }
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarView.java
new file mode 100644
index 0000000..b1ab559
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarView.java
@@ -0,0 +1,56 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryView;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+
+import java.util.stream.Stream;
+
+public class TopBarView extends ViewElement {
+ private Button quitBtn;
+ private Button statsBtn;
+ private Button marketBtn;
+ private Button settingsBtn;
+ private final SummaryView summaryView;
+
+ public TopBarView(final SummaryView summaryView) {
+ this.summaryView = summaryView;
+ super(new VBox(10), TopBarActions.class);
+ }
+
+ @Override
+ protected void initLayout() {
+ HBox navRow = new HBox(20);
+ navRow.setAlignment(Pos.CENTER);
+
+ quitBtn = new Button("Quit");
+ statsBtn = new Button("Stats");
+ marketBtn = new Button("Market");
+ settingsBtn = new Button("Settings");
+
+ navRow.getChildren().addAll(
+ quitBtn,
+ statsBtn,
+ marketBtn,
+ settingsBtn
+ );
+
+ getRootPane().getChildren().addAll(navRow, summaryView.getRootPane());
+
+ registerButton(TopBarActions.EXIT, quitBtn);
+ registerButton(TopBarActions.STATS, statsBtn);
+ registerButton(TopBarActions.MARKET, marketBtn);
+ registerButton(TopBarActions.SETTINGS, settingsBtn);
+
+ }
+
+ @Override
+ protected void initStyling() {
+ getRootPane().getStyleClass().add("top-bar"); // For your CSS file
+ Stream.of(quitBtn, statsBtn, marketBtn, settingsBtn)
+ .forEach(b -> b.getStyleClass().add("menu-button"));
+ }
+}
diff --git a/src/main/resources/styles.css b/src/main/resources/styles.css
index 7fc3640..13e27d0 100644
--- a/src/main/resources/styles.css
+++ b/src/main/resources/styles.css
@@ -138,7 +138,92 @@
.settings-slider .track {
-fx-background-color: rgba(0, 0, 0, 0.4);
-fx-pref-height: 2;
+}
.title-text {
-fx-font-size: 100px;
+}
+/* ------------- TOP BAR ------------- */
+.top-bar {
+ -fx-background-color: rgba(255, 255, 255, 0.7);
+ -fx-background-radius: 20;
+ -fx-margin: 10;
+ -fx-padding: 1%;
+}
+
+
+.top-bar-menu-button {
+ -fx-font-size: 18px;
+ -fx-font-weight: bold;
+ -fx-font-style: italic;
+ -fx-background-color: #f0f0f0;
+ -fx-background-radius: 10;
+ -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.2), 5, 0, 0, 2);
+}
+
+.top-bar-menu-button:hover {
+ -fx-background-color: #d0d0d0;
+}
+
+/* ------------- SUMMARY IN TOP BAR -----------*/
+.summary-container {
+ -fx-border-color: black;
+ -fx-border-width: 1 0 1 0; /* Horizontal lines from image */
+ -fx-padding: 10;
+}
+
+.balance-title {
+ -fx-font-family: "Aptos";
+ -fx-font-style: italic;
+ -fx-font-weight: bold;
+ -fx-font-size: 14;
+}
+
+.balance-value {
+ -fx-font-family: "Aptos";
+ -fx-font-weight: bold;
+ -fx-font-size: 24;
+}
+
+.chart-series-line {
+ -fx-stroke: green;
+}
+
+
+.chart-plot-background {
+ -fx-background-color: transparent;
+}
+
+.chart {
+ -fx-padding: 0;
+}
+
+.axis {
+ -fx-tick-label-font-weight: bold;
+ -fx-tick-label-font-style: italic;
+ -fx-tick-label-fill: black;
+}
+
+.axis:bottom {
+ -fx-border-color: black transparent transparent transparent;
+ -fx-border-width: 2px;
+}
+
+.axis:left {
+ -fx-border-color: transparent;
+}
+
+.chart-series-line {
+ -fx-stroke: #00ff00;
+ -fx-stroke-width: 2px;
+}
+
+.next-button {
+ -fx-background-color: #e0e0e0;
+ -fx-background-radius: 10;
+ -fx-font-family: "Aptos";
+ -fx-font-weight: bold;
+ -fx-padding: 5 15;
+ -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.2), 2, 0, 0, 1);
+ -fx-cursor: hand;
}
\ No newline at end of file
From 8bd5c9091e5909b437401aa13ecd0d9cf054455c Mon Sep 17 00:00:00 2001
From: =
Date: Tue, 12 May 2026 18:59:23 +0200
Subject: [PATCH 3/9] Feat: Added icon pngs
---
src/main/resources/Icons/minus.png | Bin 0 -> 833 bytes
src/main/resources/Icons/minus2.png | Bin 0 -> 178 bytes
src/main/resources/Icons/plus.png | Bin 0 -> 3653 bytes
src/main/resources/Icons/plus2.png | Bin 0 -> 340 bytes
4 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 src/main/resources/Icons/minus.png
create mode 100644 src/main/resources/Icons/minus2.png
create mode 100644 src/main/resources/Icons/plus.png
create mode 100644 src/main/resources/Icons/plus2.png
diff --git a/src/main/resources/Icons/minus.png b/src/main/resources/Icons/minus.png
new file mode 100644
index 0000000000000000000000000000000000000000..d6a10870ee19704d5fcd793fb2b8ceccee9ebc14
GIT binary patch
literal 833
zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yu@pObhHwBu4M$1`kk47*5n0T@
zz%2~Ij105pNH8!kJ@#~Q45^s&_U``v)MT0CAGgn)s?_2&o?DzE!mtMfi+$-K!ugV^9oU|o)
zZ;Wlt1mQ!5AKktte7$|g(VE@j;^(W6Z@=IOds0)nuB!Omg1_$+zK5^RU#%RmkbPEV
z?|IfIAzwX9Pj9ns68*VpSHNGZZx1?Ws@qK~_;9~G`>=ZS;%7{sj$DgwES)tc*?;fR
zT`PZO&5TQ!nwRrq-V>wX@(I<`-m-?Je=)Teoxsg)#*|%Bms6mn@LVj1<=Tt3jR#jY
z#B5Gb-r#n~2`R
z-P+7Tbi#bFG3_8@YW9JQS^WCDAM2C7tkR99yDZEszRvz4%zJv_ojoDu87X5INaav
zulU-2HTUY=+i!p>uD-gtlbLVRuHVtTjFPcptbHrXSGBLY|D4at!=Y^T^JL
zxqLO2_w(eC@+jG|c+W7FkyWNU?cDKsNPe34@%l>jEznb^Vq~*+05ZBYy&t;uc
GLK6TkB2S+H
literal 0
HcmV?d00001
diff --git a/src/main/resources/Icons/minus2.png b/src/main/resources/Icons/minus2.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a816334f2132f557f5223fd15588ecbd873bc59
GIT binary patch
literal 178
zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VV{wqX6T`Z5GB1G~mUKs7M+SzC
z{oH>NS%G}c0*}aI1_o|n5N2eUHAey{=^fs60jcG!
z8(A4TK|rRW-9*G&IYI=b9YHHZO$Qb5a<*qyv(EoBKhL+;_v3rNcRl-k-nHNTJp0$3
zf!pWL{cbJ$h#rNlwB8{Rh8y}TnI@FhR#`#$R
z%kA>wgGUcMTZ$SzwryPnZ%^|bXVkNQHMC9{6|O#u`8NFaTW{E}g+$E5$1W8Y`7Y1i
z6+e4v84&;d#U;G;4RcnV=~{Aa?SSn&*S=t4)?5MrSj;44&Cbf$@8{-iYSl#OfR;+o{oofUhAc79?QHDdO$xKlsKf<7F5k7(S((w1>0yW6zeHXJsE(W6&7l4szPFF
zxtedNZy>a+C0p<`-K`me!&VIm>pwU{Xwisa-6j;9_LI72kw5j&
zzMg=D`BY3#&gU8|HF3NU)<*a}$EfkP7DE4FN$8q>GfQ(ct^T%n8O(t4C7mjI0eA}L
z<%%7AyWys=>=p6mv*;E+OFdr19OL-~9)#9^x_R!rIwO3kF*USMIy73$3d(77J&gq1
z+`3F%ZPyu^Bzt>%h3S#;md4br4A`Sah~R>l!*YSH-Zr_BWD4VeSQA8`S)P$BKe_Iv
z$&IaG9i;DJP!$~Hxk6W&CO3Wocp$G8A}mJCaa<3D2AKQBSoo|4dBsMJ>p@N{JZo#
z%QGR%zvBJRttcmCgZT&=j%I1E;F?%)ce>&(*K6{Wi{L_?S9e$w7I~aj!=6$+ZrqSd
z>WXGX9J2Uv+*x_<`oW0HvrtU&i
zB`-Ha^^1Do)A`EGXjYvQlfqCIc19hhub{}DYtv=g7|4>@CUI-zPr=)IKkn($lXI{GgO?GzJ$qL$pbPC_(_{sS*%Vo
zUUBXNz^fC}Z}!|<8~^q-x#8tKZU!E!6Lv;-YCgsDD+LFZRoLsCMb_%(Q~q($EIa$u
zk&hogz9M$zi`!Mmp`$$pahO_NsOvrQ_K0h1tUM7}UGM-@j#T9fgZct|mY4X;UPf|5jDKGx6-t?wh(;nI*s70cRd@wgQMUQr6u!G9`>ERMS%vK5
zY{XtF*^tqQvRCh_wC)b>F+Q44`dpuf^nHBoiOos%>9~>W3dCMI(s#p(cMIyt){Us;
zQG87m1HVr~k2UKazd7W^Zpmd6Wr~-nvX?|pT-HTY>mZFRxK6-QH;dE$(3n1U^ICLV
zbY}tSs^yvTdvc@4UgK^HoAB%(!T0l5|6TS~OXbRA9uOZ7z5h`@;jlN)v1)@;a8{8O
zqVeOuCQ!28d05b*M-R5+K`Ca+@x&+*$}pR9LDmaXD7Fx+3bpqQ!QJVR^4QJ1P4cm^
z&B>$ESf?inh)=dtQvk7KLWgX;N-ux>AHBnvuF};`kqIUY92~SHJ3^9
z`$Q|+@{=~Y`;3H2N!ke;Qi)}en{{R&Xz+?lQKmC!6fN{aH$7?>)Su@{7WyN*$mi6-98TmRwvI&kt;WkS4jEskaZ!5<$l_}I$vF7a4z@w_dDmFd7#
zyxrswbYcflbH7NkBD&$MVWX&WcX?+NCzHJkAA2%J=slT1S5|A0Pwy~gy?ul-Ctryh
z&l0q@t1~QsqR7hdd_vZtZiNjbpI|_076VjS~(+uBhgc6eZ2Y431j^B
z@K^nTNYxeXAd~_!C0mP^+I>7HGE!>?XC=<<)A0(l$gz#qihqUf2JR<_ayq~nA6HdSfI3|)Wg&lrj6!UWS9MUeAWXyW6~kx8LRfR
z_lW9_@fu&-X0M%3h{j5IgncTd9?{s-BZT$>1F?ol35}T)8|A}*i&kB=-Gq0Bt^$jC
zlQG<F*K^vnf2>z@}so#Tr*jm{R+
zU_m@mbvB7N*dg)Mp+s?DN;6A@R%MQEK6(1!lvI6;>1s;*b3=DjSL74G){)!Z!;7d;z$B+p3x05&W9x@PNz0WPZfr+*BQfu2h
zE$$6$XBe_KIA~Q#U9vP~)!x8ZDYB$P=h2J?A;p?WvoB9CowUEv;lcfdx-}k?QrI3a
zBycgPEcq`pahzU|N7$U5Bn<{HbGK56CK-wG=Yj_Ks|_o>gg^@us@eGw~9llFtO
zZvKqDr?)ac)?3(Z(Pthg@^;p`RjYC%r~O{``QTTUW&x%;;|2HL_&s-C&%j{W;B;xJ
ho$Fhs#sjx)7`EGlsBGXq&k6K2gQu&X%Q~loCIAIpg
Date: Tue, 12 May 2026 18:59:50 +0200
Subject: [PATCH 4/9] Feat: Added new UI for the ingame view
---
.../ntnu/idi/idatt2003/g40/mappe/Main.java | 6 +-
.../g40/mappe/view/ingame/InGameActions.java | 2 +
.../mappe/view/ingame/InGameController.java | 21 +++
.../g40/mappe/view/ingame/InGameView.java | 30 +++-
.../widgets/financialsummary/SummaryView.java | 39 +++--
.../view/widgets/stats/StatsActions.java | 6 +
.../view/widgets/stats/StatsController.java | 4 +
.../mappe/view/widgets/stats/StatsView.java | 145 ++++++++++++++++++
.../view/widgets/topbar/TopBarController.java | 6 +
.../mappe/view/widgets/topbar/TopBarView.java | 20 ++-
src/main/resources/styles.css | 87 +++++++++--
11 files changed, 332 insertions(+), 34 deletions(-)
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameController.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsActions.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
create mode 100644 src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsView.java
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 4d9aa72..9321762 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
@@ -20,6 +20,7 @@
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryView;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats.StatsView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar.TopBarController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar.TopBarView;
import javafx.application.Application;
@@ -90,8 +91,11 @@ public void start(final Stage stage) throws Exception {
TopBarView topBarView = new TopBarView(summaryView);
new TopBarController(topBarView, eventManager);
+ // Stats page
+ StatsView statsView = new StatsView();
+
// In-game
- InGameView inGameView = new InGameView(topBarView);
+ InGameView inGameView = new InGameView(topBarView, statsView.getRootPane());
// Register all views
viewManager.addView(mainMenuView);
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameActions.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameActions.java
index cae5ce2..03ddd1a 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameActions.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameActions.java
@@ -1,4 +1,6 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.ingame;
public enum InGameActions {
+ BUY_SHARES,
+ SELL_SHARES;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameController.java
new file mode 100644
index 0000000..eda5729
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameController.java
@@ -0,0 +1,21 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.ingame;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
+
+public class InGameController extends ViewController {
+
+ /**
+ * {@inheritDoc}.
+ */
+ protected InGameController(final InGameView viewElement,
+ final EventManager eventManager)
+ throws IllegalArgumentException {
+ super(viewElement, eventManager);
+ }
+
+ @Override
+ protected void initInteractions() {
+
+ }
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameView.java
index 0096e48..b3b00b7 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/InGameView.java
@@ -1,27 +1,49 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.ingame;
+import edu.ntnu.idi.idatt2003.g40.mappe.model.Stock;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar.TopBarView;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.chart.LineChart;
+import javafx.scene.chart.NumberAxis;
+import javafx.scene.chart.XYChart;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.Separator;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
+import java.util.ArrayList;
+
public class InGameView extends ViewElement {
- TopBarView topBarView;
+ private final TopBarView topBarView;
+ private Node centerView;
- public InGameView(final TopBarView topBarView) {
+ public InGameView(final TopBarView topBarView, final Node centerView) {
this.topBarView = topBarView;
+ this.centerView = centerView;
super(new VBox(), ViewEnum.IN_GAME, InGameActions.class);
-
}
@Override
protected void initLayout() {
- getRootPane().getChildren().add(topBarView.getRootPane());
+ getRootPane().getChildren().addAll(topBarView.getRootPane(), centerView);
+ VBox.setVgrow(centerView, Priority.ALWAYS);
}
@Override
protected void initStyling() {
}
+
+ public void changeCenterView(final Node newCenterView) {
+ this.centerView = newCenterView;
+ getRootPane().getChildren().clear();
+ getRootPane().getChildren().addAll(topBarView.getRootPane(), centerView);
+ VBox.setVgrow(centerView, Priority.ALWAYS);
+ }
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
index 402a3bf..100f9eb 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
@@ -28,14 +28,23 @@ public SummaryView() {
protected void initLayout() {
getRootPane().setSpacing(20);
getRootPane().setAlignment(Pos.BOTTOM_CENTER);
- getRootPane().setFillHeight(false);
+ getRootPane().setFillHeight(true);
+
+ getRootPane().setPrefHeight(100);
+ getRootPane().setMinHeight(80);
+ getRootPane().setMaxHeight(100);
+
+ VBox.setVgrow(getRootPane(), Priority.ALWAYS);
VBox balanceInfo = new VBox();
titleLabel = new Label("balance/investments");
- balanceLabel = new Label("200$/2394$");
+ balanceLabel = new Label("10000$/0$");
- balanceInfo.getChildren().addAll(titleLabel, balanceLabel);
+ Region spacerL = new Region();
+ VBox.setVgrow(spacerL, Priority.ALWAYS);
+
+ balanceInfo.getChildren().addAll(titleLabel, spacerL, balanceLabel);
NumberAxis xAxis = new NumberAxis(1, 22, 1);
xAxis.setMinorTickVisible(false);
@@ -54,9 +63,15 @@ protected void initLayout() {
chart.setVerticalGridLinesVisible(false);
chart.setAlternativeRowFillVisible(false);
chart.setAnimated(false);
- chart.setPrefHeight(100);
- chart.setMinHeight(100);
- chart.setMaxHeight(100);
+ chart.setPrefHeight(250);
+ chart.setMinHeight(200);
+ chart.setMaxHeight(300);
+ chart.setMaxWidth(Double.MAX_VALUE);
+ chart.setMinWidth(0);
+ dataSeries = new XYChart.Series<>();
+ chart.prefHeightProperty().bind(getRootPane().heightProperty().divide(5));
+ chart.minHeightProperty().set(50);
+ chart.getData().add(dataSeries);
Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
@@ -65,20 +80,16 @@ protected void initLayout() {
Region leftSpacer = new Region();
HBox.setHgrow(leftSpacer, Priority.SOMETIMES);
- dataSeries = new XYChart.Series<>();
- chart.prefHeightProperty().bind(getRootPane().heightProperty().divide(5));
- chart.minHeightProperty().set(50);
- chart.getData().add(dataSeries);
-
VBox navInfo = new VBox();
- navInfo.setAlignment(Pos.BOTTOM_RIGHT);
+ navInfo.setAlignment(Pos.TOP_CENTER);
nextBtn = new Button("next");
-
weekLabel = new Label("week: 0");
weekLabel.getStyleClass().add("week-label");
+ Region spacerR = new Region();
+ VBox.setVgrow(spacerR, Priority.ALWAYS);
- navInfo.getChildren().addAll(nextBtn, weekLabel);
+ navInfo.getChildren().addAll(nextBtn, spacerR, weekLabel);
getRootPane().getChildren().addAll(balanceInfo, chart, navInfo);
registerButton(SummaryActions.NEXT_WEEK, nextBtn);
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsActions.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsActions.java
new file mode 100644
index 0000000..693d1cd
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsActions.java
@@ -0,0 +1,6 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats;
+
+public enum StatsActions {
+ BUY_SHARES,
+ SELL_SHARES;
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
new file mode 100644
index 0000000..275ea4f
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
@@ -0,0 +1,4 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats;
+
+public class StatsController {
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsView.java
new file mode 100644
index 0000000..4b6e832
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsView.java
@@ -0,0 +1,145 @@
+package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats;
+
+import edu.ntnu.idi.idatt2003.g40.mappe.model.Stock;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement;
+import java.util.ArrayList;
+import javafx.geometry.Pos;
+import javafx.scene.chart.LineChart;
+import javafx.scene.chart.NumberAxis;
+import javafx.scene.chart.XYChart;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ScrollBar;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+
+public class StatsView extends ViewElement {
+ private LineChart chart;
+ private XYChart.Series dataSeries;
+ private VBox sidebar;
+ private ArrayList stocks;
+ private ArrayList stockStrings;
+ private ArrayList stockButtons;
+ private Label selectedStock;
+
+ public StatsView() {
+ super(new HBox(), StatsActions.class);
+ }
+
+ @Override
+ protected void initLayout() {
+ getRootPane().setAlignment(Pos.TOP_LEFT);
+ getRootPane().setFillHeight(true);
+
+ sidebar = new VBox(10);
+ sidebar.setPrefWidth(150);
+ sidebar.setMaxHeight(Double.MAX_VALUE);
+ VBox.setVgrow(sidebar, Priority.ALWAYS);
+
+ stocks = new ArrayList<>();
+
+ stockStrings = new ArrayList<>();
+ stockStrings.add("AAPL");
+ stockStrings.add("AALL");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+ stockStrings.add("NVID");
+
+
+
+ stockButtons = new ArrayList<>();
+ for (String t : stockStrings) {
+ Button btn = new Button(t);
+ stockButtons.add(btn);
+ sidebar.getChildren().add(btn);
+ }
+ ScrollPane scrollPane = new ScrollPane(sidebar);
+
+ scrollPane.setFitToWidth(true);
+ scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
+ scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+
+ VBox.setVgrow(scrollPane, Priority.ALWAYS);
+ scrollPane.setMaxHeight(Double.MAX_VALUE);
+
+ VBox mainContent = new VBox(20);
+ mainContent.setAlignment(Pos.CENTER);
+ HBox.setHgrow(mainContent, Priority.ALWAYS);
+ mainContent.setMaxHeight(Double.MAX_VALUE);
+ VBox.setVgrow(mainContent, Priority.ALWAYS);
+
+ selectedStock = new Label("APL");
+
+ NumberAxis xAxis = new NumberAxis(1, 22, 1);
+ xAxis.setMinorTickVisible(false);
+ xAxis.setTickMarkVisible(true);
+ xAxis.setTickLabelsVisible(true);
+
+ NumberAxis yAxis = new NumberAxis();
+ yAxis.setTickLabelsVisible(false);
+ yAxis.setTickMarkVisible(false);
+ yAxis.setMinorTickVisible(false);
+
+ chart = new LineChart<>(xAxis, yAxis);
+ chart.setCreateSymbols(false);
+ chart.setLegendVisible(false);
+ chart.setHorizontalGridLinesVisible(false);
+ chart.setVerticalGridLinesVisible(false);
+ chart.setAlternativeRowFillVisible(false);
+ chart.setAnimated(false);
+ chart.setPrefHeight(250);
+ chart.setMinHeight(200);
+ chart.setMaxHeight(300);
+ chart.setMaxWidth(Double.MAX_VALUE);
+ chart.setMinWidth(0);
+ dataSeries = new XYChart.Series<>();
+ chart.prefHeightProperty().bind(getRootPane().heightProperty().divide(5));
+ chart.minHeightProperty().set(50);
+ chart.getData().add(dataSeries);
+
+ // Trade Buttons Row
+ HBox tradeActions = new HBox();
+ tradeActions.setAlignment(Pos.CENTER);
+ tradeActions.setSpacing(300); // Push buy/sell to opposite sides
+
+ Button buyBtn = new Button("buy");
+ buyBtn.getStyleClass().add("buy-button");
+ registerButton(StatsActions.BUY_SHARES, buyBtn);
+
+ Button sellBtn = new Button("sell");
+ sellBtn.getStyleClass().add("sell-button");
+ registerButton(StatsActions.SELL_SHARES, sellBtn);
+
+ tradeActions.getChildren().addAll(buyBtn, sellBtn);
+
+ mainContent.getChildren().addAll(selectedStock, chart, tradeActions);
+ getRootPane().getChildren().addAll(scrollPane, mainContent);
+ }
+
+ @Override
+ protected void initStyling() {
+ sidebar.getStyleClass().add("market-sidebar");
+ for (Button b : stockButtons) {
+ b.getStyleClass().add("stock-button");
+ }
+ selectedStock.getStyleClass().add("selected-stock-pill");
+ }
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarController.java
index 542c2b3..2f0c344 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarController.java
@@ -17,5 +17,11 @@ public TopBarController(final TopBarView viewElement, final EventManager eventMa
@Override
protected void initInteractions() {
getViewElement().setOnAction(TopBarActions.EXIT, () -> changeScene(ViewEnum.MAIN_MENU));
+
+ getViewElement().setOnAction(TopBarActions.STATS, () -> changeScene(ViewEnum.MAIN_MENU));
+
+ getViewElement().setOnAction(TopBarActions.MARKET, () -> changeScene(ViewEnum.MAIN_MENU));
+
+ getViewElement().setOnAction(TopBarActions.SETTINGS, () -> changeScene(ViewEnum.MAIN_MENU));
}
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarView.java
index b1ab559..e3d5b57 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/topbar/TopBarView.java
@@ -5,6 +5,8 @@
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import java.util.stream.Stream;
@@ -26,11 +28,25 @@ protected void initLayout() {
HBox navRow = new HBox(20);
navRow.setAlignment(Pos.CENTER);
+ navRow.setMaxWidth(Double.MAX_VALUE);
+ navRow.setMinHeight(Region.USE_PREF_SIZE);
+
+ //VBox.setVgrow(getRootPane(), Priority.SOMETIMES);
+ HBox.setHgrow(navRow, Priority.ALWAYS);
+
+ getRootPane().setAlignment(Pos.TOP_CENTER);
+ getRootPane().setFillWidth(true);
+ getRootPane().setPrefWidth(Double.MAX_VALUE);
+
quitBtn = new Button("Quit");
statsBtn = new Button("Stats");
marketBtn = new Button("Market");
settingsBtn = new Button("Settings");
+ Stream.of(quitBtn, statsBtn, marketBtn, settingsBtn).forEach(b -> {
+ HBox.setHgrow(b, Priority.ALWAYS);
+ });
+
navRow.getChildren().addAll(
quitBtn,
statsBtn,
@@ -38,18 +54,18 @@ protected void initLayout() {
settingsBtn
);
+
getRootPane().getChildren().addAll(navRow, summaryView.getRootPane());
registerButton(TopBarActions.EXIT, quitBtn);
registerButton(TopBarActions.STATS, statsBtn);
registerButton(TopBarActions.MARKET, marketBtn);
registerButton(TopBarActions.SETTINGS, settingsBtn);
-
}
@Override
protected void initStyling() {
- getRootPane().getStyleClass().add("top-bar"); // For your CSS file
+ getRootPane().getStyleClass().add("top-bar");
Stream.of(quitBtn, statsBtn, marketBtn, settingsBtn)
.forEach(b -> b.getStyleClass().add("menu-button"));
}
diff --git a/src/main/resources/styles.css b/src/main/resources/styles.css
index 13e27d0..43fe000 100644
--- a/src/main/resources/styles.css
+++ b/src/main/resources/styles.css
@@ -8,17 +8,23 @@
-fx-alignment: center;
}
-/* Base button styling */
+/* Base buttons */
.menu-button {
-fx-background-color: rgba(255, 255, 255, 0.7);
- /* Translucent white */
- -fx-background-radius: 15;
- -fx-min-width: 350;
- -fx-min-height: 60;
+ -fx-background-radius: 12;
+
+ -fx-min-width: 50;
+ -fx-pref-width: 200;
+ -fx-max-width: 350;
+
+ -fx-min-height: 50;
+ -fx-max-height: 70;
+
-fx-font-weight: bold;
-fx-font-style: italic;
-fx-font-size: 24px;
-fx-text-fill: black;
+
-fx-cursor: hand;
}
@@ -32,7 +38,6 @@
/* Background image styling */
.main-menu-bg {
-fx-background-image: url("millionsbackground.png");
- /* Replace with your image path */
-fx-background-size: cover;
-fx-background-position: center;
}
@@ -145,10 +150,11 @@
}
/* ------------- TOP BAR ------------- */
.top-bar {
- -fx-background-color: rgba(255, 255, 255, 0.7);
- -fx-background-radius: 20;
+ -fx-background-color: rgba(69, 69, 69, 0.7); /* Nice */
-fx-margin: 10;
- -fx-padding: 1%;
+ -fx-padding: 20 1%;
+ -fx-min-width: 100%;
+ -fx-pref-width: 100%;
}
@@ -168,7 +174,7 @@
/* ------------- SUMMARY IN TOP BAR -----------*/
.summary-container {
-fx-border-color: black;
- -fx-border-width: 1 0 1 0; /* Horizontal lines from image */
+ -fx-border-width: 1 0 1 0;
-fx-padding: 10;
}
@@ -183,6 +189,7 @@
-fx-font-family: "Aptos";
-fx-font-weight: bold;
-fx-font-size: 24;
+ -fx-min-width: 200;
}
.chart-series-line {
@@ -220,10 +227,64 @@
.next-button {
-fx-background-color: #e0e0e0;
- -fx-background-radius: 10;
- -fx-font-family: "Aptos";
+ -fx-background-radius: 5;
+ -fx-min-width: 60;
+ -fx-pref-width: 100;
+ -fx-max-width: 100;
-fx-font-weight: bold;
- -fx-padding: 5 15;
-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.2), 2, 0, 0, 1);
-fx-cursor: hand;
+}
+
+
+/* --------------- IN GAME VIEW ------------- */
+.market-sidebar {
+ -fx-border-color: transparent black transparent transparent;
+ -fx-border-width: 0 1 0 0;
+ -fx-padding: 20;
+}
+
+.stock-button {
+ -fx-background-color: transparent;
+ -fx-font-weight: bold;
+ -fx-font-style: italic;
+ -fx-font-size: 24;
+}
+
+.selected-stock-pill {
+ -fx-background-color: #e0e0e0;
+ -fx-background-radius: 10;
+ -fx-padding: 10 40;
+ -fx-font-size: 24;
+ -fx-font-weight: bold;
+ -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.2), 5, 0, 0, 2);
+}
+
+.buy-button {
+ -fx-graphic: url('Icons/plus2.png');
+ -fx-content-display: left;
+ -fx-graphic-text-gap: 10;
+ -fx-background-color: #00c853;
+ -fx-background-radius: 30;
+ -fx-text-fill: black;
+ -fx-font-style: italic;
+ -fx-font-weight: bold;
+ -fx-min-width: 150;
+ -fx-max-width: 200;
+}
+
+.sell-button {
+ -fx-graphic: url('Icons/minus2.png');
+ -fx-background-color: #d50000;
+ -fx-background-radius: 30;
+ -fx-text-fill: black;
+ -fx-font-style: italic;
+ -fx-font-weight: bold;
+ -fx-min-width: 150;
+ -fx-max-width: 200;
+}
+
+.buy-button:hover, .sell-button:hover {
+ -fx-brightness: 1.2;
+ -fx-cursor: hand;
}
\ No newline at end of file
From 1800ef949162e96d4d5841dad40e9053cc60bfda Mon Sep 17 00:00:00 2001
From: =
Date: Tue, 12 May 2026 18:59:59 +0200
Subject: [PATCH 5/9] Feat: Updated ViewManagerTest
---
.../g40/mappe/view/ViewManagerTest.java | 20 ++-----------------
1 file changed, 2 insertions(+), 18 deletions(-)
diff --git a/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManagerTest.java b/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManagerTest.java
index b5edcfe..f4d04e9 100644
--- a/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManagerTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManagerTest.java
@@ -26,7 +26,7 @@ public void start(final Stage stage) {
stage.setScene(new Scene(new Pane()));
testEventManager = new EventManager();
testViewManager = new ViewManager(stage, testEventManager);
- genericViewElement = new GenericViewElement(new Pane(), "Test View");
+ genericViewElement = new GenericViewElement(new Pane(), ViewEnum.IN_GAME);
}
@Test
@@ -73,7 +73,7 @@ private class GenericViewElement extends ViewElement {
public Boolean buttonPressed = false;
private Button interactableButton;
- protected GenericViewElement(final Pane rootPane, final String viewName) {
+ protected GenericViewElement(final Pane rootPane, final ViewEnum viewName) {
super(rootPane, viewName, GenericActions.class);
}
@@ -94,20 +94,4 @@ public Button getInteractableButton() {
@Override
protected void initStyling() { }
}
-
- private class GenericViewController extends ViewController {
-
- protected GenericViewController(final ViewManagerTest.GenericViewElement viewElement,
- final EventManager eventManager)
- throws IllegalArgumentException {
- super(viewElement, eventManager);
- }
-
- @Override
- protected void initInteractions() {
- getViewElement().setOnAction(GenericActions.ACTION_1, () -> {
- getViewElement().buttonPressed = true;
- });
- }
- }
}
From acd52fab9b5c283eba47824c51e7c9d7291c9fdd Mon Sep 17 00:00:00 2001
From: =
Date: Wed, 13 May 2026 10:30:20 +0200
Subject: [PATCH 6/9] Feat: Made week a listenable integer. Also added a method
in player for handling transactions
---
.../idatt2003/g40/mappe/engine/Exchange.java | 39 +++++++++++++++----
.../idi/idatt2003/g40/mappe/model/Player.java | 17 ++++++++
2 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java
index 8eec48d..84f9611 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java
@@ -9,7 +9,13 @@
import edu.ntnu.idi.idatt2003.g40.mappe.service.PurchaseCalculator;
import edu.ntnu.idi.idatt2003.g40.mappe.service.SaleCalculator;
import edu.ntnu.idi.idatt2003.g40.mappe.service.TransactionCalculator;
+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.EventPublisher;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventType;
import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator;
+import javafx.beans.property.IntegerProperty;
+import javafx.beans.property.SimpleIntegerProperty;
import java.math.BigDecimal;
import java.util.ArrayList;
@@ -40,7 +46,7 @@ public final class Exchange {
/**
* Current week (set to 1 in constructor).
* */
- private int week;
+ private final IntegerProperty week = new SimpleIntegerProperty(1);
/**
* Map of {@link Stock} objects. Key is stock symbol. Value is stock.
@@ -65,7 +71,6 @@ public Exchange(final String name, final List stocks) throws IllegalArgum
throw new IllegalArgumentException("Invalid exchange parameters!");
}
this.name = name;
- this.week = 1;
this.stockMap = new HashMap<>();
this.random = new Random();
for (Stock stock : stocks) {
@@ -88,9 +93,25 @@ public String getName() {
* @return week.
* */
public int getWeek() {
+ return week.get();
+ }
+
+ /**
+ * Getter method for the {@link IntegerProperty} object of week.
+ *
+ * @return week.
+ * */
+ public IntegerProperty weekProperty() {
return week;
}
+ /**
+ * Advances the week.
+ * */
+ public void nextWeek() {
+ week.set(week.get() + 1);
+ }
+
/**
* Method for checking whether exchange has a stock.
*
@@ -159,8 +180,10 @@ public Transaction buy(final String symbol,
Stock stock = stockMap.get(symbol);
Share share = new Share(stock, quantity, stock.getSalesPrice());
TransactionCalculator calculator = new PurchaseCalculator(share);
- player.withdrawMoney(calculator.calculateTotal());
- return new Purchase(share, week, calculator);
+ Purchase purchase = new Purchase(share, week.get(), calculator);
+ player.handleTransaction(purchase);
+ purchase.commit(player);
+ return purchase;
}
/**
@@ -179,15 +202,17 @@ public Transaction sell(final Share share, final Player player)
throw new IllegalArgumentException("Invalid sell!");
}
TransactionCalculator calculator = new SaleCalculator(share);
- player.addMoney(calculator.calculateTotal());
- return new Sale(share, week, calculator);
+ Sale sale = new Sale(share, week.get(), calculator);
+ player.handleTransaction(sale);
+ sale.commit(player);
+ return sale;
}
/**
* Method for advancing time, increasing the amount of weeks.
* */
public void advance() {
- week++;
+ nextWeek();
for (Stock stock : stockMap.values()) {
BigDecimal currentPrice = stock.getSalesPrice();
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java
index 971313e..4fc551d 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java
@@ -149,4 +149,21 @@ public BigDecimal getNetWorth() {
public PlayerStatus getStatus() {
return PlayerStatusController.getStatus(this);
}
+
+ /**
+ * Method for handling a transaction for the player.
+ *
+ * @param transaction the transaction to handle.
+ * */
+ public void handleTransaction(final Transaction transaction) {
+ transactionArchive.add(transaction);
+
+ if (transaction instanceof Purchase purchase) {
+ withdrawMoney(purchase.getCalculator().calculateTotal());
+ portfolio.addShare(purchase.getShare());
+ } else if (transaction instanceof Sale sale) {
+ addMoney(sale.getCalculator().calculateTotal());
+ portfolio.removeShare(sale.getShare());
+ }
+ }
}
From ac26ea0e14d7e55490f3370977a3ab64b13cc5b6 Mon Sep 17 00:00:00 2001
From: =
Date: Wed, 13 May 2026 10:31:52 +0200
Subject: [PATCH 7/9] Feat: Added stats page to in game view
---
.../ntnu/idi/idatt2003/g40/mappe/Main.java | 23 +++++-----
.../financialsummary/SummaryController.java | 12 ++++-
.../widgets/financialsummary/SummaryView.java | 2 +-
.../view/widgets/stats/StatsController.java | 44 ++++++++++++++++++-
.../mappe/view/widgets/stats/StatsView.java | 41 ++++++++++++-----
src/main/resources/styles.css | 2 -
6 files changed, 93 insertions(+), 31 deletions(-)
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 9321762..841fbb4 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
@@ -1,5 +1,6 @@
package edu.ntnu.idi.idatt2003.g40.mappe;
+import edu.ntnu.idi.idatt2003.g40.mappe.engine.Exchange;
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;
@@ -38,18 +39,6 @@
* */
public class Main extends Application {
- static void main() {
- FileParser parser1 = new FileParser("src/main/resources/dummydata.txt");
- FileConverter converter1 = new FileConverter();
- try {
- List stocksInFile = converter1.getStocksFromStrings(parser1.readFile());
- parser1.writeStocksToFile(converter1.stocksToStrings(stocksInFile));
- stocksInFile.forEach(s -> System.out.println(s.getSymbol()));
- } catch (IOException e) {
- System.err.println(e.getMessage());
- }
- }
-
/**
* {@inheritDoc}
* */
@@ -66,6 +55,14 @@ public void start(final Stage stage) throws Exception {
EventManager eventManager = new EventManager();
ViewManager viewManager = new ViewManager(stage, eventManager);
+ List stocksInFile;
+ FileParser parser1 = new FileParser("src/main/resources/dummydata.txt");
+
+ FileConverter converter1 = new FileConverter();
+ stocksInFile = converter1.getStocksFromStrings(parser1.readFile());
+
+ Exchange exchange = new Exchange("Exchange", stocksInFile);
+
// Main menu
MainMenuView mainMenuView = new MainMenuView();
new MainMenuController(mainMenuView, eventManager);
@@ -85,7 +82,7 @@ public void start(final Stage stage) throws Exception {
// Summary section of the top bar
SummaryView summaryView = new SummaryView();
- new SummaryController(summaryView, eventManager);
+ new SummaryController(summaryView, eventManager, exchange);
// Top bar
TopBarView topBarView = new TopBarView(summaryView);
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
index fecc2ae..5f720e8 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
@@ -1,23 +1,31 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary;
+import edu.ntnu.idi.idatt2003.g40.mappe.engine.Exchange;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
public class SummaryController extends ViewController {
+ private Exchange exchange;
/**
* {@inheritDoc}.
*/
public SummaryController(final SummaryView viewElement,
- final EventManager eventManager)
+ final EventManager eventManager,
+ final Exchange exchange)
throws IllegalArgumentException {
+ this.exchange = exchange;
super(viewElement, eventManager);
}
@Override
protected void initInteractions() {
getViewElement().setOnAction(SummaryActions.NEXT_WEEK, () -> {
- System.out.println("Next week!");
+ exchange.nextWeek();
+ });
+
+ exchange.weekProperty().addListener((observable, o, n) -> {
+ getViewElement().setWeek((Integer) n);
});
}
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
index 100f9eb..816d87f 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryView.java
@@ -84,7 +84,7 @@ protected void initLayout() {
navInfo.setAlignment(Pos.TOP_CENTER);
nextBtn = new Button("next");
- weekLabel = new Label("week: 0");
+ weekLabel = new Label("week: 1");
weekLabel.getStyleClass().add("week-label");
Region spacerR = new Region();
VBox.setVgrow(spacerR, Priority.ALWAYS);
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
index 275ea4f..873ca7b 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
@@ -1,4 +1,46 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats;
-public class StatsController {
+import edu.ntnu.idi.idatt2003.g40.mappe.engine.Exchange;
+import edu.ntnu.idi.idatt2003.g40.mappe.model.Player;
+import edu.ntnu.idi.idatt2003.g40.mappe.model.Share;
+import edu.ntnu.idi.idatt2003.g40.mappe.model.Transaction;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.PurchaseCalculator;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.TransactionCalculator;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.TransactionFactory;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.TransactionType;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
+import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
+
+import java.math.BigDecimal;
+
+public class StatsController extends ViewController {
+
+ private Player player;
+ private Exchange exchange;
+
+ /**
+ * {@inheritDoc}
+ */
+ public StatsController(final StatsView viewElement,
+ final EventManager eventManager,
+ final Player player,
+ final Exchange exchange)
+ throws IllegalArgumentException {
+ this.player = player;
+ this.exchange = exchange;
+ super(viewElement, eventManager);
+ }
+
+ @Override
+ protected void initInteractions() {
+ getViewElement().setOnAction(StatsActions.BUY_SHARES, () -> {
+ BigDecimal amountToBuy = new BigDecimal("1.0");
+ Transaction transaction = exchange.buy(
+ getViewElement().getCurrentStock().getSymbol(),
+ amountToBuy,
+ player
+ );
+
+ });
+ }
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsView.java
index 4b6e832..0c4c702 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsView.java
@@ -9,10 +9,10 @@
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
-import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
public class StatsView extends ViewElement {
@@ -22,7 +22,9 @@ public class StatsView extends ViewElement {
private ArrayList stocks;
private ArrayList stockStrings;
private ArrayList stockButtons;
- private Label selectedStock;
+ private Stock selectedStock;
+ private Label selectedStockLabel;
+ private HBox tradeActions;
public StatsView() {
super(new HBox(), StatsActions.class);
@@ -36,6 +38,7 @@ protected void initLayout() {
sidebar = new VBox(10);
sidebar.setPrefWidth(150);
sidebar.setMaxHeight(Double.MAX_VALUE);
+ sidebar.setMinWidth(150);
VBox.setVgrow(sidebar, Priority.ALWAYS);
stocks = new ArrayList<>();
@@ -63,8 +66,6 @@ protected void initLayout() {
stockStrings.add("NVID");
stockStrings.add("NVID");
-
-
stockButtons = new ArrayList<>();
for (String t : stockStrings) {
Button btn = new Button(t);
@@ -76,17 +77,18 @@ protected void initLayout() {
scrollPane.setFitToWidth(true);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+ scrollPane.setMinWidth(150);
VBox.setVgrow(scrollPane, Priority.ALWAYS);
scrollPane.setMaxHeight(Double.MAX_VALUE);
VBox mainContent = new VBox(20);
mainContent.setAlignment(Pos.CENTER);
- HBox.setHgrow(mainContent, Priority.ALWAYS);
mainContent.setMaxHeight(Double.MAX_VALUE);
+ HBox.setHgrow(mainContent, Priority.ALWAYS);
VBox.setVgrow(mainContent, Priority.ALWAYS);
- selectedStock = new Label("APL");
+ selectedStockLabel = new Label("AAPL");
NumberAxis xAxis = new NumberAxis(1, 22, 1);
xAxis.setMinorTickVisible(false);
@@ -115,10 +117,11 @@ protected void initLayout() {
chart.minHeightProperty().set(50);
chart.getData().add(dataSeries);
- // Trade Buttons Row
- HBox tradeActions = new HBox();
+ tradeActions = new HBox();
tradeActions.setAlignment(Pos.CENTER);
- tradeActions.setSpacing(300); // Push buy/sell to opposite sides
+ tradeActions.setMaxWidth(500);
+ tradeActions.setPrefWidth(500);
+ tradeActions.minWidth(100);
Button buyBtn = new Button("buy");
buyBtn.getStyleClass().add("buy-button");
@@ -128,18 +131,32 @@ protected void initLayout() {
sellBtn.getStyleClass().add("sell-button");
registerButton(StatsActions.SELL_SHARES, sellBtn);
- tradeActions.getChildren().addAll(buyBtn, sellBtn);
+ Region spacer = new Region();
+ HBox.setHgrow(spacer, Priority.ALWAYS);
+ tradeActions.getChildren().addAll(buyBtn, spacer, sellBtn);
- mainContent.getChildren().addAll(selectedStock, chart, tradeActions);
+ mainContent.getChildren().addAll(selectedStockLabel, chart, tradeActions);
getRootPane().getChildren().addAll(scrollPane, mainContent);
+
+ registerButton(StatsActions.BUY_SHARES, buyBtn);
+ registerButton(StatsActions.SELL_SHARES, sellBtn);
}
@Override
protected void initStyling() {
sidebar.getStyleClass().add("market-sidebar");
+ tradeActions.getStyleClass().add("trade-actions");
for (Button b : stockButtons) {
b.getStyleClass().add("stock-button");
}
- selectedStock.getStyleClass().add("selected-stock-pill");
+ selectedStockLabel.getStyleClass().add("selected-stock-pill");
+ }
+
+ public void setCurrentStock(final Stock stock) {
+ selectedStock = stock;
+ }
+
+ public Stock getCurrentStock() {
+ return selectedStock;
}
}
diff --git a/src/main/resources/styles.css b/src/main/resources/styles.css
index 43fe000..6001869 100644
--- a/src/main/resources/styles.css
+++ b/src/main/resources/styles.css
@@ -239,8 +239,6 @@
/* --------------- IN GAME VIEW ------------- */
.market-sidebar {
- -fx-border-color: transparent black transparent transparent;
- -fx-border-width: 0 1 0 0;
-fx-padding: 20;
}
From f3de9d60016abaf89b418256d38c9703877b3c43 Mon Sep 17 00:00:00 2001
From: =
Date: Wed, 13 May 2026 11:35:00 +0200
Subject: [PATCH 8/9] Minor changes to MVC impementation
---
.../idi/idatt2003/g40/mappe/view/ViewElement.java | 14 --------------
.../idi/idatt2003/g40/mappe/view/ViewManager.java | 4 +++-
2 files changed, 3 insertions(+), 15 deletions(-)
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 a0b0f1c..0463471 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
@@ -113,20 +113,6 @@ protected void setRootPane(final T pane) {
rootPane = pane;
}
- /**
- * Getter method for buttons in this view.
- *
- * Gotten by the associated {@link ViewController} object that hooks
- * the buttons to functionality.
- *
- * @return {@link Map} object containing all buttons
- * in this view element.
- *
- */
- public Map getButtons() {
- return buttonMap;
- }
-
/**
* Method that initializes the layout for the view element.
*
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManager.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManager.java
index 183fb64..51eb63f 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManager.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewManager.java
@@ -4,6 +4,8 @@
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventSubscriber;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventType;
+
+import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import javafx.scene.Scene;
@@ -54,7 +56,7 @@ public ViewManager(final Stage stage, final EventManager eventManager)
if (stage == null || eventManager == null) {
throw new IllegalArgumentException("Invalid ViewManager constructor arguments!");
} else {
- viewMap = new HashMap<>();
+ viewMap = new EnumMap<>(ViewEnum.class);
eventManager.addSubscriber(this, EventType.SCENE_CHANGE);
this.stage = stage;
}
From cff2ef57ec6674e54ae1dba43b1834988787d01e Mon Sep 17 00:00:00 2001
From: =
Date: Wed, 13 May 2026 11:44:48 +0200
Subject: [PATCH 9/9] Minor tweaks in ViewController
---
.../g40/mappe/view/ViewController.java | 24 ++++++-------------
1 file changed, 7 insertions(+), 17 deletions(-)
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewController.java
index 3284e51..fed6cfa 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ViewController.java
@@ -55,16 +55,6 @@ protected ViewController(final T1 viewElement,
}
}
- /**
- * Getter method for the event manager.
- *
- * @return the {@link EventManager} object.
- *
- */
- protected EventManager getEventManager() {
- return eventManager;
- }
-
/**
* Getter method for the current view element.
*
@@ -81,12 +71,6 @@ public T1 getViewElement() {
*/
protected abstract void initInteractions();
- @Override
- public final void invoke(final EventData data,
- final EventManager eventManager) {
- eventManager.invokeEvent(data);
- }
-
/**
* Basic method for invoking an event to change to a specific view.
*
@@ -94,7 +78,13 @@ public final void invoke(final EventData data,
* */
protected void changeScene(final ViewEnum viewName) {
ViewData viewData = new ViewData(viewName);
- EventData eventData = new EventData(EventType.SCENE_CHANGE, viewData);
+ EventData eventData = new EventData<>(EventType.SCENE_CHANGE, viewData);
invoke(eventData, eventManager);
}
+
+ @Override
+ public final void invoke(final EventData data,
+ final EventManager eventManager) {
+ eventManager.invokeEvent(data);
+ }
}