From e73a08e6672fb380cab8db71340158969c5ef56b Mon Sep 17 00:00:00 2001 From: isXander Date: Sat, 19 Oct 2024 19:22:45 +0100 Subject: 3.6.0 --- .../java/dev/isxander/yacl3/api/LabelOption.java | 2 + .../java/dev/isxander/yacl3/api/ListOption.java | 6 ++ src/main/java/dev/isxander/yacl3/api/Option.java | 20 +++++ .../isxander/yacl3/api/OptionEventListener.java | 13 ++++ .../java/dev/isxander/yacl3/api/StateManager.java | 89 ++++++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 src/main/java/dev/isxander/yacl3/api/OptionEventListener.java create mode 100644 src/main/java/dev/isxander/yacl3/api/StateManager.java (limited to 'src/main/java/dev/isxander/yacl3/api') diff --git a/src/main/java/dev/isxander/yacl3/api/LabelOption.java b/src/main/java/dev/isxander/yacl3/api/LabelOption.java index a5f015e..16372b0 100644 --- a/src/main/java/dev/isxander/yacl3/api/LabelOption.java +++ b/src/main/java/dev/isxander/yacl3/api/LabelOption.java @@ -26,6 +26,8 @@ public interface LabelOption extends Option { } interface Builder { + Builder state(@NotNull StateManager stateManager); + /** * Appends a line to the label */ diff --git a/src/main/java/dev/isxander/yacl3/api/ListOption.java b/src/main/java/dev/isxander/yacl3/api/ListOption.java index 1f4adfa..9103254 100644 --- a/src/main/java/dev/isxander/yacl3/api/ListOption.java +++ b/src/main/java/dev/isxander/yacl3/api/ListOption.java @@ -93,6 +93,8 @@ public interface ListOption extends OptionGroup, Option> { */ Builder customController(@NotNull Function, Controller> control); + Builder state(@NotNull StateManager> stateManager); + /** * Sets the binding for the option. * Used for default, getter and setter. @@ -159,6 +161,10 @@ public interface ListOption extends OptionGroup, Option> { */ Builder collapsed(boolean collapsible); + ListOption.Builder addListener(@NotNull OptionEventListener> listener); + + ListOption.Builder addListeners(@NotNull Collection>> listeners); + /** * Adds a listener to the option. Invoked upon changing any of the list's entries. * diff --git a/src/main/java/dev/isxander/yacl3/api/Option.java b/src/main/java/dev/isxander/yacl3/api/Option.java index 38bd8ca..9190168 100644 --- a/src/main/java/dev/isxander/yacl3/api/Option.java +++ b/src/main/java/dev/isxander/yacl3/api/Option.java @@ -34,12 +34,15 @@ public interface Option { */ @NotNull Controller controller(); + @NotNull StateManager stateManager(); + /** * Binding for the option. * Controls setting, getting and default value. * * @see Binding */ + @Deprecated @NotNull Binding binding(); /** @@ -101,9 +104,12 @@ public interface Option { return true; } + void addEventListener(OptionEventListener listener); + /** * Adds a listener for when the pending value changes */ + @Deprecated void addListener(BiConsumer, T> changedListener); static Builder createBuilder() { @@ -146,6 +152,10 @@ public interface Option { */ Builder description(@NotNull Function descriptionFunction); + /** + * Supplies a controller for this option. A controller is the GUI control to interact with the option. + * @return this builder + */ Builder controller(@NotNull Function, ControllerBuilder> controllerBuilder); /** @@ -156,9 +166,12 @@ public interface Option { */ Builder customController(@NotNull Function, Controller> control); + Builder stateManager(@NotNull StateManager stateManager); + /** * Sets the binding for the option. * Used for default, getter and setter. + * Under-the-hood, this creates a state manager that is individual to the option, sharing state with no options. * * @see Binding */ @@ -196,12 +209,17 @@ public interface Option { */ Builder flags(@NotNull Collection flags); + Builder addListener(@NotNull OptionEventListener listener); + + Builder addListeners(@NotNull Collection> listeners); + /** * Instantly invokes the binder's setter when modified in the GUI. * Prevents the user from undoing the change *

* Does not support {@link Option#flags()}! */ + @Deprecated Builder instant(boolean instant); /** @@ -209,6 +227,7 @@ public interface Option { * * @see Option#addListener(BiConsumer) */ + @Deprecated Builder listener(@NotNull BiConsumer, T> listener); /** @@ -216,6 +235,7 @@ public interface Option { * * @see Option#addListener(BiConsumer) */ + @Deprecated Builder listeners(@NotNull Collection, T>> listeners); Option build(); diff --git a/src/main/java/dev/isxander/yacl3/api/OptionEventListener.java b/src/main/java/dev/isxander/yacl3/api/OptionEventListener.java new file mode 100644 index 0000000..c805948 --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/api/OptionEventListener.java @@ -0,0 +1,13 @@ +package dev.isxander.yacl3.api; + +@FunctionalInterface +public interface OptionEventListener { + void onEvent(Option option, Event event); + + enum Event { + INITIAL, + STATE_CHANGE, + AVAILABILITY_CHANGE, + OTHER, + } +} diff --git a/src/main/java/dev/isxander/yacl3/api/StateManager.java b/src/main/java/dev/isxander/yacl3/api/StateManager.java new file mode 100644 index 0000000..07d263e --- /dev/null +++ b/src/main/java/dev/isxander/yacl3/api/StateManager.java @@ -0,0 +1,89 @@ +package dev.isxander.yacl3.api; + +import dev.isxander.yacl3.impl.ImmutableStateManager; +import dev.isxander.yacl3.impl.InstantStateManager; +import dev.isxander.yacl3.impl.SimpleStateManager; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +public interface StateManager { + static StateManager createSimple(Binding binding) { + return new SimpleStateManager<>(binding); + } + + static StateManager createSimple(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter) { + return new SimpleStateManager<>(Binding.generic(def, getter, setter)); + } + + static StateManager createInstant(Binding binding) { + return new InstantStateManager<>(binding); + } + + static StateManager createInstant(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter) { + return new InstantStateManager<>(Binding.generic(def, getter, setter)); + } + + static StateManager createImmutable(@NotNull T value) { + return new ImmutableStateManager<>(value); + } + + /** + * Sets the pending value. + */ + void set(T value); + + /** + * @return the pending value. + */ + T get(); + + /** + * Applies the pending value to the backed binding. + */ + void apply(); + + void resetToDefault(ResetAction action); + + /** + * Essentially "forgets" the pending value and reassigns state as backed by the binding. + */ + void sync(); + + /** + * @return true if the pending value is the same as the backed binding value. + */ + boolean isSynced(); + + /** + * @return true if this state manage will always be synced with the backing binding. + */ + default boolean isAlwaysSynced() { + return false; + } + + boolean isDefault(); + + void addListener(StateListener stateListener); + + enum ResetAction { + BY_OPTION, + BY_GLOBAL, + } + + interface StateListener { + static StateListener noop() { + return (oldValue, newValue) -> {}; + } + + void onStateChange(T oldValue, T newValue); + + default StateListener andThen(StateListener after) { + return (oldValue, newValue) -> { + this.onStateChange(oldValue, newValue); + after.onStateChange(oldValue, newValue); + }; + } + } +} -- cgit