feat(config-core): support save hooks for config screens
This commit is contained in:
parent
a312c86783
commit
c967a36eaa
|
@ -4,6 +4,7 @@ import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
|
|||
import io.gitlab.jfronny.libjf.config.impl.ui.ConfigScreenFactoryDiscovery;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
@Deprecated
|
||||
public interface ConfigScreenFactory<S extends Screen> {
|
||||
static ConfigScreenFactory<?> getInstance() {
|
||||
return ConfigScreenFactoryDiscovery.getConfigured();
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package io.gitlab.jfronny.libjf.config.api.v2.ui;
|
||||
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
|
||||
import io.gitlab.jfronny.libjf.config.impl.ui.ConfigScreenFactoryDiscovery;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
public interface ConfigScreenFactory<S extends Screen, B extends ConfigScreenFactory.Built<S>> {
|
||||
static ConfigScreenFactory<?, ?> getInstance() {
|
||||
return ConfigScreenFactoryDiscovery.getConfigured2();
|
||||
}
|
||||
|
||||
B create(ConfigInstance config, Screen parent);
|
||||
|
||||
int getPriority();
|
||||
|
||||
interface Built<S extends Screen> {
|
||||
S get();
|
||||
|
||||
void onSave(Runnable action);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.ui;
|
||||
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
|
||||
import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
public record ConfigScreenFactory1To2<S extends Screen>(io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory<S> impl) implements ConfigScreenFactory<S, ConfigScreenFactory1To2.Built<S>> {
|
||||
@Override
|
||||
public Built<S> create(ConfigInstance config, Screen parent) {
|
||||
return new Built<>(impl.create(config, parent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return impl.getPriority();
|
||||
}
|
||||
|
||||
public record Built<S extends Screen>(S screen) implements ConfigScreenFactory.Built<S> {
|
||||
@Override
|
||||
public S get() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSave(Runnable action) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.ui;
|
||||
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
public record ConfigScreenFactory2To1<S extends Screen, B extends io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory.Built<S>>(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory<S, B> impl) implements ConfigScreenFactory<S> {
|
||||
@Override
|
||||
public S create(ConfigInstance config, Screen parent) {
|
||||
return impl.create(config, parent).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return impl.getPriority();
|
||||
}
|
||||
}
|
|
@ -4,18 +4,52 @@ import io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory;
|
|||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigScreenFactoryDiscovery {
|
||||
private static ConfigScreenFactory<?> discovered = null;
|
||||
private static ConfigScreenFactory<?> discovered1 = null;
|
||||
private static io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory discovered2 = null;
|
||||
|
||||
@Deprecated
|
||||
public static ConfigScreenFactory<?> getConfigured() {
|
||||
if (discovered == null) {
|
||||
discovered = FabricLoader.getInstance()
|
||||
.getEntrypoints("libjf:config_screen", ConfigScreenFactory.class)
|
||||
if (discovered1 == null) {
|
||||
List<Object> entrypoints = getEntrypoints();
|
||||
discovered1 = entrypoints
|
||||
.stream()
|
||||
.max(Comparator.comparing(ConfigScreenFactory::getPriority))
|
||||
.orElse(new PlaceholderScreenFactory());
|
||||
.filter(it -> it instanceof io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory<?,?>)
|
||||
.map(it -> (io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory) it)
|
||||
.max(Comparator.comparing(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory::getPriority))
|
||||
.<ConfigScreenFactory>map(ConfigScreenFactory2To1::new)
|
||||
.orElseGet(() -> entrypoints
|
||||
.stream()
|
||||
.filter(it -> it instanceof ConfigScreenFactory<?>)
|
||||
.map(it -> (ConfigScreenFactory) it)
|
||||
.max(Comparator.comparing(ConfigScreenFactory::getPriority))
|
||||
.orElseGet(() -> new ConfigScreenFactory2To1(new PlaceholderScreenFactory())));
|
||||
}
|
||||
return discovered;
|
||||
return discovered1;
|
||||
}
|
||||
|
||||
public static io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory<?, ?> getConfigured2() {
|
||||
if (discovered2 == null) {
|
||||
List<Object> entrypoints = getEntrypoints();
|
||||
discovered2 = entrypoints
|
||||
.stream()
|
||||
.filter(it -> it instanceof io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory<?,?>)
|
||||
.map(it -> (io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory) it)
|
||||
.max(Comparator.comparing(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory::getPriority))
|
||||
.orElseGet(() -> entrypoints
|
||||
.stream()
|
||||
.filter(it -> it instanceof ConfigScreenFactory<?>)
|
||||
.map(it -> (ConfigScreenFactory) it)
|
||||
.<io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory>map(ConfigScreenFactory1To2::new)
|
||||
.max(Comparator.comparing(io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory::getPriority))
|
||||
.orElseGet(PlaceholderScreenFactory::new));
|
||||
}
|
||||
return discovered2;
|
||||
}
|
||||
|
||||
private static List<Object> getEntrypoints() {
|
||||
return FabricLoader.getInstance().getEntrypoints("libjf:config_screen", Object.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,6 @@ public class ModMenuAdapter implements ModMenuApi {
|
|||
}
|
||||
|
||||
private static ConfigScreenFactory<?> buildFactory(ConfigInstance config) {
|
||||
return s -> io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory.getInstance().create(config, s);
|
||||
return s -> io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory.getInstance().create(config, s).get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,29 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.ui;
|
||||
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory;
|
||||
import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
public class PlaceholderScreenFactory implements ConfigScreenFactory<PlaceholderScreen> {
|
||||
public class PlaceholderScreenFactory implements ConfigScreenFactory<PlaceholderScreen, PlaceholderScreenFactory.Built> {
|
||||
@Override
|
||||
public PlaceholderScreen create(ConfigInstance config, Screen parent) {
|
||||
return new PlaceholderScreen(parent);
|
||||
public Built create(ConfigInstance config, Screen parent) {
|
||||
return new Built(new PlaceholderScreen(parent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return -100;
|
||||
}
|
||||
|
||||
public record Built(PlaceholderScreen screen) implements ConfigScreenFactory.Built<PlaceholderScreen> {
|
||||
@Override
|
||||
public PlaceholderScreen get() {
|
||||
return screen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSave(Runnable action) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@ import net.minecraft.client.gui.screen.Screen;
|
|||
public interface ConfigScreen {
|
||||
TinyConfigScreenFactory FACTORY = new TinyConfigScreenFactory();
|
||||
static Screen create(ConfigInstance config, Screen parent) {
|
||||
return FACTORY.create(config, parent);
|
||||
return FACTORY.create(config, parent).get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,9 @@ import net.minecraft.client.font.TextHandler;
|
|||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
||||
import net.minecraft.client.gui.screen.option.OptionsScreen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.OptionListWidget;
|
||||
import net.minecraft.client.util.NarratorManager;
|
||||
import net.minecraft.client.util.SelectionManager;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Rect2i;
|
||||
import net.minecraft.screen.ScreenTexts;
|
||||
import net.minecraft.text.*;
|
||||
|
@ -31,7 +27,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EditorScreen extends Screen {
|
||||
public class EditorScreen extends ScreenWithSaveHook {
|
||||
private static final int SCROLLBAR_SIZE = 7;
|
||||
private static final int HEADER_SIZE = 32;
|
||||
private static final int FOOTER_SIZE = 36;
|
||||
|
@ -134,7 +130,10 @@ public class EditorScreen extends Screen {
|
|||
}
|
||||
|
||||
private void quit(boolean save) {
|
||||
if (save && (this.initialText == null || !this.initialText.equals(this.text))) onSave.accept(text);
|
||||
if (save && (this.initialText == null || !this.initialText.equals(this.text))) {
|
||||
onSave.accept(text);
|
||||
saveHook.run();
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.ui.tiny;
|
||||
|
||||
import io.gitlab.jfronny.commons.ref.R;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public abstract class ScreenWithSaveHook extends Screen {
|
||||
public Runnable saveHook = R::nop;
|
||||
|
||||
protected ScreenWithSaveHook(Text title) {
|
||||
super(title);
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ import net.minecraft.util.math.MathHelper;
|
|||
import java.util.*;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class TinyConfigScreen extends Screen {
|
||||
public class TinyConfigScreen extends ScreenWithSaveHook {
|
||||
public static Text getTitle(String categoryPath) {
|
||||
final String titlePath = categoryPath + "title";
|
||||
if (JfConfigSafe.TRANSLATION_SUPPLIER.apply(titlePath) != null) {
|
||||
|
@ -79,6 +79,7 @@ public class TinyConfigScreen extends Screen {
|
|||
}
|
||||
config.getRoot().write();
|
||||
Objects.requireNonNull(client).setScreen(parent);
|
||||
saveHook.run();
|
||||
})
|
||||
.dimensions(this.width / 2 + 4, this.height - 28, 150, 20)
|
||||
.build();
|
||||
|
|
|
@ -6,7 +6,7 @@ import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
|
|||
import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.type.Type;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ui.ConfigScreenFactory;
|
||||
import io.gitlab.jfronny.libjf.config.api.v2.ui.ConfigScreenFactory;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
|
@ -14,9 +14,9 @@ import net.minecraft.client.toast.SystemToast;
|
|||
import net.minecraft.text.Text;
|
||||
|
||||
// IDEA doesn't like this, but it does work in practice
|
||||
public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen> {
|
||||
public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen, TinyConfigScreenFactory.Built> {
|
||||
@Override
|
||||
public Screen create(ConfigInstance config, Screen parent) {
|
||||
public Built create(ConfigInstance config, Screen parent) {
|
||||
if (config.getEntries().size() == 1
|
||||
&& config.getPresets().keySet().stream().allMatch(s -> s.equals(CategoryBuilder.CONFIG_PRESET_DEFAULT))
|
||||
&& config.getReferencedConfigs().isEmpty()
|
||||
|
@ -31,7 +31,7 @@ public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen> {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
String key = config.getTranslationPrefix() + entry.getName();
|
||||
return new EditorScreen(
|
||||
return new Built(new EditorScreen(
|
||||
Text.translatable(key),
|
||||
I18n.hasTranslation(key + ".tooltip") ? Text.translatable(key + ".tooltip") : null,
|
||||
parent,
|
||||
|
@ -50,14 +50,28 @@ public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen> {
|
|||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
return new TinyConfigScreen(config, parent);
|
||||
return new Built(new TinyConfigScreen(config, parent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public record Built(ScreenWithSaveHook screen) implements ConfigScreenFactory.Built<Screen> {
|
||||
public Screen get() {
|
||||
return screen;
|
||||
}
|
||||
|
||||
public void onSave(Runnable action) {
|
||||
Runnable currentHook = screen.saveHook;
|
||||
screen.saveHook = () -> {
|
||||
currentHook.run();
|
||||
action.run();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue