[config] Display sliders when min and max are set

This commit is contained in:
Johannes Frohnmeyer 2022-08-28 18:48:39 +02:00
parent 51ef02c767
commit f97464fdc7
Signed by: Johannes
GPG Key ID: E76429612C2929F4
7 changed files with 120 additions and 25 deletions

View File

@ -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.*;
import io.gitlab.jfronny.libjf.config.api.v1.type.Type; import io.gitlab.jfronny.libjf.config.api.v1.type.Type;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -19,6 +20,7 @@ public interface CategoryBuilder<Builder extends CategoryBuilder<Builder>> {
Builder addVerifier(Runnable verifier); Builder addVerifier(Runnable verifier);
Builder referenceConfig(String id); Builder referenceConfig(String id);
Builder referenceConfig(ConfigInstance config); Builder referenceConfig(ConfigInstance config);
Builder referenceConfig(Supplier<List<ConfigInstance>> gen);
Builder category(String id, CategoryBuilderFunction builder); Builder category(String id, CategoryBuilderFunction builder);
Builder value(String id, int def, double min, double max, Supplier<Integer> get, Consumer<Integer> set); Builder value(String id, int def, double min, double max, Supplier<Integer> get, Consumer<Integer> set);
Builder value(String id, long def, double min, double max, Supplier<Long> get, Consumer<Long> set); Builder value(String id, long def, double min, double max, Supplier<Long> get, Consumer<Long> set);

View File

@ -16,7 +16,7 @@ public class CategoryBuilderImpl<Builder extends CategoryBuilderImpl<Builder>> i
public String translationPrefix; public String translationPrefix;
public final List<EntryInfo<?>> entries = new LinkedList<>(); public final List<EntryInfo<?>> entries = new LinkedList<>();
public final Map<String, Consumer<ConfigCategory>> presets = new LinkedHashMap<>(); public final Map<String, Consumer<ConfigCategory>> presets = new LinkedHashMap<>();
public final List<Supplier<ConfigInstance>> referencedConfigs = new LinkedList<>(); public final List<Supplier<List<ConfigInstance>>> referencedConfigs = new LinkedList<>();
public final List<Consumer<ConfigCategory>> verifiers = new LinkedList<>(); public final List<Consumer<ConfigCategory>> verifiers = new LinkedList<>();
private boolean built = false; private boolean built = false;
@ -65,15 +65,18 @@ public class CategoryBuilderImpl<Builder extends CategoryBuilderImpl<Builder>> i
@Override @Override
public Builder referenceConfig(String id) { public Builder referenceConfig(String id) {
checkBuilt(); return referenceConfig(() -> List.of(ConfigHolder.getInstance().get(id)));
referencedConfigs.add(() -> ConfigHolder.getInstance().get(id));
return asBuilder();
} }
@Override @Override
public Builder referenceConfig(ConfigInstance config) { public Builder referenceConfig(ConfigInstance config) {
return referenceConfig(() -> List.of(config));
}
@Override
public Builder referenceConfig(Supplier<List<ConfigInstance>> gen) {
checkBuilt(); checkBuilt();
referencedConfigs.add(() -> config); referencedConfigs.add(Objects.requireNonNull(gen));
return asBuilder(); return asBuilder();
} }
@ -181,7 +184,7 @@ public class CategoryBuilderImpl<Builder extends CategoryBuilderImpl<Builder>> i
translationPrefix, translationPrefix,
entries, entries,
presets, presets,
() -> referencedConfigs.stream().map(Supplier::get).toList(), () -> referencedConfigs.stream().map(Supplier::get).<ConfigInstance>mapMulti(Iterable::forEach).toList(),
categories.stream().collect(Collectors.toMap(CategoryBuilder::getId, b -> b.build(root))), categories.stream().collect(Collectors.toMap(CategoryBuilder::getId, b -> b.build(root))),
root, root,
verifiers); verifiers);

View File

@ -12,8 +12,9 @@ public class TestConfig {
public static boolean disablePacks = false; public static boolean disablePacks = false;
@Entry public static Boolean disablePacks2 = false; @Entry public static Boolean disablePacks2 = false;
@Entry public static int intTest = 20; @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(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 public static String dieStr = "lolz";
@Entry @Ignore @Entry @Ignore
public static String guiOnlyStr = "lolz"; public static String guiOnlyStr = "lolz";

View File

@ -1,13 +1,13 @@
{ {
"libjf-config-reflect-v0-testmod.jfconfig.title": "JfConfig example", "libjf-config-reflect-v1-testmod.jfconfig.title": "JfConfig example",
"libjf-config-reflect-v0-testmod.jfconfig.disablePacks": "Disable resource packs", "libjf-config-reflect-v1-testmod.jfconfig.disablePacks": "Disable resource packs",
"libjf-config-reflect-v0-testmod.jfconfig.intTest": "Int Test", "libjf-config-reflect-v1-testmod.jfconfig.intTest": "Int Test",
"libjf-config-reflect-v0-testmod.jfconfig.decimalTest": "Decimal Test", "libjf-config-reflect-v1-testmod.jfconfig.decimalTest": "Decimal Test",
"libjf-config-reflect-v0-testmod.jfconfig.dieStr": "String Test", "libjf-config-reflect-v1-testmod.jfconfig.dieStr": "String Test",
"libjf-config-reflect-v0-testmod.jfconfig.gsonOnlyStr.tooltip": "George", "libjf-config-reflect-v1-testmod.jfconfig.gsonOnlyStr.tooltip": "George",
"libjf-config-reflect-v0-testmod.jfconfig.enumTest": "Enum Test", "libjf-config-reflect-v1-testmod.jfconfig.enumTest": "Enum Test",
"libjf-config-reflect-v0-testmod.jfconfig.enumTest.tooltip": "Enum Test Tooltip", "libjf-config-reflect-v1-testmod.jfconfig.enumTest.tooltip": "Enum Test Tooltip",
"libjf-config-reflect-v0-testmod.jfconfig.enum.Test.Test": "Test", "libjf-config-reflect-v1-testmod.jfconfig.enum.Test.Test": "Test",
"libjf-config-reflect-v0-testmod.jfconfig.enum.Test.ER": "ER", "libjf-config-reflect-v1-testmod.jfconfig.enum.Test.ER": "ER",
"libjf-config-reflect-v0-testmod.jfconfig.moskau": "Moskau" "libjf-config-reflect-v1-testmod.jfconfig.moskau": "Moskau"
} }

View File

@ -1,6 +1,6 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"id": "libjf-config-reflect-v0-testmod", "id": "libjf-config-reflect-v1-testmod",
"version": "1.0", "version": "1.0",
"environment": "*", "environment": "*",
"entrypoints": { "entrypoints": {

View File

@ -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<Double> onChange;
private final boolean wholeNumber;
public CustomSlider(int x, int y, int width, int height, double value, double min, double max, Consumer<Double> 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));
}
}

View File

@ -37,12 +37,25 @@ public class EntryInfoWidgetBuilder {
WidgetState<T> state = new WidgetState<>(); WidgetState<T> state = new WidgetState<>();
WidgetFactory factory; WidgetFactory factory;
if (type.isInt()) factory = textField(info, state, INTEGER_ONLY, Integer::parseInt, true, info.getMinValue(), info.getMaxValue()); if (type.isInt()) {
else if (type.isLong()) factory = textField(info, state, INTEGER_ONLY, Long::parseLong, true, info.getMinValue(), info.getMaxValue()); factory = isDiscrete(info)
else if (type.isFloat()) factory = textField(info, state, DECIMAL_ONLY, Float::parseFloat, false, info.getMinValue(), info.getMaxValue()); ? slider(info, state, t -> (double)(int)t, Double::intValue, true)
else if (type.isDouble()) factory = textField(info, state, DECIMAL_ONLY, Double::parseDouble, false, info.getMinValue(), info.getMaxValue()); : textField(info, state, INTEGER_ONLY, Integer::parseInt, true, 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.isLong()) {
else if (type.isBool()) { 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, factory = toggle(info, state,
value -> !(Boolean) value, value -> !(Boolean) value,
value -> Text.literal((Boolean) value ? "True" : "False").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED)); 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); return new WidgetFactory.Widget(() -> widget.setText(state.cachedValue == null ? "" : state.cachedValue.toString()), widget);
}; };
} }
private static <T extends Number> WidgetFactory slider(EntryInfo info, WidgetState state, Function<T, Double> t2d, Function<Double, T> 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);
}
} }