aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/dev/isxander/yacl3/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/dev/isxander/yacl3/api')
-rw-r--r--src/main/java/dev/isxander/yacl3/api/LabelOption.java2
-rw-r--r--src/main/java/dev/isxander/yacl3/api/ListOption.java6
-rw-r--r--src/main/java/dev/isxander/yacl3/api/Option.java20
-rw-r--r--src/main/java/dev/isxander/yacl3/api/OptionEventListener.java13
-rw-r--r--src/main/java/dev/isxander/yacl3/api/StateManager.java89
5 files changed, 130 insertions, 0 deletions
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<Component> {
}
interface Builder {
+ Builder state(@NotNull StateManager<Component> 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<T> extends OptionGroup, Option<List<T>> {
*/
Builder<T> customController(@NotNull Function<ListOptionEntry<T>, Controller<T>> control);
+ Builder<T> state(@NotNull StateManager<List<T>> stateManager);
+
/**
* Sets the binding for the option.
* Used for default, getter and setter.
@@ -159,6 +161,10 @@ public interface ListOption<T> extends OptionGroup, Option<List<T>> {
*/
Builder<T> collapsed(boolean collapsible);
+ ListOption.Builder<T> addListener(@NotNull OptionEventListener<List<T>> listener);
+
+ ListOption.Builder<T> addListeners(@NotNull Collection<OptionEventListener<List<T>>> 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<T> {
*/
@NotNull Controller<T> controller();
+ @NotNull StateManager<T> stateManager();
+
/**
* Binding for the option.
* Controls setting, getting and default value.
*
* @see Binding
*/
+ @Deprecated
@NotNull Binding<T> binding();
/**
@@ -101,9 +104,12 @@ public interface Option<T> {
return true;
}
+ void addEventListener(OptionEventListener<T> listener);
+
/**
* Adds a listener for when the pending value changes
*/
+ @Deprecated
void addListener(BiConsumer<Option<T>, T> changedListener);
static <T> Builder<T> createBuilder() {
@@ -146,6 +152,10 @@ public interface Option<T> {
*/
Builder<T> description(@NotNull Function<T, OptionDescription> descriptionFunction);
+ /**
+ * Supplies a controller for this option. A controller is the GUI control to interact with the option.
+ * @return this builder
+ */
Builder<T> controller(@NotNull Function<Option<T>, ControllerBuilder<T>> controllerBuilder);
/**
@@ -156,9 +166,12 @@ public interface Option<T> {
*/
Builder<T> customController(@NotNull Function<Option<T>, Controller<T>> control);
+ Builder<T> stateManager(@NotNull StateManager<T> 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<T> {
*/
Builder<T> flags(@NotNull Collection<? extends OptionFlag> flags);
+ Builder<T> addListener(@NotNull OptionEventListener<T> listener);
+
+ Builder<T> addListeners(@NotNull Collection<OptionEventListener<T>> listeners);
+
/**
* Instantly invokes the binder's setter when modified in the GUI.
* Prevents the user from undoing the change
* <p>
* Does not support {@link Option#flags()}!
*/
+ @Deprecated
Builder<T> instant(boolean instant);
/**
@@ -209,6 +227,7 @@ public interface Option<T> {
*
* @see Option#addListener(BiConsumer)
*/
+ @Deprecated
Builder<T> listener(@NotNull BiConsumer<Option<T>, T> listener);
/**
@@ -216,6 +235,7 @@ public interface Option<T> {
*
* @see Option#addListener(BiConsumer)
*/
+ @Deprecated
Builder<T> listeners(@NotNull Collection<BiConsumer<Option<T>, T>> listeners);
Option<T> 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<T> {
+ void onEvent(Option<T> 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<T> {
+ static <T> StateManager<T> createSimple(Binding<T> binding) {
+ return new SimpleStateManager<>(binding);
+ }
+
+ static <T> StateManager<T> createSimple(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter) {
+ return new SimpleStateManager<>(Binding.generic(def, getter, setter));
+ }
+
+ static <T> StateManager<T> createInstant(Binding<T> binding) {
+ return new InstantStateManager<>(binding);
+ }
+
+ static <T> StateManager<T> createInstant(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter) {
+ return new InstantStateManager<>(Binding.generic(def, getter, setter));
+ }
+
+ static <T> StateManager<T> 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<T> stateListener);
+
+ enum ResetAction {
+ BY_OPTION,
+ BY_GLOBAL,
+ }
+
+ interface StateListener<T> {
+ static <T> StateListener<T> noop() {
+ return (oldValue, newValue) -> {};
+ }
+
+ void onStateChange(T oldValue, T newValue);
+
+ default StateListener<T> andThen(StateListener<T> after) {
+ return (oldValue, newValue) -> {
+ this.onStateChange(oldValue, newValue);
+ after.onStateChange(oldValue, newValue);
+ };
+ }
+ }
+}