Skip to content

Commit

Permalink
Theme improvements (#15)
Browse files Browse the repository at this point in the history
(cherry picked from commit ee9d2fd)
  • Loading branch information
miozune committed Jun 23, 2023
1 parent 58203bd commit 03a7ac1
Show file tree
Hide file tree
Showing 12 changed files with 515 additions and 175 deletions.
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 cpw.mods.fml.relauncher.Side;
import cpw.mods.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 @@ -387,7 +387,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.IDraggable;
import com.cleanroommc.modularui.api.widget.IFocusedWidget;
Expand All @@ -13,7 +14,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 cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
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 @@ -510,7 +510,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 cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
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

0 comments on commit 03a7ac1

Please sign in to comment.