diff --git a/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/Config.java b/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/Config.java index 07a7797a6..5459409a0 100644 --- a/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/Config.java +++ b/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/Config.java @@ -34,8 +34,8 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.function.BooleanSupplier; import java.util.function.Predicate; +import java.util.function.Supplier; public abstract class Config { protected Tree tree; @@ -66,15 +66,19 @@ protected Tree makeTree(@NotNull String id) { return ConfigManager.collect(this, id); } - protected void addDependency(String option, BooleanSupplier condition) { - getProperty(option).addDisplayCondition(condition); - } - - protected void addDependency(String option, String name, BooleanSupplier condition) { + protected void addDependency(String option, String name, Supplier condition) { Property opt = getProperty(option).addDisplayCondition(condition); if (name != null) opt.getOrPutMetadata("dependencyNames", () -> new ArrayList(3)).add(name); } + protected void addDependency(String option, String condition) { + addDependency(option, condition, false); + } + + protected void hideIf(String option, String condition) { + addDependency(option, condition, true); + } + /** * Add a dependency on the given option, which will gray out or hide the option unless condition is true. * @@ -82,10 +86,10 @@ protected void addDependency(String option, String name, BooleanSupplier conditi * @param condition the boolean option which provides the dependency */ @SuppressWarnings("unchecked") - protected void addDependency(String option, String condition) { + protected void addDependency(String option, String condition, boolean hide) { Property cond = getProperty(condition); if (cond.type != boolean.class) throw new IllegalArgumentException("Condition property must be boolean"); - Property opt = getProperty(option).addDisplayCondition((Property) cond); + Property opt = getProperty(option).addDisplayCondition((Property) cond, hide); opt.getOrPutMetadata("dependencyNames", () -> new ArrayList(3)).add(cond.getTitle()); } diff --git a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt index faff39337..b46cc7592 100644 --- a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt +++ b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt @@ -34,7 +34,8 @@ import org.polyfrost.oneconfig.api.config.v1.Visualizer import org.polyfrost.polyui.animate.Animations import org.polyfrost.polyui.color.PolyColor import org.polyfrost.polyui.color.rgba -import org.polyfrost.polyui.component.* +import org.polyfrost.polyui.component.Component +import org.polyfrost.polyui.component.Drawable import org.polyfrost.polyui.component.extensions.* import org.polyfrost.polyui.component.impl.* import org.polyfrost.polyui.data.PolyImage @@ -46,7 +47,10 @@ import org.polyfrost.polyui.unit.Align import org.polyfrost.polyui.unit.Vec2 import org.polyfrost.polyui.unit.by import org.polyfrost.polyui.unit.seconds -import org.polyfrost.polyui.utils.* +import org.polyfrost.polyui.utils.fastEach +import org.polyfrost.polyui.utils.image +import org.polyfrost.polyui.utils.levenshteinDistance +import org.polyfrost.polyui.utils.mapToArray import kotlin.math.PI open class ConfigVisualizer { @@ -276,11 +280,38 @@ open class ConfigVisualizer { } private fun Drawable.addHideHandler(prop: Property<*>): Drawable { + this.on(Event.Lifetime.Disabled) { + this.alpha = 0.8f + } + this.on(Event.Lifetime.Enabled) { + this.alpha = 1f + } + var hidden = false prop.onDisplayChange { s -> - this.isEnabled = s - if (prop.getMetadata("hideOnDisplayFailure") == true) { - // todo + if (s == Property.Display.HIDDEN) { + hidden = true + if (!initialized) { + this.afterParentInit { + layoutIgnored = true + x = -100f + y = -100f + parent.position() + renders = false + } + } else { + layoutIgnored = true + x = -100f + y = -100f + parent.position() + renders = false + } + } else if (hidden) { + hidden = false + layoutIgnored = false + parent.position() + renders = true } + this.isEnabled = s == Property.Display.SHOWN } return this } diff --git a/modules/config/src/main/java/org/polyfrost/oneconfig/api/config/v1/Property.java b/modules/config/src/main/java/org/polyfrost/oneconfig/api/config/v1/Property.java index be7b00150..e1dee9018 100644 --- a/modules/config/src/main/java/org/polyfrost/oneconfig/api/config/v1/Property.java +++ b/modules/config/src/main/java/org/polyfrost/oneconfig/api/config/v1/Property.java @@ -34,7 +34,6 @@ import java.io.Serializable; import java.lang.ref.WeakReference; import java.util.*; -import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.Supplier; @@ -55,9 +54,9 @@ public abstract class Property extends Node implements Serializable { @NotNull public transient final Class type; protected transient List<@NotNull Predicate<@Nullable T>> callbacks = null; - private transient Consumer displayCallback = null; - private transient boolean display = true; - private transient List conditions = null; + private transient Consumer displayCallback = null; + private transient Display display = Display.SHOWN; + private transient List> conditions = null; protected Property(@Nullable String id, @Nullable String title, @Nullable String description, @NotNull Class type) { super(id, title, description); @@ -72,27 +71,28 @@ public static Property recast(@NotNull Property prop) { /** * This is used by the frontend to know if this property is able to be displayed, which is controlled by {@link #conditions}. * - * @see #addDisplayCondition(BooleanSupplier) + * @see #addDisplayCondition(Supplier) */ public final boolean canDisplay() { - return display; + return display == Display.SHOWN; } - public void onDisplayChange(Consumer callback) { + public void onDisplayChange(Consumer callback) { this.displayCallback = callback; + if (callback != null && display != Display.SHOWN) callback.accept(display); } /** * Add a display condition to this property. */ - public final Property addDisplayCondition(@NotNull BooleanSupplier condition) { + public final Property addDisplayCondition(@NotNull Supplier condition) { if (conditions == null) conditions = new ArrayList<>(3); conditions.add(condition); revaluateDisplay(); return this; } - public final Property addDisplayCondition(@NotNull Property condition) { + public final Property addDisplayCondition(@NotNull Property condition, boolean hides) { // asm: weak ref to avoid a potential memory leak if we are discarded for any reason WeakReference> ref = new WeakReference<>(this); condition.addCallback(t -> { @@ -101,16 +101,21 @@ public final Property addDisplayCondition(@NotNull Property conditio else self.revaluateDisplay(); return false; }); - this.addDisplayCondition(condition::get); + if (hides) { + this.addDisplayCondition(() -> Boolean.FALSE.equals(condition.get()) ? Display.HIDDEN : Display.SHOWN); + } else { + this.addDisplayCondition(() -> Boolean.FALSE.equals(condition.get()) ? Display.DISABLED : Display.SHOWN); + } return this; } - public final Property addDisplayCondition(@NotNull BooleanSupplier... conditions) { + @SafeVarargs + public final Property addDisplayCondition(@NotNull Supplier... conditions) { return addDisplayCondition(Arrays.asList(conditions)); } - public final Property addDisplayCondition(@NotNull Collection conditions) { + public final Property addDisplayCondition(@NotNull Collection> conditions) { if (this.conditions == null) this.conditions = new ArrayList<>(conditions); else { this.conditions.addAll(conditions); @@ -120,26 +125,23 @@ public final Property addDisplayCondition(@NotNull Collection s : conditions) { + Display out = s.get(); + if (out == Display.HIDDEN) { + d = Display.HIDDEN; + break; + } + if (out == Display.DISABLED) { + d = Display.DISABLED; } } } - if (displayCallback != null) displayCallback.accept(true); - display = true; - } - - /** - * Remove a display condition from this property. - */ - public final void removeDisplayCondition(@NotNull BooleanSupplier condition) { - if (conditions == null) return; - conditions.remove(condition); - revaluateDisplay(); + if (d != display) { + if (displayCallback != null) displayCallback.accept(d); + display = d; + } } /** @@ -147,14 +149,13 @@ public final void removeDisplayCondition(@NotNull BooleanSupplier condition) { */ protected final void clearDisplayConditions() { conditions = null; - display = true; + display = Display.SHOWN; } /** * Add a callback to this property, which is called when the value changes. * * @param callback the callback to add. The new value is passed to the callback. Return true if you wish to cancel the setting of the property. - * @see #removeCallback(Predicate) */ @kotlin.OverloadResolutionByLambdaReturnType public final Property addCallback(@NotNull Predicate<@Nullable T> callback) { @@ -188,14 +189,6 @@ public void overwrite(Node with) { if (that.callbacks != null) addCallback((Collection) that.callbacks); } - /** - * Remove a callback. - */ - public final void removeCallback(@NotNull Predicate<@Nullable T> callback) { - if (callbacks == null) return; - callbacks.remove(callback); - } - /** * Remove all callbacks. */ @@ -314,6 +307,12 @@ public final boolean isArray() { return type.isArray(); } + public enum Display { + SHOWN, + DISABLED, + HIDDEN + } + // classes are package-private so that NO internal implementation details are leaked to the user // they can only see the Property type diff --git a/versions/src/main/java/org/polyfrost/oneconfig/test/TestConfig_Test.java b/versions/src/main/java/org/polyfrost/oneconfig/test/TestConfig_Test.java index 24a72dfd5..86b3c474b 100644 --- a/versions/src/main/java/org/polyfrost/oneconfig/test/TestConfig_Test.java +++ b/versions/src/main/java/org/polyfrost/oneconfig/test/TestConfig_Test.java @@ -72,13 +72,13 @@ public class TestConfig_Test extends Config { public static boolean scow = false; @Switch(title = "Cow", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") public static boolean cgow = false; - @Switch(title = "Cow", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") + @Switch(title = "Cow 2", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") public static boolean c2ow = false; - @Switch(title = "Cow", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") + @Switch(title = "Cow 3", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") public static boolean c3ow = false; - @Switch(title = "Cow", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") + @Switch(title = "Cow 4", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") public static boolean c4ow = false; - @Switch(title = "Cow", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") + @Switch(title = "Cow 5", description = "Something that is way too long and is going to be trimmed (I hope) because that is what its meant to do") public static boolean c5ow = false; @RadioButton(title = "radio", description = "send help") public static Align.Main radio = Align.Main.Center; @@ -89,6 +89,8 @@ public class TestConfig_Test extends Config { public TestConfig_Test() { super("test_mod.json", "Test Mod", Category.QOL); + addDependency("c3ow", "c2ow"); + hideIf("c5ow", "c4ow"); } @Button(title = "Test")