package dev.isxander.yacl3.gui.controllers.dropdown; import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.gui.controllers.string.IStringController; import java.util.ArrayList; import java.util.Collections; import java.util.List; public abstract class AbstractDropdownController<T> implements IStringController<T> { protected final Option<T> option; private final List<String> allowedValues; public final boolean allowEmptyValue; public final boolean allowAnyValue; /** * Constructs a dropdown controller * * @param option bound option * @param allowedValues possible values */ protected AbstractDropdownController(Option<T> option, List<String> allowedValues, boolean allowEmptyValue, boolean allowAnyValue) { this.option = option; this.allowedValues = allowedValues; this.allowEmptyValue = allowEmptyValue; this.allowAnyValue = allowAnyValue; } protected AbstractDropdownController(Option<T> option, List<String> allowedValues) { this(option, allowedValues, false, false); } protected AbstractDropdownController(Option<T> option) { this(option, Collections.emptyList()); } /** * {@inheritDoc} */ @Override public Option<T> option() { return option; } public List<String> getAllowedValues() { return getAllowedValues(""); } public List<String> getAllowedValues(String inputField) { List<String> values = new ArrayList<>(allowedValues); if (allowEmptyValue && !values.contains("")) values.add(""); if (allowAnyValue && !inputField.isBlank() && !allowedValues.contains(inputField)) { values.add(inputField); } String currentValue = getString(); if (allowAnyValue && !allowedValues.contains(currentValue)) { values.add(currentValue); } return values; } public boolean isValueValid(String value) { if (value.isBlank()) return allowEmptyValue; return allowAnyValue || getAllowedValues().contains(value); } protected String getValidValue(String value) { return getValidValue(value, 0); } protected String getValidValue(String value, int offset) { if (offset == -1) return getString(); String valueLowerCase = value.toLowerCase(); return getAllowedValues(value).stream() .filter(val -> val.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); }) .skip(offset) .findFirst() .orElseGet(this::getString); } }