diff options
author | Xander <xander@isxander.dev> | 2022-12-11 19:31:56 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-11 19:31:56 +0000 |
commit | dd65110f60aa3e32c2970863a06a7682520cce5e (patch) | |
tree | 44612c6aa85374efa639462592ae706fb93f2575 /src/client/java/dev/isxander/yacl/gui | |
parent | b890c2f0eec3627e552f1c6cfc846c8a55663243 (diff) | |
download | YetAnotherConfigLib-dd65110f60aa3e32c2970863a06a7682520cce5e.tar.gz YetAnotherConfigLib-dd65110f60aa3e32c2970863a06a7682520cce5e.tar.bz2 YetAnotherConfigLib-dd65110f60aa3e32c2970863a06a7682520cce5e.zip |
[Feature] Lists (#40)
Diffstat (limited to 'src/client/java/dev/isxander/yacl/gui')
10 files changed, 341 insertions, 50 deletions
diff --git a/src/client/java/dev/isxander/yacl/gui/CategoryListWidget.java b/src/client/java/dev/isxander/yacl/gui/CategoryListWidget.java index e97f46c..71a8e4e 100644 --- a/src/client/java/dev/isxander/yacl/gui/CategoryListWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/CategoryListWidget.java @@ -32,12 +32,6 @@ public class CategoryListWidget extends ElementListWidgetExt<CategoryListWidget. RenderSystem.disableScissor(); } - public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { - for (CategoryEntry entry : children()) { - entry.postRender(matrices, mouseX, mouseY, delta); - } - } - @Override public int getRowWidth() { return Math.min(width - width / 10, 396); diff --git a/src/client/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java b/src/client/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java index 9fa01a7..36e0852 100644 --- a/src/client/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java @@ -19,7 +19,7 @@ public class LowProfileButtonWidget extends ButtonWidget { @Override public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { - if (!isHovered()) { + if (!isHovered() || !active) { int j = this.active ? 0xFFFFFF : 0xA0A0A0; drawCenteredText(matrices, MinecraftClient.getInstance().textRenderer, this.getMessage(), this.getX() + this.width / 2, this.getY() + (this.height - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); } else { diff --git a/src/client/java/dev/isxander/yacl/gui/OptionListWidget.java b/src/client/java/dev/isxander/yacl/gui/OptionListWidget.java index 976d796..8284b0e 100644 --- a/src/client/java/dev/isxander/yacl/gui/OptionListWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/OptionListWidget.java @@ -1,10 +1,9 @@ package dev.isxander.yacl.gui; import com.google.common.collect.ImmutableList; -import dev.isxander.yacl.api.ConfigCategory; -import dev.isxander.yacl.api.Option; -import dev.isxander.yacl.api.OptionGroup; +import dev.isxander.yacl.api.*; import dev.isxander.yacl.api.utils.Dimension; +import dev.isxander.yacl.gui.controllers.ListEntryWidget; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.MultilineText; import net.minecraft.client.font.TextRenderer; @@ -13,14 +12,11 @@ import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.screen.narration.NarrationPart; -import net.minecraft.client.gui.widget.ElementListWidget; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; -import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.function.Supplier; public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entry> { private final YACLScreen yaclScreen; @@ -33,6 +29,14 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr this.yaclScreen = screen; refreshOptions(); + + for (ConfigCategory category : screen.config.categories()) { + for (OptionGroup group : category.groups()) { + if (group instanceof ListOption<?> listOption) { + listOption.addRefreshListener(() -> refreshListEntries(listOption, category)); + } + } + } } public void refreshOptions() { @@ -40,6 +44,7 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr List<ConfigCategory> categories = new ArrayList<>(); if (yaclScreen.getCurrentCategoryIdx() == -1) { + // -1 = no category, search in progress, so use all categories for search categories.addAll(yaclScreen.config.categories()); } else { categories.add(yaclScreen.config.categories().get(yaclScreen.getCurrentCategoryIdx())); @@ -48,19 +53,19 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr for (ConfigCategory category : categories) { for (OptionGroup group : category.groups()) { - Supplier<Boolean> viewableSupplier; - GroupSeparatorEntry groupSeparatorEntry = null; + GroupSeparatorEntry groupSeparatorEntry; if (!group.isRoot()) { - groupSeparatorEntry = new GroupSeparatorEntry(group, yaclScreen); - viewableSupplier = groupSeparatorEntry::isExpanded; + groupSeparatorEntry = group instanceof ListOption<?> listOption + ? new ListGroupSeparatorEntry(listOption, yaclScreen) + : new GroupSeparatorEntry(group, yaclScreen); addEntry(groupSeparatorEntry); } else { - viewableSupplier = () -> true; + groupSeparatorEntry = null; } List<OptionEntry> optionEntries = new ArrayList<>(); for (Option<?> option : group.options()) { - OptionEntry entry = new OptionEntry(option, category, group, option.controller().provideWidget(yaclScreen, Dimension.ofInt(getRowLeft(), 0, getRowWidth(), 20)), viewableSupplier); + OptionEntry entry = new OptionEntry(option, category, group, groupSeparatorEntry, option.controller().provideWidget(yaclScreen, getDefaultEntryPosition())); addEntry(entry); optionEntries.add(entry); } @@ -76,6 +81,30 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr resetSmoothScrolling(); } + private void refreshListEntries(ListOption<?> listOption, ConfigCategory category) { + // find group separator for group + GroupSeparatorEntry groupSeparator = super.children().stream().filter(e -> e instanceof GroupSeparatorEntry gs && gs.group == listOption).map(GroupSeparatorEntry.class::cast).findAny().orElse(null); + + if (groupSeparator == null) + return; + + for (OptionEntry entry : groupSeparator.optionEntries) + super.removeEntry(entry); + + groupSeparator.optionEntries.clear(); + Entry lastEntry = groupSeparator; + for (ListOptionEntry<?> listOptionEntry : listOption.options()) { + OptionEntry optionEntry = new OptionEntry(listOptionEntry, category, listOption, groupSeparator, listOptionEntry.controller().provideWidget(yaclScreen, getDefaultEntryPosition())); + addEntryBelow(lastEntry, optionEntry); + groupSeparator.optionEntries.add(optionEntry); + lastEntry = optionEntry; + } + } + + public Dimension<Integer> getDefaultEntryPosition() { + return Dimension.ofInt(getRowLeft(), 0, getRowWidth(), 20); + } + public void expandAllGroups() { for (Entry entry : super.children()) { if (entry instanceof GroupSeparatorEntry groupSeparatorEntry) { @@ -153,6 +182,40 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr return viewableChildren; } + public void addEntry(int index, Entry entry) { + super.children().add(index, entry); + recacheViewableChildren(); + } + + public void addEntryBelow(Entry below, Entry entry) { + int idx = super.children().indexOf(below) + 1; + + if (idx == 0) + throw new IllegalStateException("The entry to insert below does not exist!"); + + addEntry(idx, entry); + } + + public void addEntryBelowWithoutScroll(Entry below, Entry entry) { + double d = (double)this.getMaxScroll() - this.getScrollAmount(); + addEntryBelow(below, entry); + setScrollAmount(getMaxScroll() - d); + } + + @Override + public boolean removeEntryWithoutScrolling(Entry entry) { + boolean ret = super.removeEntryWithoutScrolling(entry); + recacheViewableChildren(); + return ret; + } + + @Override + public boolean removeEntry(Entry entry) { + boolean ret = super.removeEntry(entry); + recacheViewableChildren(); + return ret; + } + public abstract class Entry extends ElementListWidgetExt.Entry<Entry> { public boolean isViewable() { return true; @@ -168,25 +231,28 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr public final ConfigCategory category; public final OptionGroup group; + public final @Nullable GroupSeparatorEntry groupSeparatorEntry; + public final AbstractWidget widget; - private final Supplier<Boolean> viewableSupplier; private final TextScaledButtonWidget resetButton; private final String categoryName; private final String groupName; - private OptionEntry(Option<?> option, ConfigCategory category, OptionGroup group, AbstractWidget widget, Supplier<Boolean> viewableSupplier) { + public OptionEntry(Option<?> option, ConfigCategory category, OptionGroup group, @Nullable GroupSeparatorEntry groupSeparatorEntry, AbstractWidget widget) { this.option = option; this.category = category; this.group = group; - this.widget = widget; - this.viewableSupplier = viewableSupplier; + this.groupSeparatorEntry = groupSeparatorEntry; + if (option instanceof ListOptionEntry<?> listOptionEntry) + this.widget = new ListEntryWidget(yaclScreen, listOptionEntry, widget); + else this.widget = widget; this.categoryName = category.name().getString().toLowerCase(); this.groupName = group.name().getString().toLowerCase(); - if (this.widget.canReset()) { - this.widget.setDimension(this.widget.getDimension().expanded(-21, 0)); - this.resetButton = new TextScaledButtonWidget(widget.getDimension().xLimit() + 1, -50, 20, 20, 2f, Text.of("\u21BB"), button -> { + if (option.canResetToDefault() && this.widget.canReset()) { + this.widget.setDimension(this.widget.getDimension().expanded(-20, 0)); + this.resetButton = new TextScaledButtonWidget(widget.getDimension().xLimit(), -50, 20, 20, 2f, Text.of("\u21BB"), button -> { option.requestSetDefault(); }); option.addListener((opt, val) -> this.resetButton.active = !opt.isPendingValueDefault() && opt.available()); @@ -231,7 +297,7 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr @Override public boolean isViewable() { String query = yaclScreen.searchFieldWidget.getText(); - return viewableSupplier.get() + return (groupSeparatorEntry == null || groupSeparatorEntry.isExpanded()) && (yaclScreen.searchFieldWidget.isEmpty() || (!singleCategory && categoryName.contains(query)) || groupName.contains(query) @@ -261,18 +327,18 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr } public class GroupSeparatorEntry extends Entry { - private final OptionGroup group; - private final MultilineText wrappedName; - private final MultilineText wrappedTooltip; + protected final OptionGroup group; + protected final MultilineText wrappedName; + protected final MultilineText wrappedTooltip; - private final LowProfileButtonWidget expandMinimizeButton; + protected final LowProfileButtonWidget expandMinimizeButton; - private final Screen screen; - private final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + protected final Screen screen; + protected final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - private boolean groupExpanded; + protected boolean groupExpanded; - private List<OptionEntry> optionEntries; + protected List<OptionEntry> optionEntries; private int y; @@ -282,10 +348,7 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr this.wrappedName = MultilineText.create(textRenderer, group.name(), getRowWidth() - 45); this.wrappedTooltip = MultilineText.create(textRenderer, group.tooltip(), screen.width / 3 * 2 - 10); this.groupExpanded = !group.collapsed(); - this.expandMinimizeButton = new LowProfileButtonWidget(0, 0, 20, 20, Text.empty(), btn -> { - setExpanded(!isExpanded()); - recacheViewableChildren(); - }); + this.expandMinimizeButton = new LowProfileButtonWidget(0, 0, 20, 20, Text.empty(), btn -> onExpandButtonPress()); updateExpandMinimizeText(); } @@ -293,8 +356,10 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { this.y = y; + int buttonY = y + entryHeight / 2 - expandMinimizeButton.getHeight() / 2 + 1; + + expandMinimizeButton.setY(buttonY); expandMinimizeButton.setX(x); - expandMinimizeButton.setY(y + entryHeight / 2 - expandMinimizeButton.getHeight() / 2); expandMinimizeButton.render(matrices, mouseX, mouseY, tickDelta); wrappedName.drawCenterWithShadow(matrices, x + entryWidth / 2, y + getYPadding()); @@ -316,7 +381,12 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr updateExpandMinimizeText(); } - private void updateExpandMinimizeText() { + protected void onExpandButtonPress() { + setExpanded(!isExpanded()); + recacheViewableChildren(); + } + + protected void updateExpandMinimizeText() { expandMinimizeButton.setMessage(Text.of(isExpanded() ? "▼" : "▶")); } @@ -349,6 +419,7 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr @Override public void appendNarrations(NarrationMessageBuilder builder) { builder.put(NarrationPart.TITLE, group.name()); + builder.put(NarrationPart.HINT, group.tooltip()); } }); } @@ -358,4 +429,72 @@ public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entr return ImmutableList.of(expandMinimizeButton); } } + + public class ListGroupSeparatorEntry extends GroupSeparatorEntry { + private final ListOption<?> listOption; + private final TextScaledButtonWidget resetListButton; + private final TooltipButtonWidget addListButton; + + private ListGroupSeparatorEntry(ListOption<?> group, Screen screen) { + super(group, screen); + this.listOption = group; + + this.resetListButton = new TextScaledButtonWidget(getRowRight() - 20, -50, 20, 20, 2f, Text.of("\u21BB"), button -> { + group.requestSetDefault(); + }); + group.addListener((opt, val) -> this.resetListButton.active = !opt.isPendingValueDefault() && opt.available()); + this.resetListButton.active = !group.isPendingValueDefault() && group.available(); + + this.addListButton = new TooltipButtonWidget(yaclScreen, resetListButton.getX() - 20, -50, 20, 20, Text.of("+"), Text.translatable("yacl.list.add_top"), btn -> { + group.insertNewEntryToTop(); + }); + + updateExpandMinimizeText(); + minimizeIfUnavailable(); + } + + @Override + public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + updateExpandMinimizeText(); // update every render because option could become available/unavailable at any time + + super.render(matrices, index, y, x, entryWidth, entryHeight, mouseX, mouseY, hovered, tickDelta); + + int buttonY = expandMinimizeButton.getY(); + + resetListButton.setY(buttonY); + addListButton.setY(buttonY); + + resetListButton.render(matrices, mouseX, mouseY, tickDelta); + addListButton.render(matrices, mouseX, mouseY, tickDelta); + } + + @Override + public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { + minimizeIfUnavailable(); // cannot run in render because it *should* cause a ConcurrentModificationException (but doesn't) + + super.postRender(matrices, mouseX, mouseY, delta); + + addListButton.renderHoveredTooltip(matrices); + } + + private void minimizeIfUnavailable() { + if (!listOption.available() && isExpanded()) { + setExpanded(false); + recacheViewableChildren(); + } + } + + @Override + protected void updateExpandMinimizeText() { + super.updateExpandMinimizeText(); + if (resetListButton != null && addListButton != null) + resetListButton.visible = addListButton.visible = isExpanded(); + expandMinimizeButton.active = listOption == null || listOption.available(); + } + + @Override + public List<? extends Element> children() { + return ImmutableList.of(expandMinimizeButton, addListButton, resetListButton); + } + } } diff --git a/src/client/java/dev/isxander/yacl/gui/TooltipButtonWidget.java b/src/client/java/dev/isxander/yacl/gui/TooltipButtonWidget.java index b034f4b..359e8d0 100644 --- a/src/client/java/dev/isxander/yacl/gui/TooltipButtonWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/TooltipButtonWidget.java @@ -3,21 +3,26 @@ package dev.isxander.yacl.gui; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.MultilineText; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; -public class TooltipButtonWidget extends ButtonWidget { +public class TooltipButtonWidget extends TextScaledButtonWidget { protected final Screen screen; protected MultilineText wrappedDescription; - public TooltipButtonWidget(Screen screen, int x, int y, int width, int height, Text message, Text tooltip, PressAction onPress) { - super(x, y, width, height, message, onPress, DEFAULT_NARRATION_SUPPLIER); + public TooltipButtonWidget(Screen screen, int x, int y, int width, int height, Text message, float textScale, Text tooltip, PressAction onPress) { + super(x, y, width, height, textScale, message, onPress); this.screen = screen; setTooltip(tooltip); } + public TooltipButtonWidget(Screen screen, int x, int y, int width, int height, Text message, Text tooltip, PressAction onPress) { + this(screen, x, y, width, height, message, 1, tooltip, onPress); + } + public void renderHoveredTooltip(MatrixStack matrices) { if (isHovered()) { YACLScreen.renderMultilineTooltip(matrices, MinecraftClient.getInstance().textRenderer, wrappedDescription, getX() + width / 2, getY() - 4, getY() + height + 4, screen.width, screen.height); diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java b/src/client/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java index 0f49d3d..ae54ca4 100644 --- a/src/client/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java @@ -8,6 +8,7 @@ import dev.isxander.yacl.gui.utils.GuiUtils; import net.minecraft.client.font.MultilineText; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -151,6 +152,7 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract @Override public void appendNarrations(NarrationMessageBuilder builder) { - + builder.put(NarrationPart.TITLE, control.option().name()); + builder.put(NarrationPart.HINT, control.option().tooltip()); } } diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/LabelController.java b/src/client/java/dev/isxander/yacl/gui/controllers/LabelController.java index 8369680..960c950 100644 --- a/src/client/java/dev/isxander/yacl/gui/controllers/LabelController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/LabelController.java @@ -64,7 +64,7 @@ public class LabelController implements Controller<Text> { float y = getDimension().y(); for (OrderedText text : wrappedText) { - textRenderer.drawWithShadow(matrices, text, getDimension().x(), y + getYPadding(), option().available() ? -1 : 0xFFA0A0A0); + textRenderer.drawWithShadow(matrices, text, getDimension().x() + getXPadding(), y + getYPadding(), option().available() ? -1 : 0xFFA0A0A0); y += textRenderer.fontHeight; } } @@ -123,12 +123,16 @@ public class LabelController implements Controller<Text> { return textRenderer.getTextHandler().getStyleAt(wrappedText.get(line), x); } + private int getXPadding() { + return 4; + } + private int getYPadding() { return 3; } private void updateText() { - wrappedText = textRenderer.wrapLines(formatValue(), getDimension().width()); + wrappedText = textRenderer.wrapLines(formatValue(), getDimension().width() - getXPadding() * 2); setDimension(getDimension().withHeight(wrappedText.size() * textRenderer.fontHeight + getYPadding() * 2)); } diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/ListEntryWidget.java b/src/client/java/dev/isxander/yacl/gui/controllers/ListEntryWidget.java new file mode 100644 index 0000000..a548efb --- /dev/null +++ b/src/client/java/dev/isxander/yacl/gui/controllers/ListEntryWidget.java @@ -0,0 +1,132 @@ +package dev.isxander.yacl.gui.controllers; + +import com.google.common.collect.ImmutableList; +import dev.isxander.yacl.api.ListOption; +import dev.isxander.yacl.api.ListOptionEntry; +import dev.isxander.yacl.api.utils.Dimension; +import dev.isxander.yacl.gui.*; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.ParentElement; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class ListEntryWidget extends AbstractWidget implements ParentElement { + private final TooltipButtonWidget removeButton, moveUpButton, moveDownButton; + private final AbstractWidget entryWidget; + + private final ListOption<?> listOption; + private final ListOptionEntry<?> listOptionEntry; + + private final String optionNameString; + + private Element focused; + private boolean dragging; + + public ListEntryWidget(YACLScreen screen, ListOptionEntry<?> listOptionEntry, AbstractWidget entryWidget) { + super(entryWidget.getDimension()); + this.listOptionEntry = listOptionEntry; + this.listOption = listOptionEntry.parentGroup(); + this.optionNameString = listOptionEntry.name().getString().toLowerCase(); + this.entryWidget = entryWidget; + + Dimension<Integer> dim = entryWidget.getDimension(); + entryWidget.setDimension(dim.clone().move(20 * 2, 0).expand(-20 * 3, 0)); + + removeButton = new TooltipButtonWidget(screen, dim.xLimit() - 20, dim.y(), 20, 20, Text.of("\u274c"), Text.translatable("yacl.list.remove"), btn -> { + listOption.removeEntry(listOptionEntry); + }); + + moveUpButton = new TooltipButtonWidget(screen, dim.x(), dim.y(), 20, 20, Text.of("\u2191"), Text.translatable("yacl.list.move_up"), btn -> { + int index = listOption.indexOf(listOptionEntry) - 1; + if (index >= 0) { + listOption.removeEntry(listOptionEntry); + listOption.insertEntry(index, listOptionEntry); + updateButtonStates(); + } + }); + + moveDownButton = new TooltipButtonWidget(screen, dim.x() + 20, dim.y(), 20, 20, Text.of("\u2193"), Text.translatable("yacl.list.move_down"), btn -> { + int index = listOption.indexOf(listOptionEntry) + 1; + if (index < listOption.options().size()) { + listOption.removeEntry(listOptionEntry); + listOption.insertEntry(index, listOptionEntry); + updateButtonStates(); + } + }); + + updateButtonStates(); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + updateButtonStates(); // update every render in case option becomes available/unavailable + + removeButton.setY(getDimension().y()); + moveUpButton.setY(getDimension().y()); + moveDownButton.setY(getDimension().y()); + entryWidget.setDimension(entryWidget.getDimension().withY(getDimension().y())); + + removeButton.render(matrices, mouseX, mouseY, delta); + moveUpButton.render(matrices, mouseX, mouseY, delta); + moveDownButton.render(matrices, mouseX, mouseY, delta); + entryWidget.render(matrices, mouseX, mouseY, delta); + } + + @Override + public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { + removeButton.renderHoveredTooltip(matrices); + moveUpButton.renderHoveredTooltip(matrices); + moveDownButton.renderHoveredTooltip(matrices); + } + + protected void updateButtonStates() { + removeButton.active = listOption.available(); + moveUpButton.active = listOption.indexOf(listOptionEntry) > 0 && listOption.available(); + moveDownButton.active = listOption.indexOf(listOptionEntry) < listOption.options().size() - 1 && listOption.available(); + } + + @Override + public void unfocus() { + entryWidget.unfocus(); + } + + @Override + public void appendNarrations(NarrationMessageBuilder builder) { + entryWidget.appendNarrations(builder); + } + + @Override + public boolean matchesSearch(String query) { + return optionNameString.contains(query.toLowerCase()); + } + + @Override + public List<? extends Element> children() { + return ImmutableList.of(moveUpButton, moveDownButton, entryWidget, removeButton); + } + + @Override + public boolean isDragging() { + return dragging; + } + + @Override + public void setDragging(boolean dragging) { + this.dragging = dragging; + } + + @Nullable + @Override + public Element getFocused() { + return focused; + } + + @Override + public void setFocused(@Nullable Element focused) { + this.focused = focused; + } +} diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java b/src/client/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java index c78e0eb..ea4e262 100644 --- a/src/client/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java @@ -141,7 +141,11 @@ public class SliderControllerElement extends ControllerWidget<ISliderController< @Override public void setDimension(Dimension<Integer> dim) { super.setDimension(dim); - sliderBounds = Dimension.ofInt(dim.xLimit() - getXPadding() - getThumbWidth() / 2 - dim.width() / 3, dim.centerY() - 5, dim.width() / 3, 10); + int trackWidth = dim.width() / 3; + if (optionNameString.isEmpty()) + trackWidth = dim.width() / 2; + + sliderBounds = Dimension.ofInt(dim.xLimit() - getXPadding() - getThumbWidth() / 2 - trackWidth, dim.centerY() - 5, trackWidth, 10); } protected int getThumbX() { diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java index ef70341..da33aec 100644 --- a/src/client/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java @@ -49,7 +49,7 @@ public class StringControllerElement extends ControllerWidget<IStringController< @Override protected void drawValueText(MatrixStack matrices, int mouseX, int mouseY, float delta) { Text valueText = getValueText(); - if (!isHovered()) valueText = Text.literal(GuiUtils.shortenString(valueText.getString(), textRenderer, getDimension().width() / 2, "...")).setStyle(valueText.getStyle()); + if (!isHovered()) valueText = Text.literal(GuiUtils.shortenString(valueText.getString(), textRenderer, getMaxUnwrapLength(), "...")).setStyle(valueText.getStyle()); matrices.push(); int textX = getDimension().xLimit() - textRenderer.getWidth(valueText) + renderOffset - getXPadding(); @@ -311,9 +311,17 @@ public class StringControllerElement extends ControllerWidget<IStringController< } public int getUnshiftedLength() { + if (optionNameString.isEmpty()) + return getDimension().width() - getXPadding() * 2; return getDimension().width() / 8 * 5; } + public int getMaxUnwrapLength() { + if (optionNameString.isEmpty()) + return getDimension().width() - getXPadding() * 2; + return getDimension().width() / 2; + } + public int getSelectionStart() { return Math.min(caretPos, caretPos + selectionLength); } @@ -378,7 +386,7 @@ public class StringControllerElement extends ControllerWidget<IStringController< @Override protected int getUnhoveredControlWidth() { - return !isHovered() ? Math.min(getHoveredControlWidth(), getDimension().width() / 2) : getHoveredControlWidth(); + return !isHovered() ? Math.min(getHoveredControlWidth(), getMaxUnwrapLength()) : getHoveredControlWidth(); } @Override diff --git a/src/client/java/dev/isxander/yacl/gui/utils/GuiUtils.java b/src/client/java/dev/isxander/yacl/gui/utils/GuiUtils.java index 670bd12..b1f0148 100644 --- a/src/client/java/dev/isxander/yacl/gui/utils/GuiUtils.java +++ b/src/client/java/dev/isxander/yacl/gui/utils/GuiUtils.java @@ -22,6 +22,9 @@ public class GuiUtils { } public static String shortenString(String string, TextRenderer textRenderer, int maxWidth, String suffix) { + if (string.isEmpty()) + return string; + boolean firstIter = true; while (textRenderer.getWidth(string) > maxWidth) { string = string.substring(0, Math.max(string.length() - 1 - (firstIter ? 1 : suffix.length() + 1), 0)).trim(); |