diff options
author | isXander <xandersmith2008@gmail.com> | 2023-06-03 23:10:03 +0100 |
---|---|---|
committer | isXander <xandersmith2008@gmail.com> | 2023-06-04 16:25:09 +0100 |
commit | 3e36feeef60e56ef8cb7f737ac8eeab9fbcd6abb (patch) | |
tree | f9c3395b4da2235681b87a35ac5056a0724a181b /common/src/main/java/dev/isxander/yacl3/impl/OptionImpl.java | |
parent | d00a486d3bdf6105f8ca8af1034c384058b8c832 (diff) | |
download | YetAnotherConfigLib-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.java | 257 |
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); + } + } +} |