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 index 73a021541..d6278d8a7 100644 --- 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 @@ -25,6 +25,7 @@ import io.github.notenoughupdates.moulconfig.common.text.StructuredText; import io.github.notenoughupdates.moulconfig.gui.GuiComponent; import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext; +import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent; import io.github.notenoughupdates.moulconfig.gui.MouseEvent; import io.github.notenoughupdates.moulconfig.gui.component.*; import io.github.notenoughupdates.moulconfig.internal.*; @@ -332,6 +333,23 @@ private void reorderElements(int width, int mouseX, int mouseY) { GuiComponent makeDropDownOverlay() { return new GuiComponent() { + boolean hasRequestedFocus = false; + List remaining = new ArrayList<>(); + List filteredRemaining = new ArrayList<>(); + String searchText = ""; + + { + recalculateRemaining(); + requestFocus(); + } + + void recalculateRemaining() { + remaining = new ArrayList<>(exampleText.keySet()); + remaining.removeAll(activeText); + filteredRemaining = remaining.stream() + .filter(r -> getExampleText(r).getText().toLowerCase().contains(searchText.toLowerCase())) + .collect(Collectors.toList()); + } @Override public int getWidth() { @@ -340,9 +358,28 @@ public int getWidth() { @Override public int getHeight() { - List remaining = new ArrayList<>(exampleText.keySet()); - remaining.removeAll(activeText); - return -1 + 12 * remaining.size(); + return 11 + 12 * filteredRemaining.size(); + } + + @Override + public boolean keyboardEvent(@NotNull KeyboardEvent event, @NotNull GuiImmediateContext context) { + if (event instanceof KeyboardEvent.CharTyped) { + var typed = (KeyboardEvent.CharTyped) event; + searchText = searchText + typed.getChar(); + recalculateRemaining(); + return true; + } else if (event instanceof KeyboardEvent.KeyPressed) { + var pressed = (KeyboardEvent.KeyPressed) event; + if (pressed.getKeycode() == 259 && pressed.getPressed()) { + // if backspace, remove last character + if (!searchText.isEmpty()) { + searchText = searchText.substring(0, searchText.length() - 1); + recalculateRemaining(); + return true; + } + } + } + return super.keyboardEvent(event, context); } @Override @@ -350,12 +387,11 @@ public boolean mouseEvent(@NotNull MouseEvent mouseEvent, @NotNull GuiImmediateC if (mouseEvent instanceof MouseEvent.Click) { var click = (MouseEvent.Click) mouseEvent; if (click.getMouseState() && context.isHovered()) { - List remaining = new ArrayList<>(exampleText.keySet()); - remaining.removeAll(activeText); - int dropdownY = -1; - for (Object indexObject : remaining) { + int dropdownY = 13; + for (Object indexObject : filteredRemaining) { if (context.translated(0, dropdownY + 3, context.getWidth(), 10).isHovered()) { activeText.add(indexObject); + recalculateRemaining(); return true; } dropdownY += 12; @@ -369,9 +405,11 @@ public boolean mouseEvent(@NotNull MouseEvent mouseEvent, @NotNull GuiImmediateC @Override public void render(@NotNull GuiImmediateContext context) { - List remaining = new ArrayList<>(exampleText.keySet()); - remaining.removeAll(activeText); - if (remaining.isEmpty()) { + if (!hasRequestedFocus) { + hasRequestedFocus = true; + requestFocus(); + } + if (filteredRemaining.isEmpty() && searchText.isEmpty()) { closeOverlay(); return; } @@ -394,9 +432,18 @@ public void render(@NotNull GuiImmediateContext context) { outline ); //Bottom renderContext.drawColoredRect(1, 1, dropdownWidth - 1, dropdownHeight - 1, main); //Middle + renderContext.drawColoredRect(1, 13, dropdownWidth - 1, 14, 0xffd0d0d0); - int dropdownY = -1; - for (Object indexObject : remaining) { + context.getRenderContext().drawStringScaledMaxWidth( + StructuredText.of(searchText), fr, 3, 3, false, + dropdownWidth - 16, 0xffd0d0d0 + ); + if (System.currentTimeMillis() % 1000 > 500) { + int cursorX = 3 + fr.getStringWidth(searchText); + renderContext.drawColoredRect(cursorX, 3, cursorX + 1, 11, 0xffffffff); + } + int dropdownY = 13; + for (Object indexObject : filteredRemaining) { StructuredText str = getExampleText(indexObject); if (str.getText().isEmpty()) { str = StructuredText.of("");