Skip to content

text vis og setting upgrade #137

Merged
merged 1 commit into from
May 26, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.settings;

/**
* User-triggered actions available on the main-menu settings view.
*
* <p>{@link #AUDIO}, {@link #VIDEO} and {@link #HOTKEYS} are kept for
* backwards compatibility with the older sidebar/tab layout - they no
* longer correspond to user-pressable buttons in the redesigned view,
* but the {@code SettingsController} still wires no-op handlers to
* them so existing call sites keep compiling.</p>
* */
public enum SettingsActions {
/** Legacy audio-tab action. No longer triggered by the redesigned view. */
AUDIO,

/** Legacy video-tab action. No longer triggered by the redesigned view. */
VIDEO,

/** Legacy hot-keys-tab action. No longer triggered by the redesigned view. */
HOTKEYS,
BACK;

/** Returns to the main menu. */
BACK,

/** Selects the dark theme. */
DARK_MODE,

/** Selects the light theme. */
LIGHT_MODE;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.settings;

import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventData;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventType;
import edu.ntnu.idi.idatt2003.g40.mappe.utils.ThemeManager;
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}.
*
* <p>Wires up the category buttons to switch the right-hand content,
* and the Back button to return to the main menu.</p>
* <p>Wires up the Back button to return to the main menu and the
* theme toggle buttons to the global {@link ThemeManager}. The
* legacy {@code AUDIO}, {@code VIDEO} and {@code HOTKEYS} actions
* are no longer pressable in the redesigned view, so no handlers
* are attached for them.</p>
*/
public class SettingsController extends ViewController<SettingsView> {

Expand All @@ -24,14 +25,26 @@ public class SettingsController extends ViewController<SettingsView> {
public SettingsController(final SettingsView view,
final EventManager eventManager) {
super(view, eventManager);
// Sync the highlighted theme button with the current theme on
// construction (matches InGameSettingsController behaviour).
getViewElement().setActiveTheme(
ThemeManager.getInstance().getCurrentTheme());
}

/** {@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));
getViewElement().setOnAction(SettingsActions.BACK,
() -> changeScene(ViewEnum.MAIN_MENU));

getViewElement().setOnAction(SettingsActions.DARK_MODE, () -> {
ThemeManager.getInstance().setTheme(ThemeManager.Theme.DARK);
getViewElement().setActiveTheme(ThemeManager.Theme.DARK);
});

getViewElement().setOnAction(SettingsActions.LIGHT_MODE, () -> {
ThemeManager.getInstance().setTheme(ThemeManager.Theme.LIGHT);
getViewElement().setActiveTheme(ThemeManager.Theme.LIGHT);
});
}
}
}
Original file line number Diff line number Diff line change
@@ -1,174 +1,168 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.settings;

import edu.ntnu.idi.idatt2003.g40.mappe.utils.ThemeManager;
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;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;

/**
* View shown when the player clicks "Settings" on the main menu.
*
* <p>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. </p>
* <p>
* Mirrors
* {@link edu.ntnu.idi.idatt2003.g40.mappe.view.ingame.settings.InGameSettingsView}
* so the player gets the same panel layout in both places: a compact
* card with a header (title + Back button) and a single Theme section
* containing a Dark / Light toggle.
* </p>
*
* <p>
* The view applies the {@link ThemeManager} directly when the
* player clicks the Dark/Light buttons so the toggle works
* identically to the in-game one.
* </p>
*/
public class SettingsView extends ViewElement<StackPane, SettingsActions> {

/** Category buttons on the left side. */
private Button audioButton;
private Button videoButton;
private Button hotKeysButton;

/** Bottom-left back button. */
/** Back-to-menu button shown in the panel's top-right corner. */
private Button backButton;

/** The currently displayed content pane on the right side. */
private StackPane contentArea;
/** Selects the dark theme. */
private Button darkModeButton;

/** Master volume slider for the audio section. */
private Slider masterVolumeSlider;
/** Selects the light theme. */
private Button lightModeButton;

/** Main border layout containing the sidebar and content area. */
private BorderPane mainPanel;
/** Modal-style card hosting the settings sections. */
private VBox panel;

/**
* Constructor.
*
* <p>Constructs with name "SettingsView"</p>
* <p>
* Constructs with name "SettingsView"
* </p>
*/
public SettingsView() {
super(new StackPane(), ViewEnum.SETTINGS, SettingsActions.class);
}

public Slider getMasterVolumeSlider() {
return masterVolumeSlider;
}

/**
* Replaces the content area with the audio section (master volume).
* Getter for the dark-mode button.
*
* @return the dark-mode button.
*/
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(24, title, masterVolumeSlider);
audioBox.setAlignment(Pos.TOP_LEFT);
audioBox.setPadding(new Insets(20, 30, 30, 30));

contentArea.getChildren().setAll(audioBox);
public Button getDarkModeButton() {
return darkModeButton;
}

/**
* Replaces the content area with the video section placeholder.
* Getter for the light-mode button.
*
* @return the light-mode button.
*/
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_LEFT);
videoBox.setPadding(new Insets(20, 30, 30, 30));

contentArea.getChildren().setAll(videoBox);
public Button getLightModeButton() {
return lightModeButton;
}

/**
* Replaces the content area with the hot keys section placeholder.
* Highlights the active theme button so the player always sees which
* theme is currently selected. Mirrors {@code InGameSettingsView}.
*
* @param theme the active {@link ThemeManager.Theme}.
*/
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_LEFT);
hotKeysBox.setPadding(new Insets(20, 30, 30, 30));

contentArea.getChildren().setAll(hotKeysBox);
public void setActiveTheme(final ThemeManager.Theme theme) {
darkModeButton.getStyleClass().remove("active");
lightModeButton.getStyleClass().remove("active");
if (theme == ThemeManager.Theme.LIGHT) {
lightModeButton.getStyleClass().add("active");
} else {
darkModeButton.getStyleClass().add("active");
}
}

/** {@inheritDoc} */
@Override
protected void initLayout() {
audioButton = new Button("Audio");
videoButton = new Button("Video");
hotKeysButton = new Button("Hot keys");
// Header row: title + back button.
Label title = new Label("Settings");
title.getStyleClass().add("ingame-settings-title");

Region headerSpacer = new Region();
HBox.setHgrow(headerSpacer, Priority.ALWAYS);

backButton = new Button("Back");
backButton.setFocusTraversable(false);
backButton.getStyleClass().add("ingame-settings-toggle-button");

HBox header = new HBox(12, title, headerSpacer, backButton);
header.setAlignment(Pos.CENTER_LEFT);

// Theme section.
Label themeSectionLabel = new Label("Theme");
themeSectionLabel.getStyleClass().add("ingame-settings-section-label");

Label themeDescription = new Label(
"Choose between dark and light appearance for the game.");
themeDescription.getStyleClass().add("ingame-settings-description");
themeDescription.setWrapText(true);

darkModeButton = new Button("Dark mode");
lightModeButton = new Button("Light mode");
darkModeButton.setFocusTraversable(false);
lightModeButton.setFocusTraversable(false);
darkModeButton.getStyleClass().add("ingame-settings-toggle-button");
lightModeButton.getStyleClass().add("ingame-settings-toggle-button");

HBox themeToggleRow = new HBox(12, darkModeButton, lightModeButton);
themeToggleRow.setAlignment(Pos.CENTER_LEFT);

VBox themeSection = new VBox(10, themeSectionLabel,
themeDescription, themeToggleRow);
themeSection.setAlignment(Pos.TOP_LEFT);

// Assemble panel - same dimensions as InGameSettingsView for visual
// parity between the two settings entry points.
panel = new VBox(22, header, themeSection);
panel.setAlignment(Pos.TOP_LEFT);
panel.setPadding(new Insets(28, 32, 32, 32));
panel.setMaxWidth(440);
panel.setMaxHeight(280);
panel.setPrefWidth(440);
panel.getStyleClass().add("ingame-settings-panel");

getRootPane().getStyleClass().add("main-menu-bg");
getRootPane().getChildren().add(panel);
StackPane.setAlignment(panel, Pos.CENTER);

// Sidebar header so the panel doesn't feel anonymous.
Label sidebarHeader = new Label("Settings");
sidebarHeader.getStyleClass().add("settings-title");
VBox.setMargin(sidebarHeader, new Insets(0, 0, 8, 0));

// 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(8,
sidebarHeader,
audioButton, videoButton, hotKeysButton, spacer, backButton);
sidebar.setAlignment(Pos.TOP_LEFT);
sidebar.setPadding(new Insets(28, 22, 28, 22));
sidebar.setPrefWidth(200);

contentArea = new StackPane();
contentArea.setPadding(new Insets(10));

mainPanel = new BorderPane();
mainPanel.setLeft(sidebar);
mainPanel.setCenter(contentArea);
mainPanel.setMaxWidth(820);
mainPanel.setMaxHeight(520);
mainPanel.setPrefWidth(820);
mainPanel.setPrefHeight(520);

// Center the BorderPane.
HBox centerWrapper = new HBox(mainPanel);
centerWrapper.setAlignment(Pos.CENTER);

getRootPane().getChildren().add(centerWrapper);

// Default section shown when settings opens.
showAudioSection();

registerButton(SettingsActions.AUDIO, audioButton);
registerButton(SettingsActions.VIDEO, videoButton);
registerButton(SettingsActions.HOTKEYS, hotKeysButton);
registerButton(SettingsActions.BACK, backButton);
registerButton(SettingsActions.DARK_MODE, darkModeButton);
registerButton(SettingsActions.LIGHT_MODE, lightModeButton);
}

/** {@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");
// Styling is applied via the .ingame-settings-* and .main-menu-bg
// style classes assigned in initLayout(). Nothing else to do here.
}

/** {@inheritDoc} */
@Override
public void onUpdate() {
// Reset til audio-section hver gang viewet vises.
if (contentArea != null) {
showAudioSection();
// Re-sync the highlighted theme button every time the view shows,
// since the player may have toggled the theme from the in-game
// overlay since they last visited.
if (darkModeButton != null && lightModeButton != null) {
setActiveTheme(ThemeManager.getInstance().getCurrentTheme());
}
}
}
11 changes: 1 addition & 10 deletions src/main/resources/saves/Newbie.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@
"stockDataPath": null,
"week": 5,
"ownedShares": [
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 }
{ "symbol": "NVDA", "quantity": 50.0, "purchasePrice": 191.27 }
],
"transactions": [
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 5.0, "price": 191.27, "week": 1 },
Expand Down
Loading