-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
EspenTinius
committed
May 26, 2026
1 parent
6815b80
commit 3e68358
Showing
5 changed files
with
522 additions
and
302 deletions.
There are no files selected for viewing
24 changes: 23 additions & 1 deletion
24
src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsActions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
216 changes: 105 additions & 111 deletions
216
src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/settings/SettingsView.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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()); | ||
| } | ||
| } | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.