-
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.
Merge pull request #125 from Team-40-IDATT2003/enhancement/122-deign
ny stil :)
- Loading branch information
Showing
13 changed files
with
2,043 additions
and
536 deletions.
There are no files selected for viewing
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
136 changes: 136 additions & 0 deletions
136
src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/utils/ThemeManager.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 |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| package edu.ntnu.idi.idatt2003.g40.mappe.utils; | ||
|
|
||
| import javafx.scene.Scene; | ||
|
|
||
| /** | ||
| * Singleton utility for managing the active visual theme of the application. | ||
| * | ||
| * <p>The base stylesheet ({@code styles.css}) defines the dark theme as the | ||
| * default. When light mode is activated, this manager adds the | ||
| * {@code "light-mode"} style class on the scene's root node, which causes the | ||
| * light-mode CSS overrides to take effect for all descendant nodes.</p> | ||
| * | ||
| * <p>The active scene is registered once from {@code Main} after the | ||
| * application has been initialized. After that, callers (e.g. the in-game | ||
| * settings panel) only need to call {@link #setTheme(Theme)} or | ||
| * {@link #toggleTheme()}.</p> | ||
| */ | ||
| public final class ThemeManager { | ||
|
|
||
| /** | ||
| * Style class added to the scene root to activate light mode. | ||
| * | ||
| * <p>Matches the {@code .light-mode} CSS rules in {@code styles.css}.</p> | ||
| * */ | ||
| public static final String LIGHT_MODE_CLASS = "light-mode"; | ||
|
|
||
| /** | ||
| * Available themes. | ||
| * */ | ||
| public enum Theme { | ||
| /** Default dark theme (no extra style class). */ | ||
| DARK, | ||
|
|
||
| /** Light theme (adds the {@link #LIGHT_MODE_CLASS} style class). */ | ||
| LIGHT | ||
| } | ||
|
|
||
| /** Singleton instance. */ | ||
| private static final ThemeManager INSTANCE = new ThemeManager(); | ||
|
|
||
| /** The currently registered scene. */ | ||
| private Scene scene; | ||
|
|
||
| /** The currently active theme. */ | ||
| private Theme currentTheme = Theme.DARK; | ||
|
|
||
| /** | ||
| * Private constructor for singleton. | ||
| * */ | ||
| private ThemeManager() { | ||
|
|
||
| } | ||
|
|
||
| /** | ||
| * Getter method for the singleton instance. | ||
| * | ||
| * @return the {@link ThemeManager} singleton. | ||
| * */ | ||
| public static ThemeManager getInstance() { | ||
| return INSTANCE; | ||
| } | ||
|
|
||
| /** | ||
| * Registers the active {@link Scene} with the theme manager. | ||
| * | ||
| * <p>Should be called once from {@code Main} after the scene is built. | ||
| * Re-registering with a new scene applies the current theme to it.</p> | ||
| * | ||
| * <p>A listener is attached to the scene's root property so that the | ||
| * active theme is re-applied whenever the {@code ViewManager} swaps the | ||
| * scene root for a view change.</p> | ||
| * | ||
| * @param scene the active scene. | ||
| * | ||
| * @throws IllegalArgumentException if scene is null. | ||
| * */ | ||
| public void registerScene(final Scene scene) { | ||
| if (scene == null) { | ||
| throw new IllegalArgumentException("Scene cannot be null!"); | ||
| } | ||
| this.scene = scene; | ||
| scene.rootProperty().addListener((obs, oldRoot, newRoot) -> applyCurrentTheme()); | ||
| applyCurrentTheme(); | ||
| } | ||
|
|
||
| /** | ||
| * Getter method for the active theme. | ||
| * | ||
| * @return the currently active {@link Theme}. | ||
| * */ | ||
| public Theme getCurrentTheme() { | ||
| return currentTheme; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the active theme and applies it to the registered scene. | ||
| * | ||
| * @param theme the {@link Theme} to set. | ||
| * | ||
| * @throws IllegalArgumentException if theme is null. | ||
| * */ | ||
| public void setTheme(final Theme theme) { | ||
| if (theme == null) { | ||
| throw new IllegalArgumentException("Theme cannot be null!"); | ||
| } | ||
| this.currentTheme = theme; | ||
| applyCurrentTheme(); | ||
| } | ||
|
|
||
| /** | ||
| * Toggles between {@link Theme#DARK} and {@link Theme#LIGHT}. | ||
| * */ | ||
| public void toggleTheme() { | ||
| setTheme(currentTheme == Theme.DARK ? Theme.LIGHT : Theme.DARK); | ||
| } | ||
|
|
||
| /** | ||
| * Applies the current theme to the registered scene. | ||
| * | ||
| * <p>For light mode, the {@link #LIGHT_MODE_CLASS} style class is added | ||
| * to the scene root. For dark mode, it is removed.</p> | ||
| * */ | ||
| private void applyCurrentTheme() { | ||
| if (scene == null || scene.getRoot() == null) { | ||
| return; | ||
| } | ||
| var styleClasses = scene.getRoot().getStyleClass(); | ||
| if (currentTheme == Theme.LIGHT) { | ||
| if (!styleClasses.contains(LIGHT_MODE_CLASS)) { | ||
| styleClasses.add(LIGHT_MODE_CLASS); | ||
| } | ||
| } else { | ||
| styleClasses.remove(LIGHT_MODE_CLASS); | ||
| } | ||
| } | ||
| } |
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
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
15 changes: 15 additions & 0 deletions
15
...ain/java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/settings/InGameSettingsActions.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 |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package edu.ntnu.idi.idatt2003.g40.mappe.view.ingame.settings; | ||
|
|
||
| /** | ||
| * User-triggered actions available in the in-game settings overlay. | ||
| * */ | ||
| public enum InGameSettingsActions { | ||
| /** Closes the settings overlay and returns to the game. */ | ||
| CLOSE, | ||
|
|
||
| /** Selects the dark theme. */ | ||
| DARK_MODE, | ||
|
|
||
| /** Selects the light theme. */ | ||
| LIGHT_MODE; | ||
| } |
66 changes: 66 additions & 0 deletions
66
.../java/edu/ntnu/idi/idatt2003/g40/mappe/view/ingame/settings/InGameSettingsController.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 |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package edu.ntnu.idi.idatt2003.g40.mappe.view.ingame.settings; | ||
|
|
||
| import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager; | ||
| 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.ingame.InGameView; | ||
|
|
||
| /** | ||
| * Controller for {@link InGameSettingsView}. | ||
| * | ||
| * <p>Wires the close button to remove the overlay from the | ||
| * {@link InGameView}, and the theme toggle buttons to the global | ||
| * {@link ThemeManager}.</p> | ||
| */ | ||
| public final class InGameSettingsController | ||
| extends ViewController<InGameSettingsView> { | ||
|
|
||
| /** The in-game view hosting this overlay. */ | ||
| private final InGameView inGameView; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param view the {@link InGameSettingsView} this controller is | ||
| * attached to. | ||
| * @param eventManager the active {@link EventManager}. | ||
| * @param inGameView the in-game view that hosts this settings overlay. | ||
| * */ | ||
| public InGameSettingsController(final InGameSettingsView view, | ||
| final EventManager eventManager, | ||
| final InGameView inGameView) { | ||
| this.inGameView = inGameView; | ||
| super(view, eventManager); | ||
| // Sync the highlighted button with the current theme on construction. | ||
| getViewElement().setActiveTheme(ThemeManager.getInstance().getCurrentTheme()); | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| protected void initInteractions() { | ||
| getViewElement().setOnAction(InGameSettingsActions.CLOSE, | ||
| inGameView::hideSettingsOverlay); | ||
|
|
||
| getViewElement().setOnAction(InGameSettingsActions.DARK_MODE, () -> { | ||
| ThemeManager.getInstance().setTheme(ThemeManager.Theme.DARK); | ||
| getViewElement().setActiveTheme(ThemeManager.Theme.DARK); | ||
| }); | ||
|
|
||
| getViewElement().setOnAction(InGameSettingsActions.LIGHT_MODE, () -> { | ||
| ThemeManager.getInstance().setTheme(ThemeManager.Theme.LIGHT); | ||
| getViewElement().setActiveTheme(ThemeManager.Theme.LIGHT); | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Shows the settings overlay on the host {@link InGameView}. | ||
| * | ||
| * <p>Re-syncs the active-theme highlight before showing, so that if the | ||
| * user has toggled the theme elsewhere, the panel reflects the current | ||
| * state.</p> | ||
| * */ | ||
| public void show() { | ||
| getViewElement().setActiveTheme(ThemeManager.getInstance().getCurrentTheme()); | ||
| inGameView.showSettingsOverlay(getViewElement().getRootPane()); | ||
| } | ||
| } |
Oops, something went wrong.