feat: search filter for options toggle list

This commit is contained in:
trafficlunar 2025-10-15 22:30:56 +01:00
parent c5e5bb46e4
commit 226a43c8dd
6 changed files with 49 additions and 23 deletions

View file

@ -10,6 +10,7 @@ import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.components.CycleButton;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.narration.NarratableEntry;
@ -25,18 +26,37 @@ import java.util.stream.Stream;
public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggleList.Entry> { public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggleList.Entry> {
private final String profileName; private final String profileName;
private final ProfileConfiguration profileConfiguration; private final ProfileConfiguration profileConfiguration;
private final EditBox searchBox;
private final List<OptionEntry> allEntries = new ArrayList<>();
public OptionsToggleList(OptionsToggleScreen optionsToggleScreen, Minecraft minecraft, String profileName, ProfileConfiguration profileConfiguration) { public OptionsToggleList(OptionsToggleScreen optionsToggleScreen, Minecraft minecraft, String profileName, ProfileConfiguration profileConfiguration, EditBox searchBox) {
super(minecraft, optionsToggleScreen.width, optionsToggleScreen.layout.getContentHeight(), optionsToggleScreen.layout.getHeaderHeight(), 20); super(minecraft, optionsToggleScreen.width, optionsToggleScreen.layout.getContentHeight(), optionsToggleScreen.layout.getHeaderHeight(), 20);
this.profileConfiguration = profileConfiguration; this.profileConfiguration = profileConfiguration;
this.profileName = profileName; this.profileName = profileName;
this.searchBox = searchBox;
this.searchBox.setResponder(this::filterEntries);
refreshEntries(false, false); refreshEntries(false, false);
} }
private void filterEntries(String searchText) {
this.clearEntries();
if (searchText.isEmpty()) {
allEntries.forEach(this::addEntry);
return;
}
String filter = searchText.toLowerCase();
allEntries.stream()
.filter(entry -> entry.key.toLowerCase().contains(filter))
.forEach(this::addEntry);
}
// If overriding boolean is set to true then this function will set every option in the list to overrideToggle (false or true) // If overriding boolean is set to true then this function will set every option in the list to overrideToggle (false or true)
public void refreshEntries(boolean overriding, boolean overrideToggle) { public void refreshEntries(boolean overriding, boolean overrideToggle) {
this.clearEntries(); allEntries.clear();
Path profile = Profiles.PROFILES_DIRECTORY.resolve(profileName); Path profile = Profiles.PROFILES_DIRECTORY.resolve(profileName);
Path optionsFile = profile.resolve("options.txt"); Path optionsFile = profile.resolve("options.txt");
@ -60,14 +80,16 @@ public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggl
} }
// Add entry with option key and value and if the key is in the profile configuration // Add entry with option key and value and if the key is in the profile configuration
this.addEntry(new OptionEntry(option[0], option[1], profileConfiguration.getOptionsToLoad().contains(option[0]))); allEntries.add(new OptionEntry(option[0], option[1], profileConfiguration.getOptionsToLoad().contains(option[0])));
} else { } else {
this.addEntry(new OptionEntry(option[0], "", profileConfiguration.getOptionsToLoad().contains(option[0]))); allEntries.add(new OptionEntry(option[0], "", profileConfiguration.getOptionsToLoad().contains(option[0])));
} }
}); });
} catch (IOException e) { } catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when listing options", e); OptionsProfilesMod.LOGGER.error("An error occurred when listing options", e);
} }
filterEntries(searchBox.getValue());
} }
protected int scrollBarX() { protected int scrollBarX() {
@ -79,10 +101,12 @@ public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggl
} }
public class OptionEntry extends Entry { public class OptionEntry extends Entry {
private final String key;
private final Component optionKey; private final Component optionKey;
private final CycleButton<Boolean> toggleButton; private final CycleButton<Boolean> toggleButton;
OptionEntry(String optionKey, String optionValue, boolean toggled) { OptionEntry(String optionKey, String optionValue, boolean toggled) {
this.key = optionKey;
this.optionKey = Component.literal(optionKey); this.optionKey = Component.literal(optionKey);
this.toggleButton = CycleButton.onOffBuilder(toggled).displayOnlyValue().create(0, 0, 44, 20, Component.empty(), (button, boolean_) -> { this.toggleButton = CycleButton.onOffBuilder(toggled).displayOnlyValue().create(0, 0, 44, 20, Component.empty(), (button, boolean_) -> {

View file

@ -1,18 +1,22 @@
package net.trafficlunar.optionsprofiles.gui; package net.trafficlunar.optionsprofiles.gui;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.StringWidget;
import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.options.OptionsSubScreen; import net.minecraft.client.gui.screens.options.OptionsSubScreen;
import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
public class OptionsToggleScreen extends OptionsSubScreen { public class OptionsToggleScreen extends OptionsSubScreen {
private final Component profileName; private final Component profileName;
private final ProfileConfiguration profileConfiguration; private final ProfileConfiguration profileConfiguration;
private OptionsToggleList optionsToggleList; private OptionsToggleList optionsToggleList;
private EditBox searchBox;
protected OptionsToggleScreen(Screen lastScreen, Component profileName, ProfileConfiguration profileConfiguration) { protected OptionsToggleScreen(Screen lastScreen, Component profileName, ProfileConfiguration profileConfiguration) {
super(lastScreen, null, Component.literal(Component.translatable("gui.optionsprofiles.options-toggle").append(": ").getString() + profileName.getString())); super(lastScreen, null, Component.literal(Component.translatable("gui.optionsprofiles.options-toggle").append(": ").getString() + profileName.getString()));
@ -20,11 +24,22 @@ public class OptionsToggleScreen extends OptionsSubScreen {
this.profileConfiguration = profileConfiguration; this.profileConfiguration = profileConfiguration;
} }
protected void init() {
this.searchBox = new EditBox(this.minecraft.font, 0, 0, 200, 20, Component.empty());
this.searchBox.setHint(Component.translatable("gui.optionsprofiles.options-search-hint"));
super.init();
}
protected void addTitle() {
this.layout.addToHeader(new StringWidget(this.title, this.font), (settings) -> settings.alignVerticallyTop().paddingTop(6));
this.layout.addToHeader(this.searchBox, (settings) -> settings.alignVerticallyBottom().padding(4));
}
protected void addOptions() {} protected void addOptions() {}
protected void addContents() { protected void addContents() {
this.layout.setHeaderHeight(24); this.layout.setHeaderHeight(42);
this.optionsToggleList = this.layout.addToContents(new OptionsToggleList(this, this.minecraft, profileName.getString(), this.profileConfiguration)); this.optionsToggleList = this.layout.addToContents(new OptionsToggleList(this, this.minecraft, profileName.getString(), this.profileConfiguration, this.searchBox));
} }
protected void addFooter() { protected void addFooter() {

View file

@ -50,12 +50,6 @@ public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.Prof
} catch (Exception e) { } catch (Exception e) {
OptionsProfilesMod.LOGGER.error("An error occurred when listing profiles", e); OptionsProfilesMod.LOGGER.error("An error occurred when listing profiles", e);
} }
checkEntriesLoaded();
}
public void checkEntriesLoaded() {
this.children().forEach(ProfileEntry::checkLoaded);
} }
protected int scrollBarX() { protected int scrollBarX() {
@ -85,9 +79,6 @@ public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.Prof
(button) -> { (button) -> {
Profiles.loadProfile(profileName.getString()); Profiles.loadProfile(profileName.getString());
OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Loaded through button", profileName); OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Loaded through button", profileName);
ProfilesList.this.checkEntriesLoaded();
button.active = false;
}) })
.size(75, 20) .size(75, 20)
.build(); .build();
@ -116,9 +107,5 @@ public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.Prof
public List<? extends NarratableEntry> narratables() { public List<? extends NarratableEntry> narratables() {
return ImmutableList.of(this.editButton, this.loadButton); return ImmutableList.of(this.editButton, this.loadButton);
} }
protected void checkLoaded() {
this.loadButton.active = !Profiles.isProfileLoaded(profileName.getString());
}
} }
} }

View file

@ -29,8 +29,6 @@ public class Profiles {
public static final Path IRIS_OPTIONS_FILE = Paths.get("config/iris.properties"); public static final Path IRIS_OPTIONS_FILE = Paths.get("config/iris.properties");
public static final Path DISTANT_HORIZONS_OPTIONS_FILE = Paths.get("config/DistantHorizons.toml"); public static final Path DISTANT_HORIZONS_OPTIONS_FILE = Paths.get("config/DistantHorizons.toml");
private static final Minecraft minecraft = Minecraft.getInstance();
public static void createProfile() { public static void createProfile() {
String profileName = "Profile 1"; String profileName = "Profile 1";
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
@ -269,6 +267,7 @@ public class Profiles {
} }
// Reload Minecraft options // Reload Minecraft options
Minecraft minecraft = Minecraft.getInstance();
minecraft.options.load(); minecraft.options.load();
if (ProfileConfiguration.get(profileName).getOptionsToLoad().contains("resourcePacks")) { if (ProfileConfiguration.get(profileName).getOptionsToLoad().contains("resourcePacks")) {

View file

@ -19,6 +19,7 @@
"gui.optionsprofiles.load-on-startup": "Load on startup", "gui.optionsprofiles.load-on-startup": "Load on startup",
"gui.optionsprofiles.options-toggle": "Select options to toggle", "gui.optionsprofiles.options-toggle": "Select options to toggle",
"gui.optionsprofiles.options-search-hint": "Search options...",
"gui.optionsprofiles.options-toggle.tooltip": "Select the options you want to load in this profile", "gui.optionsprofiles.options-toggle.tooltip": "Select the options you want to load in this profile",
"gui.optionsprofiles.all-on": "All ON", "gui.optionsprofiles.all-on": "All ON",
"gui.optionsprofiles.all-off": "All OFF", "gui.optionsprofiles.all-off": "All OFF",

View file

@ -11,4 +11,4 @@ include("common")
include("fabric") include("fabric")
include("neoforge") include("neoforge")
rootProject.name = "optionsprofiles-v1.4.3-1.21.9" rootProject.name = "optionsprofiles-v1.4.3-1.21.6"