Skip to content

Commit 36891bb

Browse files
committed
1.4.2
1 parent 2ffdf3e commit 36891bb

20 files changed

Lines changed: 72 additions & 71 deletions

changelogs/1.4.2.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
- Improve search performance (even when empty) by a LOT
2+
- API to add listeners before building
13
- Fix cancel/reset button tooltip going off-screen

src/main/java/dev/isxander/yacl/api/Controller.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,5 @@ public interface Controller<T> {
2525
*
2626
* @param screen parent screen
2727
*/
28-
@ApiStatus.Internal
2928
AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension);
3029
}

src/main/java/dev/isxander/yacl/api/Option.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ class Builder<T> {
136136

137137
private final Class<T> typeClass;
138138

139+
private final List<BiConsumer<Option<T>, T>> listeners = new ArrayList<>();
140+
139141
private Builder(Class<T> typeClass) {
140142
this.typeClass = typeClass;
141143
}
@@ -269,6 +271,26 @@ public Builder<T> instant(boolean instant) {
269271
return this;
270272
}
271273

274+
/**
275+
* Adds a listener to the option. Invoked upon changing the pending value.
276+
*
277+
* @see Option#addListener(BiConsumer)
278+
*/
279+
public Builder<T> listener(@NotNull BiConsumer<Option<T>, T> listener) {
280+
this.listeners.add(listener);
281+
return this;
282+
}
283+
284+
/**
285+
* Adds multiple listeners to the option. Invoked upon changing the pending value.
286+
*
287+
* @see Option#addListener(BiConsumer)
288+
*/
289+
public Builder<T> listeners(@NotNull Collection<BiConsumer<Option<T>, T>> listeners) {
290+
this.listeners.addAll(listeners);
291+
return this;
292+
}
293+
272294
/**
273295
* Dictates whether the option should require a restart.
274296
* {@link Option#requiresRestart()}
@@ -299,11 +321,11 @@ public Option<T> build() {
299321
return concatenatedTooltip;
300322
};
301323

302-
OptionImpl<T> option = new OptionImpl<>(name, concatenatedTooltipGetter, controlGetter, binding, available, ImmutableSet.copyOf(flags), typeClass);
303324
if (instant) {
304-
option.addListener((opt, pendingValue) -> opt.applyValue());
325+
listeners.add((opt, pendingValue) -> opt.applyValue());
305326
}
306-
return option;
327+
328+
return new OptionImpl<>(name, concatenatedTooltipGetter, controlGetter, binding, available, ImmutableSet.copyOf(flags), typeClass, listeners);
307329
}
308330
}
309331
}

src/main/java/dev/isxander/yacl/api/OptionGroup.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public Builder option(@NotNull Option<?> option) {
106106
*
107107
* @see OptionGroup#options()
108108
*/
109-
public Builder options(@NotNull Collection<Option<?>> options) {
109+
public Builder options(@NotNull Collection<? extends Option<?>> options) {
110110
Validate.notEmpty(options, "`options` must not be empty");
111111

112112
this.options.addAll(options);

src/main/java/dev/isxander/yacl/gui/OptionListWidget.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,16 @@ public class OptionEntry extends Entry {
233233
public final AbstractWidget widget;
234234
private final Supplier<Boolean> viewableSupplier;
235235

236+
private final String categoryName;
237+
private final String groupName;
238+
236239
private OptionEntry(ConfigCategory category, OptionGroup group, AbstractWidget widget, Supplier<Boolean> viewableSupplier) {
237240
this.category = category;
238241
this.group = group;
239242
this.widget = widget;
240243
this.viewableSupplier = viewableSupplier;
244+
this.categoryName = category.name().getString().toLowerCase();
245+
this.groupName = group.name().getString().toLowerCase();
241246
}
242247

243248
@Override
@@ -269,7 +274,12 @@ public boolean charTyped(char chr, int modifiers) {
269274

270275
@Override
271276
public boolean isViewable() {
272-
return viewableSupplier.get() && yaclScreen.searchFieldWidget.matches(this, singleCategory);
277+
String query = yaclScreen.searchFieldWidget.getText();
278+
return viewableSupplier.get()
279+
&& (yaclScreen.searchFieldWidget.isEmpty()
280+
|| (!singleCategory && categoryName.contains(query))
281+
|| groupName.contains(query)
282+
|| widget.matchesSearch(query));
273283
}
274284

275285
@Override
@@ -353,7 +363,7 @@ public void setOptionEntries(List<OptionEntry> optionEntries) {
353363

354364
@Override
355365
public boolean isViewable() {
356-
return yaclScreen.searchFieldWidget.getText().isEmpty() || optionEntries.stream().anyMatch(OptionEntry::isViewable);
366+
return yaclScreen.searchFieldWidget.isEmpty() || optionEntries.stream().anyMatch(OptionEntry::isViewable);
357367
}
358368

359369
@Override

src/main/java/dev/isxander/yacl/gui/SearchFieldWidget.java

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package dev.isxander.yacl.gui;
22

3-
import dev.isxander.yacl.api.ConfigCategory;
4-
import dev.isxander.yacl.api.OptionGroup;
53
import net.minecraft.client.font.TextRenderer;
64
import net.minecraft.client.gui.widget.TextFieldWidget;
75
import net.minecraft.client.util.math.MatrixStack;
@@ -12,8 +10,11 @@ public class SearchFieldWidget extends TextFieldWidget {
1210
private final YACLScreen yaclScreen;
1311
private final TextRenderer textRenderer;
1412

13+
private boolean isEmpty = true;
14+
1515
public SearchFieldWidget(YACLScreen yaclScreen, TextRenderer textRenderer, int x, int y, int width, int height, Text text, Text emptyText) {
1616
super(textRenderer, x, y, width, height, text);
17+
setTextPredicate(string -> !string.endsWith(" ") && !string.startsWith(" "));
1718
this.yaclScreen = yaclScreen;
1819
this.textRenderer = textRenderer;
1920
this.emptyText = emptyText;
@@ -22,48 +23,41 @@ public SearchFieldWidget(YACLScreen yaclScreen, TextRenderer textRenderer, int x
2223
@Override
2324
public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) {
2425
super.renderButton(matrices, mouseX, mouseY, delta);
25-
if (isVisible() && getText().isEmpty()) {
26+
if (isVisible() && isEmpty()) {
2627
textRenderer.drawWithShadow(matrices, emptyText, x + 4, this.y + (this.height - 8) / 2f, 0x707070);
2728
}
2829
}
2930

3031
@Override
3132
public void write(String text) {
32-
yaclScreen.optionList.setScrollAmount(0);
33-
yaclScreen.categoryList.setScrollAmount(0);
34-
for (OptionListWidget.Entry entry : yaclScreen.optionList.children()) {
35-
if (entry instanceof OptionListWidget.GroupSeparatorEntry groupSeparatorEntry) {
36-
groupSeparatorEntry.setExpanded(true);
37-
}
38-
}
33+
update();
3934

4035
super.write(text);
36+
37+
isEmpty = getText().isEmpty();
4138
}
4239

4340
@Override
4441
public void eraseCharacters(int characterOffset) {
45-
yaclScreen.optionList.setScrollAmount(0);
42+
update();
4643

4744
super.eraseCharacters(characterOffset);
48-
}
4945

50-
public boolean matches(OptionListWidget.OptionEntry optionEntry, boolean ignoreCategory) {
51-
return (matchesCategory(optionEntry.category) && !ignoreCategory) || matchesGroup(optionEntry.group) || matchesWidget(optionEntry.widget);
46+
isEmpty = getText().isEmpty();
5247
}
5348

54-
public boolean matchesCategory(ConfigCategory category) {
55-
return category.name().getString().toLowerCase().contains(getText().trim());
56-
}
57-
58-
public boolean matchesGroup(OptionGroup group) {
59-
if (group.isRoot())
60-
return false;
61-
62-
return group.name().getString().toLowerCase().contains(getText().trim());
49+
private void update() {
50+
yaclScreen.optionList.setScrollAmount(0);
51+
yaclScreen.categoryList.setScrollAmount(0);
52+
for (OptionListWidget.Entry entry : yaclScreen.optionList.children()) {
53+
if (entry instanceof OptionListWidget.GroupSeparatorEntry groupSeparatorEntry) {
54+
groupSeparatorEntry.setExpanded(true);
55+
}
56+
}
6357
}
6458

65-
public boolean matchesWidget(AbstractWidget widget) {
66-
return widget.matchesSearch(getText().trim());
59+
public boolean isEmpty() {
60+
return isEmpty;
6761
}
6862

6963
public Text getEmptyText() {

src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import dev.isxander.yacl.gui.AbstractWidget;
77
import dev.isxander.yacl.gui.YACLScreen;
88
import net.minecraft.text.Text;
9-
import org.jetbrains.annotations.ApiStatus;
109
import org.lwjgl.glfw.GLFW;
1110

1211
import java.util.function.BiConsumer;
@@ -67,10 +66,12 @@ public AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widget
6766
return new ActionControllerElement(this, screen, widgetDimension);
6867
}
6968

70-
@ApiStatus.Internal
7169
public static class ActionControllerElement extends ControllerWidget<ActionController> {
70+
private final String buttonString;
71+
7272
public ActionControllerElement(ActionController control, YACLScreen screen, Dimension<Integer> dim) {
7373
super(control, screen, dim);
74+
buttonString = control.formatValue().getString().toLowerCase();
7475
}
7576

7677
public void executeAction() {
@@ -108,7 +109,7 @@ protected int getHoveredControlWidth() {
108109

109110
@Override
110111
public boolean matchesSearch(String query) {
111-
return super.matchesSearch(query) || getValueText().getString().toLowerCase().contains(query);
112+
return super.matchesSearch(query) || buttonString.contains(query);
112113
}
113114
}
114115
}

src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ public AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widget
102102
return new BooleanControllerElement(this, screen, widgetDimension);
103103
}
104104

105-
@ApiStatus.Internal
106105
public static class BooleanControllerElement extends ControllerWidget<BooleanController> {
107106
private BooleanControllerElement(BooleanController control, YACLScreen screen, Dimension<Integer> dim) {
108107
super(control, screen, dim);

src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract
1818
protected boolean focused = false;
1919
protected boolean hovered = false;
2020

21+
protected final String optionName;
22+
2123
public ControllerWidget(T control, YACLScreen screen, Dimension<Integer> dim) {
2224
super(dim);
2325
this.control = control;
2426
this.screen = screen;
2527
control.option().addListener((opt, pending) -> updateTooltip());
2628
updateTooltip();
29+
this.optionName = control.option().name().getString().toLowerCase();
2730
}
2831

2932
@Override
@@ -145,7 +148,7 @@ public void unfocus() {
145148

146149
@Override
147150
public boolean matchesSearch(String query) {
148-
return control.option().name().getString().toLowerCase().contains(query.toLowerCase());
151+
return optionName.contains(query.toLowerCase());
149152
}
150153

151154
@Override

src/main/java/dev/isxander/yacl/gui/controllers/EnumController.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ public AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widget
7777
return new EnumControllerElement<>(this, screen, widgetDimension, option().typeClass().getEnumConstants());
7878
}
7979

80-
@ApiStatus.Internal
8180
public static class EnumControllerElement<T extends Enum<T>> extends ControllerWidget<EnumController<T>> {
8281
private final T[] values;
8382

0 commit comments

Comments
 (0)