From bd3f0329d0e391bd84b5f9e3ff207d9dd9815853 Mon Sep 17 00:00:00 2001 From: Yasin Date: Mon, 9 Oct 2023 12:58:02 +0200 Subject: new pr because fixing merge conflict would take too long --- .../config/controllers/EnumDropdownController.java | 93 ++++++++++++++++++++++ .../controllers/EnumDropdownControllerBuilder.java | 27 +++++++ .../EnumDropdownControllerBuilderImpl.java | 27 +++++++ .../controllers/EnumDropdownControllerElement.java | 26 ++++++ 4 files changed, 173 insertions(+) create mode 100644 src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownController.java create mode 100644 src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerBuilder.java create mode 100644 src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java create mode 100644 src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerElement.java (limited to 'src/main/java/de/hysky/skyblocker/config/controllers') diff --git a/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownController.java b/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownController.java new file mode 100644 index 00000000..0b9a809d --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownController.java @@ -0,0 +1,93 @@ +package de.hysky.skyblocker.config.controllers; + +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.utils.Dimension; +import dev.isxander.yacl3.gui.AbstractWidget; +import dev.isxander.yacl3.gui.YACLScreen; +import dev.isxander.yacl3.gui.controllers.dropdown.AbstractDropdownController; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.function.Function; +import java.util.stream.Stream; + +public class EnumDropdownController> extends AbstractDropdownController { + /** + * The function used to convert enum constants to strings used for display, suggestion, and validation. Defaults to {@link Enum#toString}. + */ + protected final Function toString; + + protected EnumDropdownController(Option option, Function toString) { + super(option); + this.toString = toString; + } + + @Override + public String getString() { + return toString.apply(option().pendingValue()); + } + + @Override + public void setFromString(String value) { + option().requestSet(getEnumFromString(value)); + } + + /** + * Searches through enum constants for one whose {@link #toString} result equals {@code value} + * + * @return The enum constant associated with the {@code value} or the pending value if none are found + * @implNote The return value of {@link #toString} on each enum constant should be unique in order to ensure accuracy + */ + private E getEnumFromString(String value) { + value = value.toLowerCase(); + for (E constant : option().pendingValue().getDeclaringClass().getEnumConstants()) { + if (toString.apply(constant).toLowerCase().equals(value)) return constant; + } + + return option().pendingValue(); + } + + @Override + public boolean isValueValid(String value) { + value = value.toLowerCase(); + for (E constant : option().pendingValue().getDeclaringClass().getEnumConstants()) { + if (toString.apply(constant).equals(value)) return true; + } + + return false; + } + + @Override + protected String getValidValue(String value, int offset) { + return getValidEnumConstants(value) + .skip(offset) + .findFirst() + .orElseGet(this::getString); + } + + /** + * Filters and sorts through enum constants for those whose {@link #toString} result equals {@code value} + * + * @return a sorted stream containing enum constants associated with the {@code value} + * @implNote The return value of {@link #toString} on each enum constant should be unique in order to ensure accuracy + */ + @NotNull + protected Stream getValidEnumConstants(String value) { + String valueLowerCase = value.toLowerCase(); + return Arrays.stream(option().pendingValue().getDeclaringClass().getEnumConstants()) + .map(this.toString) + .filter(constant -> constant.toLowerCase().contains(valueLowerCase)) + .sorted((s1, s2) -> { + String s1LowerCase = s1.toLowerCase(); + String s2LowerCase = s2.toLowerCase(); + if (s1LowerCase.startsWith(valueLowerCase) && !s2LowerCase.startsWith(valueLowerCase)) return -1; + if (!s1LowerCase.startsWith(valueLowerCase) && s2LowerCase.startsWith(valueLowerCase)) return 1; + return s1.compareTo(s2); + }); + } + + @Override + public AbstractWidget provideWidget(YACLScreen screen, Dimension widgetDimension) { + return new EnumDropdownControllerElement<>(this, screen, widgetDimension); + } +} diff --git a/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerBuilder.java b/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerBuilder.java new file mode 100644 index 00000000..d451a88c --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerBuilder.java @@ -0,0 +1,27 @@ +package de.hysky.skyblocker.config.controllers; + +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.controller.ControllerBuilder; + +import java.util.function.Function; + +public interface EnumDropdownControllerBuilder> extends ControllerBuilder { + EnumDropdownControllerBuilder toString(Function toString); + + static > EnumDropdownControllerBuilder create(Option option) { + return new EnumDropdownControllerBuilderImpl<>(option); + } + + /** + * Creates a factory for {@link EnumDropdownControllerBuilder}s with the given function for converting enum constants to strings. + * Use this if a custom toString function for an enum is needed. + * Use it like this: + *
{@code Option.createBuilder().controller(createEnumDropdownControllerBuilder.getFactory(MY_CUSTOM_ENUM_TO_STRING_FUNCTION))}
+ * @param toString The function used to convert enum constants to strings used for display, suggestion, and validation + * @return a factory for {@link EnumDropdownControllerBuilder}s + * @param the enum type + */ + static > Function, ControllerBuilder> getFactory(Function toString) { + return opt -> EnumDropdownControllerBuilder.create(opt).toString(toString); + } +} diff --git a/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java b/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java new file mode 100644 index 00000000..8f6dbb2a --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java @@ -0,0 +1,27 @@ +package de.hysky.skyblocker.config.controllers; + +import dev.isxander.yacl3.api.Controller; +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.impl.controller.AbstractControllerBuilderImpl; + +import java.util.function.Function; + +public class EnumDropdownControllerBuilderImpl> extends AbstractControllerBuilderImpl implements EnumDropdownControllerBuilder { + private Function toString = Enum::toString; + + public EnumDropdownControllerBuilderImpl(Option option) { + super(option); + } + + @Override + public EnumDropdownControllerBuilder toString(Function toString) { + this.toString = toString; + return this; + } + + @SuppressWarnings("UnstableApiUsage") + @Override + public Controller build() { + return new EnumDropdownController<>(option, toString); + } +} diff --git a/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerElement.java b/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerElement.java new file mode 100644 index 00000000..2a8de609 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/config/controllers/EnumDropdownControllerElement.java @@ -0,0 +1,26 @@ +package de.hysky.skyblocker.config.controllers; + +import dev.isxander.yacl3.api.utils.Dimension; +import dev.isxander.yacl3.gui.YACLScreen; +import dev.isxander.yacl3.gui.controllers.dropdown.AbstractDropdownControllerElement; + +import java.util.List; + +public class EnumDropdownControllerElement> extends AbstractDropdownControllerElement { + private final EnumDropdownController controller; + + public EnumDropdownControllerElement(EnumDropdownController control, YACLScreen screen, Dimension dim) { + super(control, screen, dim); + this.controller = control; + } + + @Override + public List computeMatchingValues() { + return controller.getValidEnumConstants(inputField).toList(); + } + + @Override + public String getString(String object) { + return object; + } +} -- cgit