aboutsummaryrefslogtreecommitdiff
path: root/src/client/java/dev/isxander/yacl/impl
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/java/dev/isxander/yacl/impl')
-rw-r--r--src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java5
-rw-r--r--src/client/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java122
-rw-r--r--src/client/java/dev/isxander/yacl/impl/ListOptionImpl.java208
-rw-r--r--src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java2
-rw-r--r--src/client/java/dev/isxander/yacl/impl/OptionImpl.java5
-rw-r--r--src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java67
6 files changed, 397 insertions, 12 deletions
diff --git a/src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java b/src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java
index dcb9c7a..f526d42 100644
--- a/src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java
+++ b/src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java
@@ -79,11 +79,6 @@ public class ButtonOptionImpl implements ButtonOption {
}
@Override
- public boolean requiresRestart() {
- return false;
- }
-
- @Override
public boolean changed() {
return false;
}
diff --git a/src/client/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java b/src/client/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java
new file mode 100644
index 0000000..dc7aa88
--- /dev/null
+++ b/src/client/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java
@@ -0,0 +1,122 @@
+package dev.isxander.yacl.impl;
+
+import dev.isxander.yacl.api.*;
+import net.minecraft.text.Text;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+public class ListOptionEntryImpl<T> implements ListOptionEntry<T> {
+ private final ListOptionImpl<T> group;
+
+ private T value;
+
+ private final Binding<T> binding;
+ private final Controller<T> controller;
+
+ public ListOptionEntryImpl(ListOptionImpl<T> group, T initialValue, @NotNull Function<ListOptionEntry<T>, Controller<T>> controlGetter) {
+ this.group = group;
+ this.value = initialValue;
+ this.binding = new EntryBinding();
+ this.controller = controlGetter.apply(this);
+ }
+
+ @Override
+ public @NotNull Text name() {
+ return Text.empty();
+ }
+
+ @Override
+ public @NotNull Text tooltip() {
+ return Text.empty();
+ }
+
+ @Override
+ public @NotNull Controller<T> controller() {
+ return controller;
+ }
+
+ @Override
+ public @NotNull Binding<T> binding() {
+ return binding;
+ }
+
+ @Override
+ public boolean available() {
+ return parentGroup().available();
+ }
+
+ @Override
+ public void setAvailable(boolean available) {
+
+ }
+
+ @Override
+ public ListOption<T> parentGroup() {
+ return group;
+ }
+
+ @Override
+ public boolean changed() {
+ return false;
+ }
+
+ @Override
+ public @NotNull T pendingValue() {
+ return value;
+ }
+
+ @Override
+ public void requestSet(T value) {
+ binding.setValue(value);
+ }
+
+ @Override
+ public boolean applyValue() {
+ return false;
+ }
+
+ @Override
+ public void forgetPendingValue() {
+
+ }
+
+ @Override
+ public void requestSetDefault() {
+
+ }
+
+ @Override
+ public boolean isPendingValueDefault() {
+ return false;
+ }
+
+ @Override
+ public boolean canResetToDefault() {
+ return false;
+ }
+
+ @Override
+ public void addListener(BiConsumer<Option<T>, T> changedListener) {
+
+ }
+
+ private class EntryBinding implements Binding<T> {
+ @Override
+ public void setValue(T newValue) {
+ value = newValue;
+ group.callListeners();
+ }
+
+ @Override
+ public T getValue() {
+ return value;
+ }
+
+ @Override
+ public T defaultValue() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/src/client/java/dev/isxander/yacl/impl/ListOptionImpl.java b/src/client/java/dev/isxander/yacl/impl/ListOptionImpl.java
new file mode 100644
index 0000000..128d3e7
--- /dev/null
+++ b/src/client/java/dev/isxander/yacl/impl/ListOptionImpl.java
@@ -0,0 +1,208 @@
+package dev.isxander.yacl.impl;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import dev.isxander.yacl.api.*;
+import net.minecraft.text.Text;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class ListOptionImpl<T> implements ListOption<T> {
+ private final Text name;
+ private final Text tooltip;
+ private final Binding<List<T>> binding;
+ private final T initialValue;
+ private final List<ListOptionEntry<T>> entries;
+ private final boolean collapsed;
+ private boolean available;
+ private final Class<T> typeClass;
+ private final ImmutableSet<OptionFlag> flags;
+ private final EntryFactory entryFactory;
+ private final List<BiConsumer<Option<List<T>>, List<T>>> listeners;
+ private final List<Runnable> refreshListeners;
+
+ public ListOptionImpl(@NotNull Text name, @NotNull Text tooltip, @NotNull Binding<List<T>> binding, @NotNull T initialValue, @NotNull Class<T> typeClass, @NotNull Function<ListOptionEntry<T>, Controller<T>> controllerFunction, ImmutableSet<OptionFlag> flags, boolean collapsed, boolean available) {
+ this.name = name;
+ this.tooltip = tooltip;
+ this.binding = binding;
+ this.initialValue = initialValue;
+ this.entryFactory = new EntryFactory(controllerFunction);
+ this.entries = createEntries(binding().getValue());
+ this.collapsed = collapsed;
+ this.typeClass = typeClass;
+ this.flags = flags;
+ this.available = available;
+ this.listeners = new ArrayList<>();
+ this.refreshListeners = new ArrayList<>();
+ callListeners();
+ }
+
+ @Override
+ public @NotNull Text name() {
+ return this.name;
+ }
+
+ @Override
+ public @NotNull Text tooltip() {
+ return this.tooltip;
+ }
+
+ @Override
+ public @NotNull ImmutableList<ListOptionEntry<T>> options() {
+ return ImmutableList.copyOf(entries);
+ }
+
+ @Override
+ public @NotNull Controller<List<T>> controller() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public @NotNull Binding<List<T>> binding() {
+ return binding;
+ }
+
+ @Override
+ public @NotNull Class<List<T>> typeClass() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public @NotNull Class<T> elementTypeClass() {
+ return typeClass;
+ }
+
+ @Override
+ public boolean collapsed() {
+ return collapsed;
+ }
+
+ @Override
+ public @NotNull ImmutableSet<OptionFlag> flags() {
+ return flags;
+ }
+
+ @Override
+ public ImmutableList<T> pendingValue() {
+ return ImmutableList.copyOf(entries.stream().map(Option::pendingValue).toList());
+ }
+
+ @Override
+ public void insertEntry(int index, ListOptionEntry<?> entry) {
+ entries.add(index, (ListOptionEntry<T>) entry);
+ onRefresh();
+ }
+
+ @Override
+ public ListOptionEntry<T> insertNewEntryToTop() {
+ ListOptionEntry<T> newEntry = entryFactory.create(initialValue);
+ entries.add(0, newEntry);
+ onRefresh();
+ return newEntry;
+ }
+
+ @Override
+ public void removeEntry(ListOptionEntry<?> entry) {
+ entries.remove(entry);
+ onRefresh();
+ }
+
+ @Override
+ public int indexOf(ListOptionEntry<?> entry) {
+ return entries.indexOf(entry);
+ }
+
+ @Override
+ public void requestSet(List<T> value) {
+ entries.clear();
+ entries.addAll(createEntries(value));
+ onRefresh();
+ listeners.forEach(listener -> listener.accept(this, value));
+ }
+
+ @Override
+ public boolean changed() {
+ return !binding().getValue().equals(pendingValue());
+ }
+
+ @Override
+ public boolean applyValue() {
+ if (changed()) {
+ binding().setValue(pendingValue());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void forgetPendingValue() {
+ requestSet(binding().getValue());
+ }
+
+ @Override
+ public void requestSetDefault() {
+ requestSet(binding().defaultValue());
+ }
+
+ @Override
+ public boolean isPendingValueDefault() {
+ return binding().defaultValue().equals(pendingValue());
+ }
+
+ @Override
+ public boolean available() {
+ return available;
+ }
+
+ @Override
+ public void setAvailable(boolean available) {
+ this.available = available;
+ }
+
+ @Override
+ public void addListener(BiConsumer<Option<List<T>>, List<T>> changedListener) {
+ this.listeners.add(changedListener);
+ }
+
+ @Override
+ public void addRefreshListener(Runnable changedListener) {
+ this.refreshListeners.add(changedListener);
+ }
+
+ @Override
+ public boolean isRoot() {
+ return false;
+ }
+
+ private List<ListOptionEntry<T>> createEntries(Collection<T> values) {
+ return values.stream().map(entryFactory::create).collect(Collectors.toList());
+ }
+
+ void callListeners() {
+ List<T> pendingValue = pendingValue();
+ this.listeners.forEach(listener -> listener.accept(this, pendingValue));
+ }
+
+ private void onRefresh() {
+ refreshListeners.forEach(Runnable::run);
+ callListeners();
+ }
+
+ private class EntryFactory {
+ private final Function<ListOptionEntry<T>, Controller<T>> controllerFunction;
+
+ private EntryFactory(Function<ListOptionEntry<T>, Controller<T>> controllerFunction) {
+ this.controllerFunction = controllerFunction;
+ }
+
+ public ListOptionEntry<T> create(T initialValue) {
+ return new ListOptionEntryImpl<>(ListOptionImpl.this, initialValue, controllerFunction);
+ }
+ }
+}
diff --git a/src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java b/src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java
index 58bc96b..02ef04c 100644
--- a/src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java
+++ b/src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java
@@ -6,5 +6,5 @@ import dev.isxander.yacl.api.OptionGroup;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
-public record OptionGroupImpl(@NotNull Text name, @NotNull Text tooltip, ImmutableList<Option<?>> options, boolean collapsed, boolean isRoot) implements OptionGroup {
+public record OptionGroupImpl(@NotNull Text name, @NotNull Text tooltip, ImmutableList<? extends Option<?>> options, boolean collapsed, boolean isRoot) implements OptionGroup {
}
diff --git a/src/client/java/dev/isxander/yacl/impl/OptionImpl.java b/src/client/java/dev/isxander/yacl/impl/OptionImpl.java
index 90158c7..0cc156f 100644
--- a/src/client/java/dev/isxander/yacl/impl/OptionImpl.java
+++ b/src/client/java/dev/isxander/yacl/impl/OptionImpl.java
@@ -93,11 +93,6 @@ public class OptionImpl<T> implements Option<T> {
}
@Override
- public boolean requiresRestart() {
- return flags.contains(OptionFlag.GAME_RESTART);
- }
-
- @Override
public boolean changed() {
return !binding().getValue().equals(pendingValue);
}
diff --git a/src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java b/src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java
index eb23eac..380929c 100644
--- a/src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java
+++ b/src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java
@@ -8,12 +8,77 @@ import dev.isxander.yacl.impl.utils.YACLConstants;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
+import java.util.Objects;
import java.util.function.Consumer;
-public record YetAnotherConfigLibImpl(Text title, ImmutableList<ConfigCategory> categories, Runnable saveFunction, Consumer<YACLScreen> initConsumer) implements YetAnotherConfigLib {
+public final class YetAnotherConfigLibImpl implements YetAnotherConfigLib {
+ private final Text title;
+ private final ImmutableList<ConfigCategory> categories;
+ private final Runnable saveFunction;
+ private final Consumer<YACLScreen> initConsumer;
+
+ private boolean generated = false;
+
+ public YetAnotherConfigLibImpl(Text title, ImmutableList<ConfigCategory> categories, Runnable saveFunction, Consumer<YACLScreen> initConsumer) {
+ this.title = title;
+ this.categories = categories;
+ this.saveFunction = saveFunction;
+ this.initConsumer = initConsumer;
+ }
+
@Override
public Screen generateScreen(Screen parent) {
+ if (generated)
+ throw new UnsupportedOperationException("To prevent memory leaks, you should only generate a Screen once per instance. Please re-build the instance to generate another GUI.");
+
YACLConstants.LOGGER.info("Generating YACL screen");
+ generated = true;
return new YACLScreen(this, parent);
}
+
+ @Override
+ public Text title() {
+ return title;
+ }
+
+ @Override
+ public ImmutableList<ConfigCategory> categories() {
+ return categories;
+ }
+
+ @Override
+ public Runnable saveFunction() {
+ return saveFunction;
+ }
+
+ @Override
+ public Consumer<YACLScreen> initConsumer() {
+ return initConsumer;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) return true;
+ if (obj == null || obj.getClass() != this.getClass()) return false;
+ var that = (YetAnotherConfigLibImpl) obj;
+ return Objects.equals(this.title, that.title) &&
+ Objects.equals(this.categories, that.categories) &&
+ Objects.equals(this.saveFunction, that.saveFunction) &&
+ Objects.equals(this.initConsumer, that.initConsumer);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(title, categories, saveFunction, initConsumer);
+ }
+
+ @Override
+ public String toString() {
+ return "YetAnotherConfigLibImpl[" +
+ "title=" + title + ", " +
+ "categories=" + categories + ", " +
+ "saveFunction=" + saveFunction + ", " +
+ "initConsumer=" + initConsumer + ']';
+ }
+
}