diff --git a/src/main/java/dev/isxander/yacl3/gui/SearchFieldWidget.java b/src/main/java/dev/isxander/yacl3/gui/SearchFieldWidget.java index a666886..37adf99 100644 --- a/src/main/java/dev/isxander/yacl3/gui/SearchFieldWidget.java +++ b/src/main/java/dev/isxander/yacl3/gui/SearchFieldWidget.java @@ -14,6 +14,7 @@ public class SearchFieldWidget extends EditBox { private final Consumer updateConsumer; private boolean isEmpty = true; + private boolean doNotUpdate = false; public SearchFieldWidget(YACLScreen yaclScreen, Font font, int x, int y, int width, int height, Component text, Component emptyText, Consumer updateConsumer) { super(font, x, y, width, height, text); @@ -33,6 +34,12 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float del } } + public void setValueDoNotUpdate(String value) { + doNotUpdate = true; + setValue(value); + doNotUpdate = false; + } + private void update(String query) { boolean wasEmpty = isEmpty; isEmpty = query.isEmpty(); @@ -40,6 +47,7 @@ private void update(String query) { if (isEmpty && wasEmpty) return; + if (doNotUpdate) return; updateConsumer.accept(query); } diff --git a/src/main/java/dev/isxander/yacl3/gui/YACLScreen.java b/src/main/java/dev/isxander/yacl3/gui/YACLScreen.java index 8a0f53f..5661f62 100644 --- a/src/main/java/dev/isxander/yacl3/gui/YACLScreen.java +++ b/src/main/java/dev/isxander/yacl3/gui/YACLScreen.java @@ -21,6 +21,8 @@ import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.MultiLineLabel; import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.components.tabs.Tab; import net.minecraft.client.gui.components.tabs.TabManager; import net.minecraft.client.gui.navigation.ScreenRectangle; import net.minecraft.client.gui.screens.Screen; @@ -28,6 +30,7 @@ import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; @@ -56,6 +59,11 @@ public class YACLScreen extends Screen { public ControllerPopupWidget currentPopupController = null; public boolean popupControllerVisible = false; + /** + * The tab where the user started searching + */ + private @Nullable CategoryTab preferredTab = null; + public YACLScreen(YetAnotherConfigLib config, Screen parent) { super(config.title()); this.config = config; @@ -313,6 +321,43 @@ public static void renderMultilineTooltip(GuiGraphics graphics, Font font, Multi } } + public void updateGlobalSearch(String search) { + Tab nextTabWithSearch = null; + if (preferredTab != null) { + preferredTab.optionList.getType().updateSearchQuery(search); + if (preferredTab.hasSearch()) nextTabWithSearch = preferredTab; + } + Tab currentTab = tabNavigationBar.getTabManager().getCurrentTab(); + int cursorPos = currentTab instanceof CategoryTab categoryTab ? categoryTab.searchField.getCursorPosition() : -1; + + for (int i = 0; i < tabNavigationBar.getTabs().size(); i++) { + Tab tab = tabNavigationBar.getTabs().get(i); + if (tab == preferredTab) continue; + if (tab instanceof CategoryTab categoryTab) { + categoryTab.optionList.getType().updateSearchQuery(search); + categoryTab.searchField.setValueDoNotUpdate(search); + if (cursorPos != -1) categoryTab.searchField.setCursorPosition(cursorPos); + if (nextTabWithSearch == null && categoryTab.hasSearch()) { + nextTabWithSearch = categoryTab; + } + } + } + // switch if the next tab is the preferred one or switch if the current tab does not have the search + if (nextTabWithSearch != null && nextTabWithSearch != currentTab && (nextTabWithSearch == preferredTab || !(currentTab instanceof CategoryTab categoryTab && categoryTab.hasSearch()))) { + tabManager.setCurrentTab(nextTabWithSearch, false); + if (nextTabWithSearch instanceof CategoryTab newTab) { + setFocused(newTab.searchField); + } + } + tabNavigationBar.updateTabNames(); + } + + @Override + public void setFocused(@Nullable GuiEventListener focused) { + super.setFocused(focused); + if (focused != null && !(focused instanceof SearchFieldWidget)) preferredTab = null; + } + public static class CategoryTab implements TabExt { private static final ResourceLocation DARKER_BG = YACLPlatform.mcRl("textures/gui/menu_list_background.png"); @@ -367,7 +412,11 @@ public CategoryTab(YACLScreen screen, ConfigCategory category, ScreenRectangle t paddedWidth - 2, 18, Component.translatable("gui.recipebook.search_hint"), Component.translatable("gui.recipebook.search_hint"), - searchQuery -> optionList.getType().updateSearchQuery(searchQuery) + s -> { + if (screen.preferredTab == null) screen.preferredTab = this; + screen.updateGlobalSearch(s); + + } ); this.optionList = YACLSelectionList.asWidget( @@ -389,9 +438,17 @@ public CategoryTab(YACLScreen screen, ConfigCategory category, ScreenRectangle t updateButtons(); } + public boolean hasSearch() { + return optionList.getType().children().stream().anyMatch(o -> o.searchQueryMatches); + } + @Override public Component getTabTitle() { - return category.name(); + MutableComponent copy = category.name().copy(); + if (!hasSearch()) { + copy.withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.STRIKETHROUGH); + } + return copy; } @Override diff --git a/src/main/java/dev/isxander/yacl3/gui/tab/ScrollableNavigationBar.java b/src/main/java/dev/isxander/yacl3/gui/tab/ScrollableNavigationBar.java index 72210b8..3a257d1 100644 --- a/src/main/java/dev/isxander/yacl3/gui/tab/ScrollableNavigationBar.java +++ b/src/main/java/dev/isxander/yacl3/gui/tab/ScrollableNavigationBar.java @@ -155,6 +155,12 @@ protected void ensureVisible(TabButton tabButton) { } } + public void updateTabNames() { + for (TabButton tabButton : accessor.yacl$getTabButtons()) { + tabButton.setMessage(tabButton.tab().getTabTitle()); + } + } + public ImmutableList getTabs() { return accessor.yacl$getTabs(); }