From 5ae0da6bdb6f44948da80ae95c5ef1b02f477350 Mon Sep 17 00:00:00 2001 From: xander Date: Sat, 10 Sep 2022 19:09:03 +0100 Subject: search field --- .../java/dev/isxander/yacl/gui/AbstractWidget.java | 4 ++ .../dev/isxander/yacl/gui/OptionListWidget.java | 43 +++++++++++++++----- .../dev/isxander/yacl/gui/SearchFieldWidget.java | 47 ++++++++++++++++++++++ .../java/dev/isxander/yacl/gui/YACLScreen.java | 13 ++++-- .../yacl/gui/controllers/ControllerWidget.java | 5 +++ .../yacl/gui/controllers/LabelController.java | 5 +++ .../assets/yet-another-config-lib/lang/en_us.json | 1 + 7 files changed, 106 insertions(+), 12 deletions(-) create mode 100644 src/main/java/dev/isxander/yacl/gui/SearchFieldWidget.java (limited to 'src/main') diff --git a/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java b/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java index d943a86..0886589 100644 --- a/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java @@ -43,6 +43,10 @@ public abstract class AbstractWidget implements Element, Drawable, Selectable { } + public boolean matchesSearch(String query) { + return true; + } + @Override public void appendNarrations(NarrationMessageBuilder builder) { diff --git a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java b/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java index f243778..3afadf3 100644 --- a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java @@ -22,29 +22,40 @@ import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.function.Supplier; public class OptionListWidget extends ElementListWidget { + private final YACLScreen yaclScreen; public OptionListWidget(ConfigCategory category, YACLScreen screen, MinecraftClient client, int width, int height) { super(client, width / 3 * 2, height, 0, height, 22); + this.yaclScreen = screen; left = width - this.width; right = width; for (OptionGroup group : category.groups()) { Supplier viewableSupplier; + GroupSeparatorEntry groupSeparatorEntry = null; if (!group.isRoot()) { - GroupSeparatorEntry groupSeparatorEntry = new GroupSeparatorEntry(group, screen); + groupSeparatorEntry = new GroupSeparatorEntry(group, screen); viewableSupplier = groupSeparatorEntry::isExpanded; addEntry(groupSeparatorEntry); } else { viewableSupplier = () -> true; } + List optionEntries = new ArrayList<>(); for (Option option : group.options()) { - addEntry(new OptionEntry(option.controller().provideWidget(screen, Dimension.ofInt(getRowLeft(), 0, getRowWidth(), 20)), viewableSupplier)); + OptionEntry entry = new OptionEntry(option.controller().provideWidget(screen, Dimension.ofInt(getRowLeft(), 0, getRowWidth(), 20)), viewableSupplier); + addEntry(entry); + optionEntries.add(entry); + } + + if (groupSeparatorEntry != null) { + groupSeparatorEntry.setOptionEntries(optionEntries); } } } @@ -219,7 +230,7 @@ public class OptionListWidget extends ElementListWidget @Override public boolean isViewable() { - return viewableSupplier.get(); + return viewableSupplier.get() && widget.matchesSearch(yaclScreen.searchFieldWidget.getText()); } @Override @@ -238,7 +249,7 @@ public class OptionListWidget extends ElementListWidget } } - private class GroupSeparatorEntry extends Entry { + public class GroupSeparatorEntry extends Entry { private final OptionGroup group; private final MultilineText wrappedName; private final List wrappedTooltip; @@ -253,15 +264,16 @@ public class OptionListWidget extends ElementListWidget private boolean groupExpanded; - public GroupSeparatorEntry(OptionGroup group, Screen screen) { + private List optionEntries; + + private GroupSeparatorEntry(OptionGroup group, Screen screen) { this.group = group; this.screen = screen; this.wrappedName = MultilineText.create(textRenderer, group.name(), getRowWidth() - 45); this.wrappedTooltip = textRenderer.wrapLines(group.tooltip(), screen.width / 2); this.groupExpanded = !group.collapsed(); this.expandMinimizeButton = new LowProfileButtonWidget(0, 0, 20, 20, Text.empty(), btn -> { - groupExpanded = !groupExpanded; - updateExpandMinimizeText(); + setExpanded(!isExpanded()); }); updateExpandMinimizeText(); } @@ -292,14 +304,27 @@ public class OptionListWidget extends ElementListWidget return groupExpanded; } + public void setExpanded(boolean expanded) { + this.groupExpanded = expanded; + updateExpandMinimizeText(); + } + private void updateExpandMinimizeText() { -// expandMinimizeButton.setMessage(Text.of(isExpanded() ? "\u25BC" : "\u25C0")); expandMinimizeButton.setMessage(Text.of(isExpanded() ? "\u25BC" : "\u25B6")); } + public void setOptionEntries(List optionEntries) { + this.optionEntries = optionEntries; + } + + @Override + public boolean isViewable() { + return yaclScreen.searchFieldWidget.getText().isEmpty() || optionEntries.stream().anyMatch(OptionEntry::isViewable); + } + @Override public int getItemHeight() { - return wrappedName.count() * textRenderer.fontHeight + getYPadding() * 2; + return Math.max(wrappedName.count(), 1) * textRenderer.fontHeight + getYPadding() * 2; } private int getYPadding() { diff --git a/src/main/java/dev/isxander/yacl/gui/SearchFieldWidget.java b/src/main/java/dev/isxander/yacl/gui/SearchFieldWidget.java new file mode 100644 index 0000000..fedebdb --- /dev/null +++ b/src/main/java/dev/isxander/yacl/gui/SearchFieldWidget.java @@ -0,0 +1,47 @@ +package dev.isxander.yacl.gui; + +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; + +public class SearchFieldWidget extends TextFieldWidget { + private Text emptyText; + private final YACLScreen yaclScreen; + private final TextRenderer textRenderer; + + public SearchFieldWidget(YACLScreen yaclScreen, TextRenderer textRenderer, int x, int y, int width, int height, Text text, Text emptyText) { + super(textRenderer, x, y, width, height, text); + this.yaclScreen = yaclScreen; + this.textRenderer = textRenderer; + this.emptyText = emptyText; + } + + @Override + public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { + super.renderButton(matrices, mouseX, mouseY, delta); + if (isVisible() && getText().isEmpty()) { + textRenderer.drawWithShadow(matrices, emptyText, x + 4, this.y + (this.height - 8) / 2f, 0x707070); + } + } + + @Override + public void write(String text) { + yaclScreen.optionList.setScrollAmount(0); + for (OptionListWidget.Entry entry : yaclScreen.optionList.children()) { + if (entry instanceof OptionListWidget.GroupSeparatorEntry groupSeparatorEntry) { + groupSeparatorEntry.setExpanded(true); + } + } + + super.write(text); + } + + public Text getEmptyText() { + return emptyText; + } + + public void setEmptyText(Text emptyText) { + this.emptyText = emptyText; + } +} diff --git a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java b/src/main/java/dev/isxander/yacl/gui/YACLScreen.java index 01d9bcb..adb6007 100644 --- a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java +++ b/src/main/java/dev/isxander/yacl/gui/YACLScreen.java @@ -8,7 +8,6 @@ import dev.isxander.yacl.api.utils.OptionUtils; import dev.isxander.yacl.impl.YACLConstants; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -26,6 +25,7 @@ public class YACLScreen extends Screen { public OptionListWidget optionList; public final List categoryButtons; public TooltipButtonWidget finishedSaveButton, cancelResetButton, undoButton; + public SearchFieldWidget searchFieldWidget; public Text saveButtonMessage; public Text saveButtonTooltipMessage; @@ -46,7 +46,8 @@ public class YACLScreen extends Screen { int columnWidth = width / 3; int padding = columnWidth / 20; columnWidth = Math.min(columnWidth, 400); - Dimension categoryDim = Dimension.ofInt(width / 3 / 2, padding, columnWidth - padding * 2, 20); + int paddedWidth = columnWidth - padding * 2; + Dimension categoryDim = Dimension.ofInt(width / 3 / 2, padding, paddedWidth, 20); int idx = 0; for (ConfigCategory category : config.categories()) { CategoryWidget categoryWidget = new CategoryWidget( @@ -64,7 +65,9 @@ public class YACLScreen extends Screen { categoryDim.move(0, 21); } - Dimension actionDim = Dimension.ofInt(width / 3 / 2, height - padding - 20, columnWidth - padding * 2, 20); + searchFieldWidget = new SearchFieldWidget(this, textRenderer, width / 3 / 2 - paddedWidth / 2 + 1, height - 71, paddedWidth - 2, 18, Text.translatable("yacl.gui.search"), Text.translatable("yacl.gui.search")); + + Dimension actionDim = Dimension.ofInt(width / 3 / 2, height - padding - 20, paddedWidth, 20); finishedSaveButton = new TooltipButtonWidget(this, actionDim.x() - actionDim.width() / 2, actionDim.y(), actionDim.width(), actionDim.height(), Text.empty(), Text.empty(), (btn) -> { saveButtonMessage = null; @@ -103,6 +106,7 @@ public class YACLScreen extends Screen { }); updateActionAvailability(); + addDrawableChild(searchFieldWidget); addDrawableChild(cancelResetButton); addDrawableChild(undoButton); addDrawableChild(finishedSaveButton); @@ -121,6 +125,7 @@ public class YACLScreen extends Screen { super.render(matrices, mouseX, mouseY, delta); optionList.render(matrices, mouseX, mouseY, delta); + searchFieldWidget.render(matrices, mouseX, mouseY, delta); for (Element child : children()) { if (child instanceof TooltipButtonWidget tooltipButtonWidget) { @@ -164,6 +169,8 @@ public class YACLScreen extends Screen { @Override public void tick() { + searchFieldWidget.tick(); + updateActionAvailability(); if (saveButtonMessage != null) { diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java b/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java index 29722e1..498ecdd 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java @@ -138,6 +138,11 @@ public abstract class ControllerWidget> extends Abstract this.focused = false; } + @Override + public boolean matchesSearch(String query) { + return control.option().name().getString().toLowerCase().contains(query.toLowerCase()); + } + @Override public SelectionType getType() { return focused ? SelectionType.FOCUSED : isHovered() ? SelectionType.HOVERED : SelectionType.NONE; diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java b/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java index 13687e0..33ca176 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java @@ -68,5 +68,10 @@ public class LabelController implements Controller { wrappedText = MultilineText.create(textRenderer, formatValue(), dim.width()); dim.setHeight(wrappedText.count() * textRenderer.fontHeight + getYPadding() * 2); } + + @Override + public boolean matchesSearch(String query) { + return formatValue().getString().toLowerCase().contains(query.toLowerCase()); + } } } diff --git a/src/main/resources/assets/yet-another-config-lib/lang/en_us.json b/src/main/resources/assets/yet-another-config-lib/lang/en_us.json index 17972a1..1c47579 100644 --- a/src/main/resources/assets/yet-another-config-lib/lang/en_us.json +++ b/src/main/resources/assets/yet-another-config-lib/lang/en_us.json @@ -15,6 +15,7 @@ "yacl.gui.fail_apply.tooltip": "There was an error and the changes couldn't be applied.", "yacl.gui.save_before_exit": "Save before exiting!", "yacl.gui.save_before_exit.tooltip": "Save or cancel to exit the GUI.", + "yacl.gui.search": "Search", "yacl.restart.title": "Config requires restart!", "yacl.restart.message": "One or more options needs you to restart the game to apply the changes.", -- cgit