Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Theme improvements #15

Merged
merged 4 commits into from
May 17, 2023
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
41 changes: 5 additions & 36 deletions src/main/java/com/cleanroommc/modularui/api/ITheme.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.cleanroommc.modularui.api;

import com.cleanroommc.modularui.theme.*;
import com.cleanroommc.modularui.theme.WidgetSlotTheme;
import com.cleanroommc.modularui.theme.WidgetTextFieldTheme;
import com.cleanroommc.modularui.theme.WidgetTheme;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

Expand All @@ -14,47 +16,15 @@ public interface ITheme {
* @return the master default theme.
*/
static ITheme getDefault() {
return Theme.DEFAULT_DEFAULT;
return IThemeApi.get().getDefaultTheme();
}

/**
* @param id theme id
* @return theme with given id
*/
static ITheme get(String id) {
return ThemeManager.get(id);
}

/**
* If you have a custom widget type and want a custom theme for the type you can register a parser here.
*
* @param id the id of the widget theme. This how json finds this parser.
* @param defaultTheme this will be used for {@link Theme#DEFAULT_DEFAULT}.
* @param function a function that creates an instance of the widget theme with the parent theme and a json.
*/
static void registerWidgetTheme(String id, WidgetTheme defaultTheme, WidgetThemeParser function) {
ThemeManager.registerWidgetTheme(id, defaultTheme, function);
}

/**
* Register a default theme for a screen id. Can also just be the mod from many screens.
*
* @param screenId screen id or mod.
* @param theme theme
*/
static void registerDefaultScreenTheme(String screenId, ITheme theme) {
ThemeManager.registerDefaultTheme(screenId, theme.getId());
}

/**
* Register a default theme for a screen id.
*
* @param mod mod id of screen
* @param id screen id without mod
* @param theme theme
*/
static void registerDefaultScreenTheme(String mod, String id, ITheme theme) {
ThemeManager.registerDefaultTheme(mod + ":" + id, theme.getId());
return IThemeApi.get().getTheme(id);
}

String getId();
Expand All @@ -74,5 +44,4 @@ static void registerDefaultScreenTheme(String mod, String id, ITheme theme) {
WidgetTextFieldTheme getTextFieldTheme();

WidgetTheme getWidgetTheme(String id);

}
109 changes: 109 additions & 0 deletions src/main/java/com/cleanroommc/modularui/api/IThemeApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.cleanroommc.modularui.api;

import com.cleanroommc.modularui.screen.ModularScreen;
import com.cleanroommc.modularui.theme.ThemeAPI;
import com.cleanroommc.modularui.theme.WidgetTheme;
import com.cleanroommc.modularui.theme.WidgetThemeParser;
import com.cleanroommc.modularui.utils.JsonBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
* An API interface for Themes.
*/
public interface IThemeApi {

/**
* @return the default api implementation
*/
static IThemeApi get() {
return ThemeAPI.INSTANCE;
}

/**
* @return the absolute fallback theme
*/
ITheme getDefaultTheme();

/**
* Finds a theme for an id
*
* @param id id of the theme
* @return the found theme or {@link #getDefaultTheme()} if no theme was found
*/
@NotNull
ITheme getTheme(String id);

/**
* @param id id of the theme
* @return if a theme with the id is registered
*/
boolean hasTheme(String id);

/**
* Registers a theme json object. Themes from resource packs always have greater priority.
*
* @param id id of the theme
* @param json theme data
*/
void registerTheme(String id, JsonBuilder json);

/**
* Gets all currently from java side registered theme json's for a theme.
*
* @param id id of the theme
* @return all theme json's for a theme.
*/
List<JsonBuilder> getJavaDefaultThemes(String id);

/**
* Gets the appropriate theme for a screen.
*
* @param owner owner of the screen
* @param name name of the screen
* @param defaultTheme default theme if no theme was found
* @return the registered theme for the given screen or the given default theme or {@link #getDefaultTheme()}
*/
ITheme getThemeForScreen(String owner, String name, @Nullable String defaultTheme);

/**
* Gets the appropriate theme for a screen.
*
* @param screen screen
* @param defaultTheme default theme if no theme was found
* @return the registered theme for the given screen or the given default theme or {@link #getDefaultTheme()}
*/
default ITheme getThemeForScreen(ModularScreen screen, @Nullable String defaultTheme) {
return getThemeForScreen(screen.getOwner(), screen.getName(), defaultTheme);
}

/**
* Registers a theme for a screen. Themes from resource packs always have greater priority.
*
* @param owner owner of the screen
* @param name name of the screen
* @param theme theme to register
*/
default void registerThemeForScreen(String owner, String name, String theme) {
registerThemeForScreen(owner + ":" + name, theme);
}

/**
* Registers a theme for a screen. Themes from resource packs always have greater priority.
*
* @param screen full screen id
* @param theme theme to register
*/
void registerThemeForScreen(String screen, String theme);

/**
* Register a widget theme.
*
* @param id id of the widget theme
* @param defaultTheme the fallback widget theme
* @param parser the widget theme json parser function
*/
void registerWidgetTheme(String id, WidgetTheme defaultTheme, WidgetThemeParser parser);
}
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ public void registerItemSlot(ItemSlotSH syncHandler) {
}

public boolean isClientOnly() {
return getSyncHandler() == null;
return getContainer().isClientOnly();
}

public ModularContainer getContainer() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.cleanroommc.modularui.ModularUI;
import com.cleanroommc.modularui.api.ITheme;
import com.cleanroommc.modularui.api.IThemeApi;
import com.cleanroommc.modularui.api.layout.IViewport;
import com.cleanroommc.modularui.api.widget.*;
import com.cleanroommc.modularui.core.mixin.GuiContainerAccessor;
Expand All @@ -11,7 +12,6 @@
import com.cleanroommc.modularui.screen.ModularPanel;
import com.cleanroommc.modularui.screen.ModularScreen;
import com.cleanroommc.modularui.screen.WindowManager;
import com.cleanroommc.modularui.theme.ThemeManager;
import com.cleanroommc.modularui.widget.sizer.GuiAxis;
import mezz.jei.api.gui.IGhostIngredientHandler;
import net.minecraft.client.Minecraft;
Expand Down Expand Up @@ -79,7 +79,7 @@ public GuiContext(ModularScreen screen) {
this.mc = ModularUI.getMC();
this.font = this.mc.fontRenderer;
if (this.currentTheme == null) {
this.currentTheme = ThemeManager.getThemeFor(screen.getOwner(), screen.getName(), null);
this.currentTheme = IThemeApi.get().getThemeForScreen(screen, null);
}
}

Expand Down Expand Up @@ -531,7 +531,7 @@ public ITheme getTheme() {
}

public void useTheme(String theme) {
this.currentTheme = ThemeManager.getThemeFor(this.screen.getOwner(), this.screen.getName(), theme);
this.currentTheme = IThemeApi.get().getThemeForScreen(this.screen, theme);
}

private static class HoveredIterable implements Iterable<IGuiElement> {
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/com/cleanroommc/modularui/theme/Theme.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.cleanroommc.modularui.theme;

import com.cleanroommc.modularui.api.ITheme;
import com.cleanroommc.modularui.api.IThemeApi;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
Expand All @@ -10,8 +11,6 @@
@SideOnly(Side.CLIENT)
public class Theme implements ITheme {

public static final ITheme DEFAULT_DEFAULT = new ThemeManager.DefaultTheme();

public static final String FALLBACK = "default";
public static final String PANEL = "panel";
public static final String BUTTON = "button";
Expand Down Expand Up @@ -40,11 +39,11 @@ public class Theme implements ITheme {
this.widgetThemes.put(entry.getKey(), entry.getValue());
}
}
} else if (parent == DEFAULT_DEFAULT) {
} else if (parent == IThemeApi.get().getDefaultTheme()) {
if (!this.widgetThemes.containsKey(FALLBACK)) {
this.widgetThemes.put(FALLBACK, ThemeManager.defaultdefaultWidgetTheme);
}
for (Map.Entry<String, WidgetTheme> entry : ThemeManager.defaultWidgetThemes.entrySet()) {
for (Map.Entry<String, WidgetTheme> entry : ThemeAPI.INSTANCE.defaultWidgetThemes.entrySet()) {
if (!this.widgetThemes.containsKey(entry.getKey())) {
this.widgetThemes.put(entry.getKey(), entry.getValue());
}
Expand Down
138 changes: 138 additions & 0 deletions src/main/java/com/cleanroommc/modularui/theme/ThemeAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.cleanroommc.modularui.theme;

import com.cleanroommc.modularui.ModularUIConfig;
import com.cleanroommc.modularui.api.ITheme;
import com.cleanroommc.modularui.api.IThemeApi;
import com.cleanroommc.modularui.drawable.GuiTextures;
import com.cleanroommc.modularui.utils.Color;
import com.cleanroommc.modularui.utils.JsonBuilder;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class ThemeAPI implements IThemeApi {

public static final ThemeAPI INSTANCE = new ThemeAPI();
public static final String DEFAULT = "DEFAULT";
public static final ITheme DEFAULT_DEFAULT = new DefaultTheme(INSTANCE);

private final Map<String, ITheme> THEMES = new Object2ObjectOpenHashMap<>();
private final Map<String, List<JsonBuilder>> defaultThemes = new Object2ObjectOpenHashMap<>();
protected final Map<String, WidgetTheme> defaultWidgetThemes = new Object2ObjectOpenHashMap<>();
protected final Map<String, WidgetThemeParser> widgetThemeFunctions = new Object2ObjectOpenHashMap<>();
protected final Map<String, String> jsonScreenThemes = new Object2ObjectOpenHashMap<>();
private final Map<String, String> screenThemes = new Object2ObjectOpenHashMap<>();

private ThemeAPI() {
registerWidgetTheme(Theme.PANEL, new WidgetTheme(GuiTextures.BACKGROUND, null, Color.WHITE.normal, 0xFF404040, false), (parent, json, fallback) -> new WidgetTheme(parent, fallback, json));
registerWidgetTheme(Theme.BUTTON, new WidgetTheme(GuiTextures.BUTTON, null, Color.WHITE.normal, Color.WHITE.normal, true), (parent, json, fallback) -> new WidgetTheme(parent, fallback, json));
registerWidgetTheme(Theme.ITEM_SLOT, new WidgetSlotTheme(GuiTextures.SLOT, Color.withAlpha(Color.WHITE.normal, 0x80)), (parent, json, fallback) -> new WidgetSlotTheme(parent, fallback, json));
registerWidgetTheme(Theme.FLUID_SLOT, new WidgetSlotTheme(GuiTextures.SLOT_DARK, Color.withAlpha(Color.WHITE.normal, 0x80)), (parent, json, fallback) -> new WidgetSlotTheme(parent, fallback, json));
registerWidgetTheme(Theme.TEXT_FIELD, new WidgetTextFieldTheme(0xFF2F72A8), (parent, json, fallback) -> new WidgetTextFieldTheme(parent, fallback, json));
}

@Override
public ITheme getDefaultTheme() {
return DEFAULT_DEFAULT;
}

@Override
public @NotNull ITheme getTheme(String id) {
return THEMES.getOrDefault(id, getDefaultTheme());
}

@Override
public boolean hasTheme(String id) {
return THEMES.containsKey(id);
}

@Override
public void registerTheme(String id, JsonBuilder json) {
getJavaDefaultThemes(id).add(json);
}

@Override
public List<JsonBuilder> getJavaDefaultThemes(String id) {
return defaultThemes.computeIfAbsent(id, key -> new ArrayList<>());
}

@Override
public ITheme getThemeForScreen(String owner, String name, @Nullable String defaultTheme) {
String theme = getThemeIdForScreen(owner, name);
if (theme != null) return getTheme(theme);
if (defaultTheme != null) return getTheme(defaultTheme);
return getTheme(ModularUIConfig.useDarkThemeByDefault ? "vanilla_dark" : "vanilla");
}

private String getThemeIdForScreen(String mod, String name) {
String theme = jsonScreenThemes.get(mod + ":" + name);
if (theme != null) return theme;
theme = jsonScreenThemes.get(mod);
if (theme != null) return theme;
theme = screenThemes.get(mod + ":" + name);
return theme;
}

@Override
public void registerThemeForScreen(String screen, String theme) {
Objects.requireNonNull(screen);
Objects.requireNonNull(theme);
screenThemes.put(screen, theme);
}

@Override
public void registerWidgetTheme(String id, WidgetTheme defaultTheme, WidgetThemeParser parser) {
if (widgetThemeFunctions.containsKey(id)) {
throw new IllegalStateException();
}
widgetThemeFunctions.put(id, parser);
defaultWidgetThemes.put(id, defaultTheme);
}

// Internals

@ApiStatus.Internal
void registerTheme(ITheme theme) {
if (THEMES.containsKey(theme.getId())) {
throw new IllegalArgumentException("Theme with id " + theme.getId() + " already exists!");
}
THEMES.put(theme.getId(), theme);
}

@ApiStatus.Internal
void onReload() {
THEMES.clear();
jsonScreenThemes.clear();
registerTheme(DEFAULT_DEFAULT);
}

public static class DefaultTheme extends AbstractDefaultTheme {

private final ThemeAPI api;

private DefaultTheme(ThemeAPI api) {
this.api = api;
}

@Override
public String getId() {
return DEFAULT;
}

@Override
public WidgetTheme getFallback() {
return ThemeManager.defaultdefaultWidgetTheme;
}

@Override
public WidgetTheme getWidgetTheme(String id) {
return this.api.defaultWidgetThemes.get(id);
}
}
}
Loading