diff --git a/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/GuiOptionEditor.java b/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/GuiOptionEditor.java
index 48fc3cfc2..6cdf1a05d 100644
--- a/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/GuiOptionEditor.java
+++ b/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/GuiOptionEditor.java
@@ -62,7 +62,7 @@ public void render(RenderContext context, int x, int y, int width) {
context.drawDarkRect(x, y, width, height, true);
context.drawStringCenteredScaledMaxWidth(option.getName(),
- fr, x + width / 6, y + 13, true, width / 3 - 10, 0xc0c0c0
+ fr, x + width / 6, y + 13, true, width / 3 - 10, 0xc0c0c0
);
float scale = 1;
@@ -115,7 +115,14 @@ public boolean mouseInputOverlay(int x, int y, int width, int mouseX, int mouseY
return false;
}
- // TODO: add RenderContext
+ public void renderOverlay(RenderContext renderContext, int x, int y, int width) {
+ this.renderOverlay(x, y, width);
+ }
+
+ /**
+ * Use {@link #renderOverlay(RenderContext, int, int, int)} instead.
+ */
+ @Deprecated
public void renderOverlay(int x, int y, int width) {
}
diff --git a/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/MoulConfigEditor.java b/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/MoulConfigEditor.java
index c4f199e06..f48642271 100644
--- a/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/MoulConfigEditor.java
+++ b/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/MoulConfigEditor.java
@@ -614,6 +614,7 @@ public void render() {
int finalOptionWidth = optionWidth;
ContextAware.wrapErrorWithContext(editor, () -> {
editor.renderOverlay(
+ context,
finalX,
finalY,
finalOptionWidth
diff --git a/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/ComponentEditor.java b/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/ComponentEditor.java
index 67af5851c..d2148a73e 100644
--- a/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/ComponentEditor.java
+++ b/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/ComponentEditor.java
@@ -209,13 +209,13 @@ public final boolean mouseInputOverlay(int x, int y, int width, int mouseX, int
}
@Override
- public final void renderOverlay(int x, int y, int width) {
+ public final void renderOverlay(RenderContext context, int x, int y, int width) {
if (overlay == null) return;
overlay.foldRecursive((Void) null, (comp, _void) -> {
comp.setContext(getDelegate().getContext());
return _void;
});
- val ctx = getImmContext(overlayX, overlayY, overlay.getWidth(), overlay.getHeight(), IMinecraft.instance.provideTopLevelRenderContext());
+ val ctx = getImmContext(overlayX, overlayY, overlay.getWidth(), overlay.getHeight(), context);
ctx.getRenderContext().translate(overlayX, overlayY, 0);
overlay.render(ctx);
}
diff --git a/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/GuiOptionEditorDraggableList.java b/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/GuiOptionEditorDraggableList.java
new file mode 100644
index 000000000..ada4c6715
--- /dev/null
+++ b/common/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/GuiOptionEditorDraggableList.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2023 NotEnoughUpdates contributors
+ *
+ * This file is part of MoulConfig.
+ *
+ * MoulConfig is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * MoulConfig is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with MoulConfig. If not, see .
+ *
+ */
+
+package io.github.notenoughupdates.moulconfig.gui.editors;
+
+import io.github.notenoughupdates.moulconfig.GuiTextures;
+import io.github.notenoughupdates.moulconfig.common.IMinecraft;
+import io.github.notenoughupdates.moulconfig.common.KeyboardConstants;
+import io.github.notenoughupdates.moulconfig.common.RenderContext;
+import io.github.notenoughupdates.moulconfig.gui.GuiOptionEditor;
+import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent;
+import io.github.notenoughupdates.moulconfig.gui.MouseEvent;
+import io.github.notenoughupdates.moulconfig.internal.LerpUtils;
+import io.github.notenoughupdates.moulconfig.internal.TypeUtils;
+import io.github.notenoughupdates.moulconfig.internal.Warnings;
+import io.github.notenoughupdates.moulconfig.processor.ProcessedOption;
+import kotlin.Pair;
+import lombok.var;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.*;
+
+public class GuiOptionEditorDraggableList extends GuiOptionEditor {
+ private Map exampleText = new HashMap<>();
+ private boolean enableDeleting;
+ private List activeText;
+ private final boolean requireNonEmpty;
+ private Object currentDragging = null;
+ private int dragStartIndex = -1;
+
+ private Pair lastMousePosition = null;
+
+ private long trashHoverTime = -1;
+
+ private int dragOffsetX = -1;
+ private int dragOffsetY = -1;
+ private boolean dropdownOpen = false;
+ private Enum>[] enumConstants;
+ private String exampleTextConcat;
+
+ public GuiOptionEditorDraggableList(
+ ProcessedOption option,
+ String[] exampleText,
+ boolean enableDeleting
+ ) {
+ this(option, exampleText, enableDeleting, false);
+ }
+
+ public GuiOptionEditorDraggableList(
+ ProcessedOption option,
+ String[] exampleText,
+ boolean enableDeleting,
+ boolean requireNonEmpty
+ ) {
+ super(option);
+
+ this.enableDeleting = enableDeleting;
+ this.activeText = (List) option.get();
+ this.requireNonEmpty = requireNonEmpty;
+
+ Class> elementType = TypeUtils.resolveRawType(((ParameterizedType) option.getType()).getActualTypeArguments()[0]);
+
+ if (Enum.class.isAssignableFrom(elementType)) {
+ Class extends Enum>> enumType = (Class extends Enum>>) elementType;
+ enumConstants = enumType.getEnumConstants();
+ for (int i = 0; i < enumConstants.length; i++) {
+ this.exampleText.put(enumConstants[i], enumConstants[i].toString());
+ }
+ } else {
+ for (int i = 0; i < exampleText.length; i++) {
+ this.exampleText.put(i, exampleText[i]);
+ }
+ }
+ }
+
+ private void saveChanges() {
+ option.explicitNotifyChange();
+ }
+
+ private String getExampleText(Object forObject) {
+ String str = exampleText.get(forObject);
+ if (str == null) {
+ str = "";
+ Warnings.warnOnce("Could not find draggable list object for " + forObject + " on option " + option.getCodeLocation(), forObject, option);
+ }
+ return str;
+ }
+
+ @Override
+ public int getHeight() {
+ int height = super.getHeight() + 13;
+
+ for (Object object : activeText) {
+ String str = getExampleText(object);
+ height += 10 * str.split("\n").length;
+ }
+
+ return height;
+ }
+
+ public boolean canDeleteRightNow() {
+ return enableDeleting && (activeText.size() > 1 || !requireNonEmpty);
+ }
+
+ @Override
+ public void render(RenderContext renderContext, int x, int y, int width) {
+ super.render(renderContext, x, y, width);
+ int height = getHeight();
+ var fr = IMinecraft.instance.getDefaultFontRenderer();
+
+ renderContext.color(1, 1, 1, 1);
+ IMinecraft.instance.bindTexture(GuiTextures.BUTTON);
+ renderContext.drawTexturedRect(x + width / 6 - 24, y + 45 - 7 - 14, 48, 16);
+
+ renderContext.drawStringCenteredScaledMaxWidth("Add", fr,
+ x + width / 6, y + 45 - 7 - 6,
+ false, 44, 0xFF303030
+ );
+
+ if (canDeleteRightNow()) {
+ long currentTime = System.currentTimeMillis();
+ if (trashHoverTime < 0) {
+ float greenBlue = LerpUtils.clampZeroOne((currentTime + trashHoverTime) / 250f);
+ renderContext.color(1, greenBlue, greenBlue, 1);
+ } else {
+ float greenBlue = LerpUtils.clampZeroOne((250 + trashHoverTime - currentTime) / 250f);
+ renderContext.color(1, greenBlue, greenBlue, 1);
+ }
+ int deleteX = x + width / 6 + 27;
+ int deleteY = y + 45 - 7 - 13;
+ renderContext.bindTexture(GuiTextures.DELETE);
+ renderContext.setTextureMinMagFilter(RenderContext.TextureFilter.NEAREST);
+ renderContext.drawTexturedRect(deleteX, deleteY, 11, 14);
+ // TODO: make use of the mouseX and mouseY from the context when switching this to a proper multi-version component
+ if (lastMousePosition != null && currentDragging == null &&
+ lastMousePosition.getFirst() >= deleteX && lastMousePosition.getFirst() < deleteX + 11 &&
+ lastMousePosition.getSecond() >= deleteY && lastMousePosition.getSecond() < deleteY + 14 &&
+ !dropdownOpen) {
+ renderContext.scheduleDrawTooltip(Collections.singletonList(
+ "§cDelete Item"
+ ));
+ }
+ renderContext.color(1, 1, 1, 1);
+ }
+
+ renderContext.drawColoredRect(x + 5, y + 45, x + width - 5, y + height - 5, 0xffdddddd);
+ renderContext.drawColoredRect(x + 6, y + 46, x + width - 6, y + height - 6, 0xff000000);
+
+ int i = 0;
+ int yOff = 0;
+ for (Object indexObject : activeText) {
+ String str = getExampleText(indexObject);
+
+ String[] multilines = str.split("\n");
+
+ int ySize = multilines.length * 10;
+
+ if (i++ != dragStartIndex) {
+ for (int multilineIndex = 0; multilineIndex < multilines.length; multilineIndex++) {
+ String line = multilines[multilineIndex];
+ renderContext.drawStringScaledMaxWidth(line + "§r", fr,
+ x + 20, y + 50 + yOff + multilineIndex * 10, true, width - 20, 0xffffffff
+ );
+ }
+ renderContext.drawString(
+ fr,
+ "≡",
+ x + 10,
+ y + 49 + yOff + ySize / 2 - 4,
+ 0xffffff,
+ true
+ );
+ }
+
+ yOff += ySize;
+ }
+ }
+
+ @Override
+ public void renderOverlay(RenderContext context, int x, int y, int width) {
+ super.renderOverlay(context, x, y, width);
+ var fr = IMinecraft.instance.getDefaultFontRenderer();
+ if (dropdownOpen) {
+ List remaining = new ArrayList<>(exampleText.keySet());
+ remaining.removeAll(activeText);
+
+ int dropdownWidth = Math.min(width / 2 - 10, 150);
+ int left = dragOffsetX;
+ int top = dragOffsetY;
+
+ int dropdownHeight = -1 + 12 * remaining.size();
+
+ int main = 0xff202026;
+ int outline = 0xff404046;
+ context.drawColoredRect(left, top, left + 1, top + dropdownHeight, outline); //Left
+ context.drawColoredRect(left + 1, top, left + dropdownWidth, top + 1, outline); //Top
+ context.drawColoredRect(left + dropdownWidth - 1, top + 1, left + dropdownWidth, top + dropdownHeight, outline); //Right
+ context.drawColoredRect(
+ left + 1,
+ top + dropdownHeight - 1,
+ left + dropdownWidth - 1,
+ top + dropdownHeight,
+ outline
+ ); //Bottom
+ context.drawColoredRect(left + 1, top + 1, left + dropdownWidth - 1, top + dropdownHeight - 1, main); //Middle
+
+ int dropdownY = -1;
+ for (Object indexObject : remaining) {
+ String str = getExampleText(indexObject);
+ if (str.isEmpty()) {
+ str = "";
+ }
+ context.drawStringScaledMaxWidth(str.replaceAll("(\n.*)+", " ..."),
+ fr, left + 3, top + 3 + dropdownY, false, dropdownWidth - 6, 0xffa0a0a0
+ );
+ dropdownY += 12;
+ }
+ } else if (currentDragging != null) {
+ int opacity = 0x80;
+ long currentTime = System.currentTimeMillis();
+ if (trashHoverTime < 0) {
+ float greenBlue = LerpUtils.clampZeroOne((currentTime + trashHoverTime) / 250f);
+ opacity = (int) (opacity * greenBlue);
+ } else {
+ float greenBlue = LerpUtils.clampZeroOne((250 + trashHoverTime - currentTime) / 250f);
+ opacity = (int) (opacity * greenBlue);
+ }
+
+ if (opacity < 20) return;
+
+ int mouseX = IMinecraft.instance.getMouseX();
+ int mouseY = IMinecraft.instance.getMouseY();
+
+ String str = getExampleText(currentDragging);
+ String[] multilines = str.split("\n");
+
+ // TODO: context.enableBlend();
+ for (int multilineIndex = 0; multilineIndex < multilines.length; multilineIndex++) {
+ String line = multilines[multilineIndex];
+ context.drawStringScaledMaxWidth(
+ line + "§r",
+ fr,
+ dragOffsetX + mouseX + 10,
+ dragOffsetY + mouseY + multilineIndex * 10,
+ true,
+ width - 20,
+ 0xffffff | (opacity << 24)
+ );
+ }
+
+ int ySize = multilines.length * 10;
+
+ context.drawString(fr, "≡",
+ dragOffsetX + mouseX,
+ dragOffsetY - 1 + mouseY + ySize / 2 - 4, 0xffffff, true
+ );
+ }
+ }
+
+ @Override
+ public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY, MouseEvent mouseEvent) {
+ lastMousePosition = new Pair<>(mouseX, mouseY);
+ if (mouseEvent instanceof MouseEvent.Scroll) {
+ this.dropdownOpen = false;
+ return false;
+ }
+ var click = mouseEvent instanceof MouseEvent.Click ? (MouseEvent.Click) mouseEvent : null;
+ if (click != null &&
+ !click.getMouseState() && !dropdownOpen &&
+ dragStartIndex >= 0 && click.getMouseButton() == 0 &&
+ mouseX >= x + width / 6 + 27 - 3 && mouseX <= x + width / 6 + 27 + 11 + 3 &&
+ mouseY >= y + 45 - 7 - 13 - 3 && mouseY <= y + 45 - 7 - 13 + 14 + 3) {
+ if (canDeleteRightNow()) {
+ activeText.remove(dragStartIndex);
+ saveChanges();
+ }
+ currentDragging = null;
+ dragStartIndex = -1;
+ return false;
+ }
+
+ if (!IMinecraft.instance.isMouseButtonDown(0) || dropdownOpen) {
+ currentDragging = null;
+ dragStartIndex = -1;
+ if (trashHoverTime > 0 && canDeleteRightNow()) trashHoverTime = -System.currentTimeMillis();
+ } else if (currentDragging != null &&
+ mouseX >= x + width / 6 + 27 - 3 && mouseX <= x + width / 6 + 27 + 11 + 3 &&
+ mouseY >= y + 45 - 7 - 13 - 3 && mouseY <= y + 45 - 7 - 13 + 14 + 3) {
+ if (trashHoverTime < 0 && canDeleteRightNow()) trashHoverTime = System.currentTimeMillis();
+ } else if (!canDeleteRightNow()) {
+ trashHoverTime = Long.MAX_VALUE;
+ } else if (trashHoverTime > 0) {
+ trashHoverTime = -System.currentTimeMillis();
+ }
+
+ if (click != null && click.getMouseState()) {
+ int height = getHeight();
+
+ if (dropdownOpen) {
+ List remaining = new ArrayList<>(exampleText.keySet());
+ remaining.removeAll(activeText);
+
+ int dropdownWidth = Math.min(width / 2 - 10, 150);
+ int left = dragOffsetX;
+ int top = dragOffsetY;
+
+ int dropdownHeight = -1 + 12 * remaining.size();
+
+ if (mouseX > left && mouseX < left + dropdownWidth &&
+ mouseY > top && mouseY < top + dropdownHeight) {
+ int dropdownY = -1;
+ for (Object objectIndex : remaining) {
+ if (mouseY < top + dropdownY + 12) {
+ activeText.add(0, objectIndex);
+ saveChanges();
+ if (remaining.size() == 1) dropdownOpen = false;
+ return true;
+ }
+
+ dropdownY += 12;
+ }
+ }
+
+ dropdownOpen = false;
+ return true;
+ }
+
+ if (activeText.size() < exampleText.size() &&
+ mouseX > x + width / 6 - 24 && mouseX < x + width / 6 + 24 &&
+ mouseY > y + 45 - 7 - 14 && mouseY < y + 45 - 7 + 2) {
+ dropdownOpen = true;
+ dragOffsetX = mouseX;
+ dragOffsetY = mouseY;
+ return true;
+ }
+
+ if (click.getMouseButton() == 0 &&
+ mouseX > x + 5 && mouseX < x + width - 5 &&
+ mouseY > y + 45 && mouseY < y + height - 6) {
+ int yOff = 0;
+ int i = 0;
+ for (Object objectIndex : activeText) {
+ String str = getExampleText(objectIndex);
+ int ySize = 10 * str.split("\n").length;
+ if (mouseY < y + 50 + yOff + ySize) {
+ dragOffsetX = x + 10 - mouseX;
+ dragOffsetY = y + 50 + yOff - mouseY;
+
+ currentDragging = objectIndex;
+ dragStartIndex = i;
+ break;
+ }
+ yOff += ySize;
+ i++;
+ }
+ }
+ } else if (mouseEvent instanceof MouseEvent.Move && currentDragging != null) {
+ int yOff = 0;
+ int i = 0;
+ for (Object objectIndex : activeText) {
+ if (dragOffsetY + mouseY + 4 < y + 50 + yOff + 10) {
+ activeText.remove(dragStartIndex);
+ activeText.add(i, currentDragging);
+ saveChanges();
+ dragStartIndex = i;
+ break;
+ }
+ String str = getExampleText(objectIndex);
+ yOff += 10 * str.split("\n").length;
+ i++;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean fulfillsSearch(String word) {
+ if (exampleTextConcat == null) {
+ exampleTextConcat = String.join("", exampleText.values()).toLowerCase(Locale.ROOT);
+ }
+ return super.fulfillsSearch(word) || exampleTextConcat.contains(word);
+ }
+
+ @Override
+ public boolean keyboardInput(KeyboardEvent event) {
+ if (event instanceof KeyboardEvent.KeyPressed) {
+ int key = ((KeyboardEvent.KeyPressed) event).getKeycode();
+ if (key == KeyboardConstants.INSTANCE.getUp() || key == KeyboardConstants.INSTANCE.getDown()) {
+ dropdownOpen = false;
+ }
+ }
+ return super.keyboardInput(event);
+ }
+}
diff --git a/common/src/main/java/io/github/notenoughupdates/moulconfig/internal/TypeUtils.java b/common/src/main/java/io/github/notenoughupdates/moulconfig/internal/TypeUtils.java
index 8b4222f03..1d11cecc2 100644
--- a/common/src/main/java/io/github/notenoughupdates/moulconfig/internal/TypeUtils.java
+++ b/common/src/main/java/io/github/notenoughupdates/moulconfig/internal/TypeUtils.java
@@ -1,5 +1,12 @@
package io.github.notenoughupdates.moulconfig.internal;
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.Arrays;
+
public class TypeUtils {
public static boolean areTypesEquals(Class> a, Class> b) {
return normalizeNative(a) == normalizeNative(b);
@@ -19,4 +26,15 @@ public static Class> normalizeNative(Class> clazz) {
if (clazz == char.class) return Character.class;
return clazz;
}
+
+ public static Class> resolveRawType(Type t) {
+ if (t instanceof Class>) return (Class>) t;
+ if (t instanceof WildcardType) return resolveRawType(((WildcardType) t).getUpperBounds()[0]);
+ if (t instanceof ParameterizedType) return resolveRawType(((ParameterizedType) t).getRawType());
+ if (t instanceof GenericArrayType) {
+ Class> component = resolveRawType(((GenericArrayType) t).getGenericComponentType());
+ return Array.newInstance(component, 0).getClass();
+ }
+ throw new IllegalArgumentException("Could not resolve type " + t + " to a raw type");
+ }
}
diff --git a/common/src/main/java/io/github/notenoughupdates/moulconfig/processor/BuiltinMoulConfigGuis.java b/common/src/main/java/io/github/notenoughupdates/moulconfig/processor/BuiltinMoulConfigGuis.java
index d7cebe878..91307420e 100644
--- a/common/src/main/java/io/github/notenoughupdates/moulconfig/processor/BuiltinMoulConfigGuis.java
+++ b/common/src/main/java/io/github/notenoughupdates/moulconfig/processor/BuiltinMoulConfigGuis.java
@@ -50,6 +50,9 @@ public static void addProcessors(MoulConfigProcessor> processor) {
new GuiOptionEditorInfoText(processedOption, configEditorInfoText.infoTitle()));
processor.registerConfigEditor(ConfigEditorText.class, (processedOption, configEditorText) ->
new GuiOptionEditorText(processedOption));
+ processor.registerConfigEditor(ConfigEditorDraggableList.class, (processedOption, configEditorDraggableList) ->
+ new GuiOptionEditorDraggableList(processedOption, configEditorDraggableList.exampleText(), configEditorDraggableList.allowDeleting(), configEditorDraggableList.requireNonEmpty()));
+
processor.registerConfigEditor(ConfigLink.class, ((option, configLink) -> {
Field field;
try {
diff --git a/legacy/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/GuiOptionEditorDraggableList.java b/legacy/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/GuiOptionEditorDraggableList.java
index a977f0c99..fe0229fab 100644
--- a/legacy/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/GuiOptionEditorDraggableList.java
+++ b/legacy/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/GuiOptionEditorDraggableList.java
@@ -29,6 +29,7 @@
import io.github.notenoughupdates.moulconfig.internal.LerpUtils;
import io.github.notenoughupdates.moulconfig.internal.RenderUtils;
import io.github.notenoughupdates.moulconfig.internal.TextRenderUtils;
+import io.github.notenoughupdates.moulconfig.internal.TypeUtils;
import io.github.notenoughupdates.moulconfig.internal.Warnings;
import io.github.notenoughupdates.moulconfig.processor.ProcessedOption;
import kotlin.Pair;
@@ -84,7 +85,7 @@ public GuiOptionEditorDraggableList(
this.activeText = (List) option.get();
this.requireNonEmpty = requireNonEmpty;
- Type elementType = ((ParameterizedType) option.getType()).getActualTypeArguments()[0];
+ Type elementType = TypeUtils.resolveRawType(((ParameterizedType) option.getType()).getActualTypeArguments()[0]);
if (Enum.class.isAssignableFrom((Class>) elementType)) {
Class extends Enum>> enumType = (Class extends Enum>>) ((ParameterizedType) option.getType()).getActualTypeArguments()[0];
diff --git a/modern/src/main/kotlin/io/github/notenoughupdates/moulconfig/test/TestCategoryA.kt b/modern/src/main/kotlin/io/github/notenoughupdates/moulconfig/test/TestCategoryA.kt
index 74ca5cdc1..78622772a 100644
--- a/modern/src/main/kotlin/io/github/notenoughupdates/moulconfig/test/TestCategoryA.kt
+++ b/modern/src/main/kotlin/io/github/notenoughupdates/moulconfig/test/TestCategoryA.kt
@@ -1,7 +1,10 @@
package io.github.notenoughupdates.moulconfig.test
+import com.google.gson.annotations.Expose
import io.github.notenoughupdates.moulconfig.annotations.*
import io.github.notenoughupdates.moulconfig.observer.Property
+import java.util.*
+import kotlin.collections.ArrayList
class TestCategoryA {
@ConfigOption(name = "Test Option", desc = "Test toggle")
@@ -59,4 +62,32 @@ class TestCategoryA {
@ConfigOption(name = "Text Box", desc = "Lets you put strings.")
@ConfigEditorText
var customText: Property = Property.of("abc")
+
+ @ConfigOption(name = "Draggable List", desc = "§eDrag text to change the order of the list.")
+ @ConfigEditorDraggableList(
+ exampleText = ["abc", "dec", "blah","surel it works really cool and great :))"]
+ )
+ var draggableList: List = ArrayList(mutableListOf(0, 1, 2, 3))
+
+ @Expose
+ @ConfigOption(name = "Enum Draggable List", desc = "Draggable list but doesnt work properly.")
+ @ConfigEditorDraggableList
+ var enumDraggableList: List = ArrayList(
+ Arrays.asList(
+ EnumDraggableList.ONE,
+ EnumDraggableList.THREE,
+ EnumDraggableList.TWO,
+ )
+ )
+
+ enum class EnumDraggableList(private val str: String) {
+ ONE("1"),
+ TWO("too"),
+ THREE("three"),
+ ;
+
+ override fun toString(): String {
+ return str
+ }
+ }
}