feat(theme): enhance theme management with storage capabilities and add unit tests
This commit is contained in:
@@ -1,13 +1,21 @@
|
||||
package de.extio.game_engine.renderer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.renderer.g2d.theme.Theme;
|
||||
|
||||
public interface ThemeManager {
|
||||
|
||||
List<String> getAvailableThemeNames();
|
||||
|
||||
Optional<Theme> loadThemeFromStorage(String themeName);
|
||||
|
||||
void saveThemeToStorage(Theme theme);
|
||||
|
||||
Optional<Theme> loadThemeFromStaticResource(StaticResource themeResource);
|
||||
|
||||
Theme getCurrentTheme();
|
||||
|
||||
void setCurrentTheme(Theme theme);
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -26,6 +25,7 @@ import de.extio.game_engine.renderer.g2d.theme.Theme;
|
||||
import de.extio.game_engine.renderer.g2d.theme.UrbanThemeFactoryBean;
|
||||
import de.extio.game_engine.renderer.g2d.theme.VintageThemeFactoryBean;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
|
||||
@AutoConfiguration
|
||||
@ConditionalOnProperty(name = "game-engine.renderer.enabled", havingValue = "true", matchIfMissing = true)
|
||||
@@ -113,10 +113,11 @@ public class G2DAutoConfiguration {
|
||||
@Bean
|
||||
G2DThemeManager g2dThemeManager(
|
||||
final StaticResourceService staticResourceService,
|
||||
final StorageService storageService,
|
||||
final List<PatternRenderer> patternRendererList,
|
||||
final Map<String, Theme> themes,
|
||||
@Qualifier("spacecraftTheme") final Theme defaultTheme) {
|
||||
return new G2DThemeManager(staticResourceService, patternRendererList, themes, defaultTheme);
|
||||
@Value("${game-engine.renderer.default-theme:urbanTheme}") final String defaultThemeName) {
|
||||
return new G2DThemeManager(staticResourceService, storageService, patternRendererList, themes, defaultThemeName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -11,15 +13,21 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.extio.game_engine.renderer.ThemeManager;
|
||||
import de.extio.game_engine.renderer.g2d.G2DRenderer;
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
|
||||
public class G2DThemeManager implements ThemeManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(G2DThemeManager.class);
|
||||
|
||||
private static final List<String> THEME_STORAGE_PATH = List.of("gameEngine", "themes");
|
||||
private static final String THEME_STORAGE_NAME = "lastTheme";
|
||||
|
||||
private G2DRenderer g2dRenderer;
|
||||
|
||||
private final StaticResourceService staticResourceService;
|
||||
private final StorageService storageService;
|
||||
|
||||
private final Map<String, PatternRenderer> patternRenderers;
|
||||
private final Map<String, Theme> themes;
|
||||
@@ -29,20 +37,48 @@ public class G2DThemeManager implements ThemeManager {
|
||||
|
||||
public G2DThemeManager(
|
||||
final StaticResourceService staticResourceService,
|
||||
final StorageService storageService,
|
||||
final List<PatternRenderer> patternRendererList,
|
||||
final Map<String, Theme> themes,
|
||||
final Theme defaultTheme) {
|
||||
final String defaultThemeName) {
|
||||
this.staticResourceService = staticResourceService;
|
||||
this.storageService = storageService;
|
||||
this.patternRenderers = patternRendererList.stream()
|
||||
.collect(Collectors.toMap(
|
||||
renderer -> renderer.getClass().getSimpleName().substring(0, 1).toLowerCase() + renderer.getClass().getSimpleName().substring(1),
|
||||
Function.identity()));
|
||||
this.themes = Objects.requireNonNull(themes, "themes cannot be null");
|
||||
this.defaultTheme = Objects.requireNonNull(defaultTheme, "defaultTheme cannot be null");
|
||||
this.themes = new ConcurrentHashMap<>(Objects.requireNonNull(themes, "themes cannot be null"));
|
||||
this.defaultTheme = Objects.requireNonNull(this.themes.get(defaultThemeName), "defaultTheme cannot be null");
|
||||
|
||||
LOGGER.info("G2DThemeManager initialized with {} pattern renderers: {}", this.patternRenderers.size(), this.patternRenderers.keySet());
|
||||
LOGGER.info("G2DThemeManager initialized with {} themes: {}", this.themes.size(), this.themes.keySet());
|
||||
this.currentTheme = this.defaultTheme;
|
||||
this.loadLastUsedTheme();
|
||||
}
|
||||
|
||||
private void registerTheme(final Theme theme) {
|
||||
if (theme == null || theme.getName() == null || theme.getName().isBlank()) {
|
||||
return;
|
||||
}
|
||||
this.themes.put(theme.getName(), theme);
|
||||
}
|
||||
|
||||
private void loadLastUsedTheme() {
|
||||
if (this.storageService == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final Optional<Theme> persistedTheme = this.storageService.loadByPath(Theme.class, THEME_STORAGE_PATH, THEME_STORAGE_NAME);
|
||||
if (persistedTheme.isPresent()) {
|
||||
this.currentTheme = persistedTheme.get();
|
||||
this.registerTheme(this.currentTheme);
|
||||
LOGGER.info("Loaded last used theme: {}", this.currentTheme.getName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
LOGGER.warn("Could not load last used theme. Using default.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,6 +90,44 @@ public class G2DThemeManager implements ThemeManager {
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Theme> loadThemeFromStorage(final String themeName) {
|
||||
if (themeName == null || themeName.isBlank()) {
|
||||
throw new IllegalArgumentException("themeName cannot be null/blank");
|
||||
}
|
||||
if (this.storageService == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
final Optional<Theme> loaded = this.storageService.loadByPath(Theme.class, THEME_STORAGE_PATH, themeName);
|
||||
loaded.ifPresent(this::registerTheme);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveThemeToStorage(final Theme theme) {
|
||||
if (theme == null) {
|
||||
throw new IllegalArgumentException("theme cannot be null");
|
||||
}
|
||||
if (theme.getName() == null || theme.getName().isBlank()) {
|
||||
throw new IllegalArgumentException("theme.name cannot be null/blank");
|
||||
}
|
||||
if (this.storageService == null) {
|
||||
throw new IllegalStateException("storageService not available");
|
||||
}
|
||||
this.storageService.store(THEME_STORAGE_PATH, theme.getName(), theme);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Theme> loadThemeFromStaticResource(final StaticResource themeResource) {
|
||||
Objects.requireNonNull(themeResource, "themeResource");
|
||||
if (this.staticResourceService == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
final Optional<Theme> loaded = this.staticResourceService.loadByPath(Theme.class, themeResource);
|
||||
loaded.ifPresent(this::registerTheme);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentTheme(final String themeName) {
|
||||
if (themeName == null || themeName.isBlank()) {
|
||||
@@ -94,14 +168,40 @@ public class G2DThemeManager implements ThemeManager {
|
||||
}
|
||||
|
||||
this.currentTheme = theme;
|
||||
this.registerTheme(theme);
|
||||
LOGGER.info("Theme switched to: {}", theme.getName());
|
||||
this.persistLastUsedTheme(theme);
|
||||
|
||||
this.g2dRenderer.reset();
|
||||
if (this.g2dRenderer != null) {
|
||||
this.g2dRenderer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void persistLastUsedTheme(final Theme theme) {
|
||||
if (this.storageService == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.storageService.store(THEME_STORAGE_PATH, THEME_STORAGE_NAME, theme);
|
||||
}
|
||||
catch (final Exception e) {
|
||||
LOGGER.warn("Could not persist last used theme", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Theme loadTheme(final String themeName) {
|
||||
Objects.requireNonNull(this.staticResourceService, "staticResourceService");
|
||||
LOGGER.warn("Theme loading from StaticResourceService not yet implemented. Requested theme: {}. Using default theme.", themeName);
|
||||
try {
|
||||
final Optional<Theme> fromStorage = this.loadThemeFromStorage(themeName);
|
||||
if (fromStorage.isPresent()) {
|
||||
LOGGER.info("Loaded theme '{}' from storage", themeName);
|
||||
return fromStorage.get();
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
LOGGER.warn("Could not load theme '{}' from storage. Using default.", themeName, e);
|
||||
}
|
||||
|
||||
LOGGER.warn("Theme '{}' not found in storage. Using default theme.", themeName);
|
||||
return this.defaultTheme;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ package de.extio.game_engine.renderer.g2d.theme;
|
||||
import java.awt.Color;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Represents a color in HSB (Hue, Saturation, Brightness) color space.
|
||||
* This allows for easier runtime color manipulation (e.g., brightening on hover).
|
||||
@@ -20,7 +23,11 @@ public final class HSBColor {
|
||||
* @param saturation Saturation component (0.0 to 1.0)
|
||||
* @param brightness Brightness component (0.0 to 1.0)
|
||||
*/
|
||||
public HSBColor(final float hue, final float saturation, final float brightness) {
|
||||
@JsonCreator
|
||||
public HSBColor(
|
||||
@JsonProperty("hue") final float hue,
|
||||
@JsonProperty("saturation") final float saturation,
|
||||
@JsonProperty("brightness") final float brightness) {
|
||||
this.hue = clamp(hue);
|
||||
this.saturation = clamp(saturation);
|
||||
this.brightness = clamp(brightness);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Represents a complete UI theme with all color definitions and pattern renderer.
|
||||
* Themes are element-based rather than component-based, allowing consistent styling across different components.
|
||||
@@ -33,21 +36,54 @@ public class Theme {
|
||||
private final float hoverBrightnessAdjustment;
|
||||
private final float pressedBrightnessAdjustment;
|
||||
|
||||
@JsonCreator
|
||||
public Theme(
|
||||
@JsonProperty("name") final String name,
|
||||
@JsonProperty("patternRendererName") final String patternRendererName,
|
||||
@JsonProperty("borderOuter") final HSBColor borderOuter,
|
||||
@JsonProperty("borderInner") final HSBColor borderInner,
|
||||
@JsonProperty("borderInnerDisabled") final HSBColor borderInnerDisabled,
|
||||
@JsonProperty("backgroundNormal") final HSBColor backgroundNormal,
|
||||
@JsonProperty("backgroundSelected") final HSBColor backgroundSelected,
|
||||
@JsonProperty("textNormal") final HSBColor textNormal,
|
||||
@JsonProperty("textDisabled") final HSBColor textDisabled,
|
||||
@JsonProperty("selectionPrimary") final HSBColor selectionPrimary,
|
||||
@JsonProperty("selectionSecondary") final HSBColor selectionSecondary,
|
||||
@JsonProperty("windowBackground") final HSBColor windowBackground,
|
||||
@JsonProperty("hoverBrightnessAdjustment") final float hoverBrightnessAdjustment,
|
||||
@JsonProperty("pressedBrightnessAdjustment") final float pressedBrightnessAdjustment) {
|
||||
this.name = name;
|
||||
this.patternRendererName = patternRendererName;
|
||||
this.borderOuter = borderOuter;
|
||||
this.borderInner = borderInner;
|
||||
this.borderInnerDisabled = borderInnerDisabled;
|
||||
this.backgroundNormal = backgroundNormal;
|
||||
this.backgroundSelected = backgroundSelected;
|
||||
this.textNormal = textNormal;
|
||||
this.textDisabled = textDisabled;
|
||||
this.selectionPrimary = selectionPrimary;
|
||||
this.selectionSecondary = selectionSecondary;
|
||||
this.windowBackground = windowBackground;
|
||||
this.hoverBrightnessAdjustment = hoverBrightnessAdjustment;
|
||||
this.pressedBrightnessAdjustment = pressedBrightnessAdjustment;
|
||||
}
|
||||
|
||||
private Theme(final Builder builder) {
|
||||
this.name = builder.name;
|
||||
this.patternRendererName = builder.patternRendererName;
|
||||
this.borderOuter = builder.borderOuter;
|
||||
this.borderInner = builder.borderInner;
|
||||
this.borderInnerDisabled = builder.borderInnerDisabled;
|
||||
this.backgroundNormal = builder.backgroundNormal;
|
||||
this.backgroundSelected = builder.backgroundSelected;
|
||||
this.textNormal = builder.textNormal;
|
||||
this.textDisabled = builder.textDisabled;
|
||||
this.selectionPrimary = builder.selectionPrimary;
|
||||
this.selectionSecondary = builder.selectionSecondary;
|
||||
this.windowBackground = builder.windowBackground;
|
||||
this.hoverBrightnessAdjustment = builder.hoverBrightnessAdjustment;
|
||||
this.pressedBrightnessAdjustment = builder.pressedBrightnessAdjustment;
|
||||
this(
|
||||
builder.name,
|
||||
builder.patternRendererName,
|
||||
builder.borderOuter,
|
||||
builder.borderInner,
|
||||
builder.borderInnerDisabled,
|
||||
builder.backgroundNormal,
|
||||
builder.backgroundSelected,
|
||||
builder.textNormal,
|
||||
builder.textDisabled,
|
||||
builder.selectionPrimary,
|
||||
builder.selectionSecondary,
|
||||
builder.windowBackground,
|
||||
builder.hoverBrightnessAdjustment,
|
||||
builder.pressedBrightnessAdjustment);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
@@ -26,7 +26,6 @@ import de.extio.game_engine.renderer.model.event.UiControlEvent;
|
||||
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
|
||||
public class DemoModule extends AbstractClientModule {
|
||||
|
||||
@@ -48,9 +47,6 @@ public class DemoModule extends AbstractClientModule {
|
||||
@Autowired
|
||||
private ThemeManager themeManager;
|
||||
|
||||
@Autowired
|
||||
private StorageService storageService;
|
||||
|
||||
private Window mainWindow;
|
||||
|
||||
private Window secondaryWindow;
|
||||
@@ -93,12 +89,6 @@ public class DemoModule extends AbstractClientModule {
|
||||
|
||||
@Override
|
||||
public void onActivate() {
|
||||
this.storageService.loadByPath(String.class, List.of("gameEngine"), "theme").ifPresent(themeName -> {
|
||||
if (themeName != null && !themeName.isBlank()) {
|
||||
this.themeManager.setCurrentTheme(themeName);
|
||||
}
|
||||
});
|
||||
|
||||
final var audioOptions = this.audioController.getAudioOptions();
|
||||
this.audioMuted = isAudioMuted(audioOptions);
|
||||
|
||||
@@ -158,7 +148,6 @@ public class DemoModule extends AbstractClientModule {
|
||||
if (themeName != null) {
|
||||
this.audioController.play(new StaticResource(List.of("audio"), "alert0.ogg"));
|
||||
this.themeManager.setCurrentTheme(themeName);
|
||||
this.storageService.store(List.of("gameEngine"), "theme", themeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
package de.extio.game_engine.renderer.g2d.theme;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
|
||||
public class G2DThemeManagerTest {
|
||||
|
||||
private static Theme theme(final String name) {
|
||||
return Theme.builder()
|
||||
.name(name)
|
||||
.patternRendererName("testPatternRenderer")
|
||||
.borderOuter(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.borderInner(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.borderInnerDisabled(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.backgroundNormal(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.backgroundSelected(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.textNormal(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.textDisabled(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.selectionPrimary(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.selectionSecondary(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.windowBackground(new HSBColor(0.1f, 0.2f, 0.3f))
|
||||
.hoverBrightnessAdjustment(0.25f)
|
||||
.pressedBrightnessAdjustment(0.40f)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadsLastUsedThemeFromStorageOnConstruction() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final Theme persistedTheme = theme("Persisted");
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
.thenReturn(Optional.of(persistedTheme));
|
||||
|
||||
final var manager = new G2DThemeManager(
|
||||
staticResourceService,
|
||||
storageService,
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
|
||||
assertEquals("Persisted", manager.getCurrentTheme().getName());
|
||||
assertTrue(manager.getAvailableThemeNames().contains("Persisted"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setCurrentThemePersistsLastThemeObject() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final var manager = new G2DThemeManager(
|
||||
staticResourceService,
|
||||
storageService,
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
|
||||
final Theme selected = theme("Selected");
|
||||
manager.setCurrentTheme(selected);
|
||||
|
||||
verify(storageService).store(eq(List.of("gameEngine", "themes")), eq("lastTheme"), eq(selected));
|
||||
assertTrue(manager.getAvailableThemeNames().contains("Selected"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadThemeFromStorageRegistersTheme() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final var manager = new G2DThemeManager(
|
||||
staticResourceService,
|
||||
storageService,
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
|
||||
final Theme loaded = theme("FromStorage");
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("FromStorage")))
|
||||
.thenReturn(Optional.of(loaded));
|
||||
|
||||
final Optional<Theme> result = manager.loadThemeFromStorage("FromStorage");
|
||||
assertTrue(result.isPresent());
|
||||
assertEquals("FromStorage", result.get().getName());
|
||||
assertTrue(manager.getAvailableThemeNames().contains("FromStorage"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadThemeFromStaticResourceRegistersTheme() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final var manager = new G2DThemeManager(
|
||||
staticResourceService,
|
||||
storageService,
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
|
||||
final Theme loaded = theme("FromStaticResource");
|
||||
final StaticResource resource = new StaticResource(List.of("themes"), "fromStatic.theme");
|
||||
when(staticResourceService.loadByPath(eq(Theme.class), eq(resource)))
|
||||
.thenReturn(Optional.of(loaded));
|
||||
|
||||
final Optional<Theme> result = manager.loadThemeFromStaticResource(resource);
|
||||
assertTrue(result.isPresent());
|
||||
assertEquals("FromStaticResource", result.get().getName());
|
||||
assertTrue(manager.getAvailableThemeNames().contains("FromStaticResource"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveThemeToStorageUsesThemeNameAsStorageName() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final var manager = new G2DThemeManager(
|
||||
staticResourceService,
|
||||
storageService,
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
|
||||
final Theme themeToSave = theme("UserTheme");
|
||||
manager.saveThemeToStorage(themeToSave);
|
||||
|
||||
verify(storageService).store(eq(List.of("gameEngine", "themes")), eq("UserTheme"), eq(themeToSave));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveThemeToStorageThrowsIfNoStorageService() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final var manager = new G2DThemeManager(
|
||||
staticResourceService,
|
||||
null,
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
|
||||
assertThrows(IllegalStateException.class, () -> manager.saveThemeToStorage(theme("SomeTheme")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadThemeFromStorageReturnsEmptyWhenStorageNotAvailable() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final var manager = new G2DThemeManager(
|
||||
staticResourceService,
|
||||
null,
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
|
||||
final Optional<Theme> loaded = manager.loadThemeFromStorage("Anything");
|
||||
assertFalse(loaded.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadThemeFromStaticResourceReturnsEmptyWhenStaticResourceServiceNotAvailable() {
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final var manager = new G2DThemeManager(
|
||||
null,
|
||||
storageService,
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
|
||||
final Optional<Theme> loaded = manager.loadThemeFromStaticResource(new StaticResource(List.of("themes"), "x"));
|
||||
assertFalse(loaded.isPresent());
|
||||
verify(storageService, never()).store(any(), any(), any());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user