LibJF/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/gui/EntryInfoWidgetBuilder.java

103 lines
5.0 KiB
Java
Raw Normal View History

2021-10-06 19:01:48 +02:00
package io.gitlab.jfronny.libjf.config.impl.gui;
2021-04-11 16:00:37 +02:00
2021-10-06 19:01:48 +02:00
import io.gitlab.jfronny.libjf.config.api.Entry;
import io.gitlab.jfronny.libjf.config.impl.Config;
import io.gitlab.jfronny.libjf.config.impl.EntryInfo;
2021-05-15 15:34:19 +02:00
import io.gitlab.jfronny.libjf.gson.GsonHidden;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
2021-10-06 19:01:48 +02:00
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
2021-05-15 15:34:19 +02:00
import net.minecraft.util.Formatting;
2021-04-11 16:00:37 +02:00
2021-10-06 19:01:48 +02:00
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.List;
2021-05-15 15:34:19 +02:00
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
2021-04-11 16:00:37 +02:00
2021-10-06 19:01:48 +02:00
@Environment(EnvType.CLIENT)
public class EntryInfoWidgetBuilder {
2021-05-15 15:34:19 +02:00
private static final Pattern INTEGER_ONLY = Pattern.compile("(-?[0-9]*)");
private static final Pattern DECIMAL_ONLY = Pattern.compile("-?([\\d]+\\.?[\\d]*|[\\d]*\\.?[\\d]+|\\.)");
2021-10-06 19:01:48 +02:00
public static void initConfig(Config config) {
for (EntryInfo info : config.entries) {
if (info.field.isAnnotationPresent(Entry.class) || info.field.isAnnotationPresent(GsonHidden.class))
2021-05-15 15:34:19 +02:00
try {
2021-10-06 19:01:48 +02:00
initEntry(config, info);
} catch (Exception ignored) {
}
2021-04-11 16:00:37 +02:00
}
}
2021-10-06 19:01:48 +02:00
private static void initEntry(Config config, EntryInfo info) {
if (!(info.field.isAnnotationPresent(io.gitlab.jfronny.libjf.config.api.Entry.class) || info.field.isAnnotationPresent(GsonHidden.class))) return;
Class<?> type = info.field.getType();
2021-10-06 19:01:48 +02:00
io.gitlab.jfronny.libjf.config.api.Entry e = info.field.getAnnotation(Entry.class);
2021-05-15 15:34:19 +02:00
info.width = e != null ? e.width() : 0;
if (e == null) return;
if (type == int.class || type == Integer.class) textField(config, info, Integer::parseInt, INTEGER_ONLY, e.min(), e.max(), true);
else if (type == float.class || type == Float.class) textField(config, info, Float::parseFloat, DECIMAL_ONLY, e.min(), e.max(),false);
else if (type == double.class || type == Double.class) textField(config, info, Double::parseDouble, DECIMAL_ONLY, e.min(), e.max(),false);
2021-10-06 19:01:48 +02:00
else if (type == String.class) textField(config, info, String::length, null, Math.min(e.min(),0), Math.max(e.max(),1),true);
else if (type == boolean.class || type == Boolean.class) {
2021-10-06 19:01:48 +02:00
Function<Object, Text> func = value -> new LiteralText((Boolean) value ? "True" : "False").formatted((Boolean) value ? Formatting.GREEN : Formatting.RED);
info.widget = new AbstractMap.SimpleEntry<ButtonWidget.PressAction, Function<Object, Text>>(button -> {
info.value = !(Boolean) info.value;
button.setMessage(func.apply(info.value));
}, func);
} else if (type.isEnum()) {
List<?> values = Arrays.asList(info.field.getType().getEnumConstants());
2021-10-06 19:01:48 +02:00
Function<Object,Text> func = value -> new TranslatableText(config.modid + ".jfconfig." + "enum." + type.getSimpleName() + "." + info.value.toString());
info.widget = new AbstractMap.SimpleEntry<ButtonWidget.PressAction, Function<Object, Text>>(button -> {
int index = values.indexOf(info.value) + 1;
info.value = values.get(index >= values.size()? 0 : index);
button.setMessage(func.apply(info.value));
}, func);
}
try {
info.value = info.field.get(null);
info.tempValue = info.value.toString();
} catch (IllegalAccessException ignored) {
}
2021-05-15 15:34:19 +02:00
}
2021-10-06 19:01:48 +02:00
private static void textField(Config config, EntryInfo info, Function<String,Number> f, Pattern pattern, double min, double max, boolean cast) {
2021-05-15 15:34:19 +02:00
boolean isNumber = pattern != null;
info.widget = (BiFunction<TextFieldWidget, ButtonWidget, Predicate<String>>) (t, b) -> s -> {
s = s.trim();
if (!(s.isEmpty() || !isNumber || pattern.matcher(s).matches())) return false;
Number value = 0;
boolean inLimits = false;
info.error = null;
if (!(isNumber && s.isEmpty()) && !s.equals("-") && !s.equals(".")) {
value = f.apply(s);
inLimits = value.doubleValue() >= min && value.doubleValue() <= max;
info.error = inLimits? null : new AbstractMap.SimpleEntry<>(t, new LiteralText(value.doubleValue() < min ?
"§cMinimum " + (isNumber? "value" : "length") + (cast? " is " + (int)min : " is " + min) :
"§cMaximum " + (isNumber? "value" : "length") + (cast? " is " + (int)max : " is " + max)));
}
info.tempValue = s;
t.setEditableColor(inLimits? 0xFFFFFFFF : 0xFFFF7777);
info.inLimits = inLimits;
2021-10-06 19:01:48 +02:00
b.active = config.entries.stream().allMatch(e -> e.inLimits);
2021-05-15 15:34:19 +02:00
if (inLimits)
info.value = isNumber? value : s;
return true;
};
}
}