From f97464fdc758ba1a51b8f23b89b50bf4403fe467 Mon Sep 17 00:00:00 2001 From: JFronny Date: Sun, 28 Aug 2022 18:48:39 +0200 Subject: [PATCH] [config] Display sliders when min and max are set --- .../config/api/v1/dsl/CategoryBuilder.java | 2 + .../config/impl/dsl/CategoryBuilderImpl.java | 15 +++--- .../libjf/config/test/reflect/TestConfig.java | 3 +- .../libjf-config-v0-testmod/lang/en_us.json | 22 ++++---- .../src/testmod/resources/fabric.mod.json | 2 +- .../impl/ui/tiny/entry/CustomSlider.java | 54 +++++++++++++++++++ .../ui/tiny/entry/EntryInfoWidgetBuilder.java | 47 +++++++++++++--- 7 files changed, 120 insertions(+), 25 deletions(-) create mode 100644 libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/CategoryBuilder.java b/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/CategoryBuilder.java index e652779..5d681af 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/CategoryBuilder.java +++ b/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/api/v1/dsl/CategoryBuilder.java @@ -3,6 +3,7 @@ package io.gitlab.jfronny.libjf.config.api.v1.dsl; import io.gitlab.jfronny.libjf.config.api.v1.*; import io.gitlab.jfronny.libjf.config.api.v1.type.Type; +import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; @@ -19,6 +20,7 @@ public interface CategoryBuilder> { Builder addVerifier(Runnable verifier); Builder referenceConfig(String id); Builder referenceConfig(ConfigInstance config); + Builder referenceConfig(Supplier> gen); Builder category(String id, CategoryBuilderFunction builder); Builder value(String id, int def, double min, double max, Supplier get, Consumer set); Builder value(String id, long def, double min, double max, Supplier get, Consumer set); diff --git a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java b/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java index 2dfc2a5..dadc0ba 100644 --- a/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java +++ b/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/CategoryBuilderImpl.java @@ -16,7 +16,7 @@ public class CategoryBuilderImpl> i public String translationPrefix; public final List> entries = new LinkedList<>(); public final Map> presets = new LinkedHashMap<>(); - public final List> referencedConfigs = new LinkedList<>(); + public final List>> referencedConfigs = new LinkedList<>(); public final List> verifiers = new LinkedList<>(); private boolean built = false; @@ -65,15 +65,18 @@ public class CategoryBuilderImpl> i @Override public Builder referenceConfig(String id) { - checkBuilt(); - referencedConfigs.add(() -> ConfigHolder.getInstance().get(id)); - return asBuilder(); + return referenceConfig(() -> List.of(ConfigHolder.getInstance().get(id))); } @Override public Builder referenceConfig(ConfigInstance config) { + return referenceConfig(() -> List.of(config)); + } + + @Override + public Builder referenceConfig(Supplier> gen) { checkBuilt(); - referencedConfigs.add(() -> config); + referencedConfigs.add(Objects.requireNonNull(gen)); return asBuilder(); } @@ -181,7 +184,7 @@ public class CategoryBuilderImpl> i translationPrefix, entries, presets, - () -> referencedConfigs.stream().map(Supplier::get).toList(), + () -> referencedConfigs.stream().map(Supplier::get).mapMulti(Iterable::forEach).toList(), categories.stream().collect(Collectors.toMap(CategoryBuilder::getId, b -> b.build(root))), root, verifiers); diff --git a/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfig.java b/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfig.java index 8e3955e..d1255da 100644 --- a/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfig.java +++ b/libjf-config-reflect-v1/src/testmod/java/io/gitlab/jfronny/libjf/config/test/reflect/TestConfig.java @@ -12,8 +12,9 @@ public class TestConfig { public static boolean disablePacks = false; @Entry public static Boolean disablePacks2 = false; @Entry public static int intTest = 20; + @Entry(min = -5, max = 12) public static int intTestB = 20; @Entry(min = -6) public static float floatTest = -5; - @Entry(max = 21) public static double doubleTest = 20; + @Entry(min = 2, max = 21) public static double doubleTest = 20; @Entry public static String dieStr = "lolz"; @Entry @Ignore public static String guiOnlyStr = "lolz"; diff --git a/libjf-config-reflect-v1/src/testmod/resources/assets/libjf-config-v0-testmod/lang/en_us.json b/libjf-config-reflect-v1/src/testmod/resources/assets/libjf-config-v0-testmod/lang/en_us.json index 5214aff..65ed715 100644 --- a/libjf-config-reflect-v1/src/testmod/resources/assets/libjf-config-v0-testmod/lang/en_us.json +++ b/libjf-config-reflect-v1/src/testmod/resources/assets/libjf-config-v0-testmod/lang/en_us.json @@ -1,13 +1,13 @@ { - "libjf-config-reflect-v0-testmod.jfconfig.title": "JfConfig example", - "libjf-config-reflect-v0-testmod.jfconfig.disablePacks": "Disable resource packs", - "libjf-config-reflect-v0-testmod.jfconfig.intTest": "Int Test", - "libjf-config-reflect-v0-testmod.jfconfig.decimalTest": "Decimal Test", - "libjf-config-reflect-v0-testmod.jfconfig.dieStr": "String Test", - "libjf-config-reflect-v0-testmod.jfconfig.gsonOnlyStr.tooltip": "George", - "libjf-config-reflect-v0-testmod.jfconfig.enumTest": "Enum Test", - "libjf-config-reflect-v0-testmod.jfconfig.enumTest.tooltip": "Enum Test Tooltip", - "libjf-config-reflect-v0-testmod.jfconfig.enum.Test.Test": "Test", - "libjf-config-reflect-v0-testmod.jfconfig.enum.Test.ER": "ER", - "libjf-config-reflect-v0-testmod.jfconfig.moskau": "Moskau" + "libjf-config-reflect-v1-testmod.jfconfig.title": "JfConfig example", + "libjf-config-reflect-v1-testmod.jfconfig.disablePacks": "Disable resource packs", + "libjf-config-reflect-v1-testmod.jfconfig.intTest": "Int Test", + "libjf-config-reflect-v1-testmod.jfconfig.decimalTest": "Decimal Test", + "libjf-config-reflect-v1-testmod.jfconfig.dieStr": "String Test", + "libjf-config-reflect-v1-testmod.jfconfig.gsonOnlyStr.tooltip": "George", + "libjf-config-reflect-v1-testmod.jfconfig.enumTest": "Enum Test", + "libjf-config-reflect-v1-testmod.jfconfig.enumTest.tooltip": "Enum Test Tooltip", + "libjf-config-reflect-v1-testmod.jfconfig.enum.Test.Test": "Test", + "libjf-config-reflect-v1-testmod.jfconfig.enum.Test.ER": "ER", + "libjf-config-reflect-v1-testmod.jfconfig.moskau": "Moskau" } \ No newline at end of file diff --git a/libjf-config-reflect-v1/src/testmod/resources/fabric.mod.json b/libjf-config-reflect-v1/src/testmod/resources/fabric.mod.json index 78a8241..1b8af90 100644 --- a/libjf-config-reflect-v1/src/testmod/resources/fabric.mod.json +++ b/libjf-config-reflect-v1/src/testmod/resources/fabric.mod.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "id": "libjf-config-reflect-v0-testmod", + "id": "libjf-config-reflect-v1-testmod", "version": "1.0", "environment": "*", "entrypoints": { diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java new file mode 100644 index 0000000..b239f75 --- /dev/null +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/CustomSlider.java @@ -0,0 +1,54 @@ +package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry; + +import net.minecraft.client.gui.widget.SliderWidget; +import net.minecraft.text.Text; + +import java.util.Objects; +import java.util.function.Consumer; + +public class CustomSlider extends SliderWidget { + private final double min; + private final double max; + private final Consumer onChange; + private final boolean wholeNumber; + + public CustomSlider(int x, int y, int width, int height, double value, double min, double max, Consumer onChange, boolean wholeNumber) { + super(x, y, width, height, toText(value), rangeToSlider(value, min, max)); + this.min = min; + this.max = max; + this.onChange = onChange; + this.wholeNumber = wholeNumber; + } + + @Override + protected void updateMessage() { + setMessage(toText(getValue())); + } + + @Override + protected void applyValue() { + onChange.accept(getValue()); + } + + public double getValue() { + double result = sliderToRange(value, min, max); + if (wholeNumber) result = Math.floor(result + 0.5); + return result; + } + + public void setValue(double value) { + this.value = rangeToSlider(value, min, max); + } + + private static double sliderToRange(double value, double min, double max) { + return value * (max - min) + min; + } + + private static double rangeToSlider(double value, double min, double max) { + return (value - min) / (max - min); + } + + private static Text toText(double value) { + return Text.literal(Objects.toString(value)); + } +} diff --git a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java index 5eb85f1..09182be 100644 --- a/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java +++ b/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/entry/EntryInfoWidgetBuilder.java @@ -37,12 +37,25 @@ public class EntryInfoWidgetBuilder { WidgetState state = new WidgetState<>(); WidgetFactory factory; - if (type.isInt()) factory = textField(info, state, INTEGER_ONLY, Integer::parseInt, true, info.getMinValue(), info.getMaxValue()); - else if (type.isLong()) factory = textField(info, state, INTEGER_ONLY, Long::parseLong, true, info.getMinValue(), info.getMaxValue()); - else if (type.isFloat()) factory = textField(info, state, DECIMAL_ONLY, Float::parseFloat, false, info.getMinValue(), info.getMaxValue()); - else if (type.isDouble()) factory = textField(info, state, DECIMAL_ONLY, Double::parseDouble, false, info.getMinValue(), info.getMaxValue()); - else if (type.isString()) factory = textField(info, state, null, String::length, true, Math.min(info.getMinValue(),0), Math.max(info.getMaxValue(),1)); - else if (type.isBool()) { + if (type.isInt()) { + factory = isDiscrete(info) + ? slider(info, state, t -> (double)(int)t, Double::intValue, true) + : textField(info, state, INTEGER_ONLY, Integer::parseInt, true, info.getMinValue(), info.getMaxValue()); + } else if (type.isLong()) { + factory = isDiscrete(info) + ? slider(info, state, t -> (double)(long)t, Double::longValue, true) + : textField(info, state, INTEGER_ONLY, Long::parseLong, true, info.getMinValue(), info.getMaxValue()); + } else if (type.isFloat()) { + factory = isDiscrete(info) + ? slider(info, state, t -> (double)(float)t, Double::floatValue, false) + : textField(info, state, DECIMAL_ONLY, Float::parseFloat, false, info.getMinValue(), info.getMaxValue()); + } else if (type.isDouble()) { + factory = isDiscrete(info) + ? slider(info, state, t -> t, t -> t, false) + : textField(info, state, DECIMAL_ONLY, Double::parseDouble, false, info.getMinValue(), info.getMaxValue()); + } else if (type.isString()) { + factory = textField(info, state, null, String::length, true, Math.min(info.getMinValue(), 0), Math.max(info.getMaxValue(), 1)); + } else if (type.isBool()) { factory = toggle(info, state, value -> !(Boolean) value, value -> Text.literal((Boolean) value ? "True" : "False").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED)); @@ -129,4 +142,26 @@ public class EntryInfoWidgetBuilder { return new WidgetFactory.Widget(() -> widget.setText(state.cachedValue == null ? "" : state.cachedValue.toString()), widget); }; } + + private static WidgetFactory slider(EntryInfo info, WidgetState state, Function t2d, Function d2t, boolean wholeNumber) { + double min = info.getMinValue(); + double max = info.getMaxValue(); + if (!isDiscrete(min)) throw new IllegalArgumentException("Attempted to create slider with indiscrete minimum"); + if (!isDiscrete(max)) throw new IllegalArgumentException("Attempted to create slider with indiscrete maximum"); + return (width, textRenderer, done) -> { + CustomSlider slider = new CustomSlider(width - 110, 0, info.getWidth(), 20, Double.parseDouble(state.tempValue), min, max, v -> { + state.updateCache(d2t.apply(v)); + }, wholeNumber); + + return new WidgetFactory.Widget(() -> slider.setValue(t2d.apply((T) state.cachedValue)), slider); + }; + } + + private static boolean isDiscrete(EntryInfo info) { + return isDiscrete(info.getMinValue()) && isDiscrete(info.getMaxValue()); + } + + private static boolean isDiscrete(double number) { + return !Double.isNaN(number) && Double.isFinite(number); + } }