aboutsummaryrefslogtreecommitdiff
path: root/common/src/main/java/dev/isxander/yacl3/impl/OptionImpl.java
diff options
context:
space:
mode:
authorisXander <xandersmith2008@gmail.com>2023-06-03 23:10:03 +0100
committerisXander <xandersmith2008@gmail.com>2023-06-04 16:25:09 +0100
commit3e36feeef60e56ef8cb7f737ac8eeab9fbcd6abb (patch)
treef9c3395b4da2235681b87a35ac5056a0724a181b /common/src/main/java/dev/isxander/yacl3/impl/OptionImpl.java
parentd00a486d3bdf6105f8ca8af1034c384058b8c832 (diff)
downloadYetAnotherConfigLib-3e36feeef60e56ef8cb7f737ac8eeab9fbcd6abb.tar.gz
YetAnotherConfigLib-3e36feeef60e56ef8cb7f737ac8eeab9fbcd6abb.tar.bz2
YetAnotherConfigLib-3e36feeef60e56ef8cb7f737ac8eeab9fbcd6abb.zip
Change package and modid to yacl3 and yet_another_config_lib_3 respectively
Diffstat (limited to 'common/src/main/java/dev/isxander/yacl3/impl/OptionImpl.java')
-rw-r--r--common/src/main/java/dev/isxander/yacl3/impl/OptionImpl.java257
1 files changed, 257 insertions, 0 deletions
diff --git a/common/src/main/java/dev/isxander/yacl3/impl/OptionImpl.java b/common/src/main/java/dev/isxander/yacl3/impl/OptionImpl.java
new file mode 100644
index 0000000..9b3a613
--- /dev/null
+++ b/common/src/main/java/dev/isxander/yacl3/impl/OptionImpl.java
@@ -0,0 +1,257 @@
+package dev.isxander.yacl3.impl;
+
+import com.google.common.collect.ImmutableSet;
+import dev.isxander.yacl3.api.*;
+import dev.isxander.yacl3.api.controller.ControllerBuilder;
+import net.minecraft.ChatFormatting;
+import net.minecraft.network.chat.Component;
+import org.apache.commons.lang3.Validate;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+@ApiStatus.Internal
+public final class OptionImpl<T> implements Option<T> {
+ private final Component name;
+ private OptionDescription description;
+ private final Controller<T> controller;
+ private final Binding<T> binding;
+ private boolean available;
+
+ private final ImmutableSet<OptionFlag> flags;
+
+ private T pendingValue;
+
+ private final List<BiConsumer<Option<T>, T>> listeners;
+
+ public OptionImpl(
+ @NotNull Component name,
+ @NotNull Function<T, OptionDescription> descriptionFunction,
+ @NotNull Function<Option<T>, Controller<T>> controlGetter,
+ @NotNull Binding<T> binding,
+ boolean available,
+ ImmutableSet<OptionFlag> flags,
+ @NotNull Collection<BiConsumer<Option<T>, T>> listeners
+ ) {
+ this.name = name;
+ this.binding = binding;
+ this.available = available;
+ this.flags = flags;
+ this.listeners = new ArrayList<>(listeners);
+ this.controller = controlGetter.apply(this);
+
+ addListener((opt, pending) -> description = descriptionFunction.apply(pending));
+
+ requestSet(binding().getValue());
+ }
+
+ @Override
+ public @NotNull Component name() {
+ return name;
+ }
+
+ @Override
+ public @NotNull OptionDescription description() {
+ return this.description;
+ }
+
+ @Override
+ public @NotNull Component tooltip() {
+ return description.text();
+ }
+
+ @Override
+ public @NotNull Controller<T> controller() {
+ return controller;
+ }
+
+ @Override
+ public @NotNull Binding<T> binding() {
+ return binding;
+ }
+
+ @Override
+ public boolean available() {
+ return available;
+ }
+
+ @Override
+ public void setAvailable(boolean available) {
+ this.available = available;
+ }
+
+ @Override
+ public @NotNull ImmutableSet<OptionFlag> flags() {
+ return flags;
+ }
+
+ @Override
+ public boolean changed() {
+ return !binding().getValue().equals(pendingValue);
+ }
+
+ @Override
+ public @NotNull T pendingValue() {
+ return pendingValue;
+ }
+
+ @Override
+ public void requestSet(T value) {
+ pendingValue = value;
+ listeners.forEach(listener -> listener.accept(this, 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 void addListener(BiConsumer<Option<T>, T> changedListener) {
+ this.listeners.add(changedListener);
+ }
+
+ @ApiStatus.Internal
+ public static class BuilderImpl<T> implements Builder<T> {
+ private Component name = Component.literal("Name not specified!").withStyle(ChatFormatting.RED);
+
+ private Function<T, OptionDescription> descriptionFunction = pending -> OptionDescription.EMPTY;
+
+ private Function<Option<T>, Controller<T>> controlGetter;
+
+ private Binding<T> binding;
+
+ private boolean available = true;
+
+ private boolean instant = false;
+
+ private final Set<OptionFlag> flags = new HashSet<>();
+
+ private final List<BiConsumer<Option<T>, T>> listeners = new ArrayList<>();
+
+ @Override
+ public Builder<T> name(@NotNull Component name) {
+ Validate.notNull(name, "`name` cannot be null");
+
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public Builder<T> description(@NotNull OptionDescription description) {
+ return description(opt -> description);
+ }
+
+ @Override
+ public Builder<T> description(@NotNull Function<T, OptionDescription> descriptionFunction) {
+ this.descriptionFunction = descriptionFunction;
+ return this;
+ }
+
+ @Override
+ public Builder<T> controller(@NotNull Function<Option<T>, ControllerBuilder<T>> controllerBuilder) {
+ Validate.notNull(controllerBuilder, "`controllerBuilder` cannot be null");
+
+ return customController(opt -> controllerBuilder.apply(opt).build());
+ }
+
+ @Override
+ public Builder<T> customController(@NotNull Function<Option<T>, Controller<T>> control) {
+ Validate.notNull(control, "`control` cannot be null");
+
+ this.controlGetter = control;
+ return this;
+ }
+
+ @Override
+ public Builder<T> binding(@NotNull Binding<T> binding) {
+ Validate.notNull(binding, "`binding` cannot be null");
+
+ this.binding = binding;
+ return this;
+ }
+
+ @Override
+ public Builder<T> binding(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter) {
+ Validate.notNull(def, "`def` must not be null");
+ Validate.notNull(getter, "`getter` must not be null");
+ Validate.notNull(setter, "`setter` must not be null");
+
+ this.binding = Binding.generic(def, getter, setter);
+ return this;
+ }
+
+ @Override
+ public Builder<T> available(boolean available) {
+ this.available = available;
+ return this;
+ }
+
+ @Override
+ public Builder<T> flag(@NotNull OptionFlag... flag) {
+ Validate.notNull(flag, "`flag` must not be null");
+
+ this.flags.addAll(Arrays.asList(flag));
+ return this;
+ }
+
+ @Override
+ public Builder<T> flags(@NotNull Collection<? extends OptionFlag> flags) {
+ Validate.notNull(flags, "`flags` must not be null");
+
+ this.flags.addAll(flags);
+ return this;
+ }
+
+ @Override
+ public Builder<T> instant(boolean instant) {
+ this.instant = instant;
+ return this;
+ }
+
+ @Override
+ public Builder<T> listener(@NotNull BiConsumer<Option<T>, T> listener) {
+ this.listeners.add(listener);
+ return this;
+ }
+
+ @Override
+ public Builder<T> listeners(@NotNull Collection<BiConsumer<Option<T>, T>> listeners) {
+ this.listeners.addAll(listeners);
+ return this;
+ }
+
+ @Override
+ public Option<T> build() {
+ Validate.notNull(controlGetter, "`control` must not be null when building `Option`");
+ Validate.notNull(binding, "`binding` must not be null when building `Option`");
+ Validate.isTrue(!instant || flags.isEmpty(), "instant application does not support option flags");
+
+ return new OptionImpl<>(name, descriptionFunction, controlGetter, binding, available, ImmutableSet.copyOf(flags), listeners);
+ }
+ }
+}