297 lines
12 KiB
Java
297 lines
12 KiB
Java
package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry;
|
|
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.client.MinecraftClient;
|
|
import net.minecraft.client.font.TextRenderer;
|
|
import net.minecraft.client.gui.*;
|
|
import net.minecraft.client.gui.screen.Screen;
|
|
import net.minecraft.client.gui.widget.*;
|
|
import net.minecraft.client.render.RenderLayer;
|
|
import net.minecraft.text.*;
|
|
import net.minecraft.util.math.MathHelper;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.util.*;
|
|
import java.util.function.BooleanSupplier;
|
|
import java.util.function.Supplier;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEntry> {
|
|
private final TextRenderer textRenderer;
|
|
private final boolean background;
|
|
|
|
public EntryListWidget(MinecraftClient client, TextRenderer tr, int width, int height, int top, int bottom) {
|
|
super(client, width, height, top, bottom, 25);
|
|
this.centerListVertically = false;
|
|
textRenderer = tr;
|
|
background = client.world == null;
|
|
setRenderBackground(background);
|
|
}
|
|
|
|
@Override
|
|
public int getScrollbarPositionX() {
|
|
return this.width -7;
|
|
}
|
|
|
|
public void addUnknown(ClickableWidget resetButton, BooleanSupplier resetVisible, Text text, Reflowable reflow) {
|
|
this.addEntry(new ConfigUnknownEntry(text, resetVisible, resetButton, reflow));
|
|
}
|
|
|
|
public void addButton(@Nullable ClickableWidget button, ClickableWidget resetButton, BooleanSupplier resetVisible, Text text, Reflowable reflow) {
|
|
this.addEntry(new ConfigScreenEntry(button, text, resetVisible, resetButton, reflow));
|
|
}
|
|
|
|
public void addReference(Text text, Supplier<Screen> targetScreen) {
|
|
this.addEntry(new ConfigReferenceEntry(width, text, targetScreen));
|
|
}
|
|
|
|
public void addText(Text text) {
|
|
for (ConfigEntry entry : ConfigTextEntry.create(this, text, width)) this.addEntry(entry);
|
|
}
|
|
|
|
@Override
|
|
public int getRowWidth() {
|
|
return 10000;
|
|
}
|
|
|
|
public Optional<Text> getHoveredEntryTitle(double mouseY) {
|
|
for (ConfigEntry abstractEntry : this.children()) {
|
|
if (abstractEntry instanceof ConfigScreenEntry entry
|
|
&& entry.button.visible
|
|
&& mouseY >= entry.button.getY() && mouseY < entry.button.getY() + itemHeight) {
|
|
return Optional.of(entry.getText());
|
|
} else if (abstractEntry instanceof ConfigUnknownEntry entry
|
|
&& mouseY >= entry.resetButton.getY() && mouseY < entry.resetButton.getY() + itemHeight) {
|
|
return Optional.of(entry.getText());
|
|
}
|
|
}
|
|
return Optional.empty();
|
|
}
|
|
|
|
public void refreshGrid(ScreenRect tabArea) {
|
|
updateSize(tabArea.width(), tabArea.height(), tabArea.getTop(), tabArea.getBottom());
|
|
setLeftPos(tabArea.getLeft());
|
|
for (int len = getEntryCount() - 1, i = len; i >= 0; i--) {
|
|
getEntry(i).reflow(width, height);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void renderDecorations(DrawContext context, int mouseX, int mouseY) {
|
|
super.renderDecorations(context, mouseX, mouseY);
|
|
if (background) return;
|
|
|
|
// Background texture at the top of the screen
|
|
context.setShaderColor(0.25f, 0.25f, 0.25f, 1.0f);
|
|
context.drawTexture(Screen.OPTIONS_BACKGROUND_TEXTURE, left, 0, 0.0f, 0.0f, width, top, 32, 32);
|
|
context.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
// Gradient at the top of the screen
|
|
context.fillGradient(RenderLayer.getGuiOverlay(), left, top, right, top + 4, 0xff000000, 0x00000000, 0);
|
|
// Gradient at the bottom of the screen
|
|
if (getScrollAmount() < getMaxScroll()) context.fillGradient(RenderLayer.getGuiOverlay(), left, bottom - 4, right, bottom, 0x00000000, 0xff000000, 0);
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public abstract static class ConfigEntry extends Entry<ConfigEntry> implements Reflowable {
|
|
@Override
|
|
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
|
|
if (hovered) {
|
|
context.fill(x, y, x + entryWidth, y + entryHeight, 0x24FFFFFF);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class ConfigTextEntry extends ConfigEntry {
|
|
private int width;
|
|
private final OrderedText text;
|
|
private final TextRenderer renderer;
|
|
private final ConfigTextEntry next;
|
|
public StringVisitable originalText = null;
|
|
|
|
public ConfigTextEntry(int width, OrderedText text, TextRenderer renderer, ConfigTextEntry next) {
|
|
this.width = width;
|
|
this.text = text;
|
|
this.renderer = renderer;
|
|
this.next = next;
|
|
}
|
|
|
|
public static List<ConfigTextEntry> create(EntryListWidget parent, StringVisitable text, int width) {
|
|
TextRenderer renderer = MinecraftClient.getInstance().textRenderer;
|
|
List<ConfigTextEntry> entries = new ArrayList<>();
|
|
ConfigTextEntry next = null;
|
|
List<OrderedText> wrappedLines = new ArrayList<>(renderer.wrapLines(text, width));
|
|
Collections.reverse(wrappedLines);
|
|
for (OrderedText line : wrappedLines) {
|
|
ConfigTextEntry[] tmp = new ConfigTextEntry[1];
|
|
entries.add(next = tmp[0] = parent.new ConfigTextEntry(width, line, renderer, next));
|
|
}
|
|
if (!entries.isEmpty()) entries.get(entries.size() - 1).originalText = text;
|
|
Collections.reverse(entries);
|
|
return entries;
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Selectable> selectableChildren() {
|
|
return List.of();
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Element> children() {
|
|
return List.of();
|
|
}
|
|
|
|
@Override
|
|
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
|
|
super.render(context, index, y, x, entryWidth, entryHeight, mouseX, mouseY, hovered, tickDelta);
|
|
int textX = (width - renderer.getWidth(text)) / 2;
|
|
int textY = y + (20 - renderer.fontHeight) / 2;
|
|
context.drawTextWithShadow(renderer, text, textX, textY, 0xFFFFFF);
|
|
}
|
|
|
|
@Override
|
|
public void reflow(int width, int height) {
|
|
this.width = width;
|
|
if (originalText != null) {
|
|
List<ConfigEntry> children = EntryListWidget.this.children();
|
|
int i = children.indexOf(this);
|
|
EntryListWidget.this.removeEntry(this);
|
|
for (ConfigTextEntry entry : create(EntryListWidget.this, originalText, width)) {
|
|
children.add(i++, entry);
|
|
}
|
|
} else {
|
|
EntryListWidget.this.removeEntry(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static class ConfigReferenceEntry extends ConfigEntry {
|
|
private final ClickableWidget button;
|
|
|
|
public ConfigReferenceEntry(int width, Text text, Supplier<Screen> targetScreen) {
|
|
this.button = ButtonWidget.builder(text, btn -> MinecraftClient.getInstance().setScreen(targetScreen.get()))
|
|
.dimensions(width / 2 - 154, 0, 308, 20)
|
|
.build();
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Selectable> selectableChildren() {
|
|
return List.of(button);
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Element> children() {
|
|
return List.of(button);
|
|
}
|
|
|
|
@Override
|
|
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
|
|
super.render(context, index, y, x, entryWidth, entryHeight, mouseX, mouseY, hovered, tickDelta);
|
|
button.setY(y);
|
|
button.render(context, mouseX, mouseY, tickDelta);
|
|
}
|
|
|
|
@Override
|
|
public void reflow(int width, int height) {
|
|
button.setX(width / 2 - 154);
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static class ConfigScreenEntry extends ConfigEntry {
|
|
private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
|
|
public final ClickableWidget button;
|
|
private final BooleanSupplier resetVisible;
|
|
private final ClickableWidget resetButton;
|
|
private final Text text;
|
|
private final Reflowable reflow;
|
|
|
|
public ConfigScreenEntry(ClickableWidget button, Text text, BooleanSupplier resetVisible, ClickableWidget resetButton, Reflowable reflow) {
|
|
this.button = button;
|
|
this.resetVisible = resetVisible;
|
|
this.resetButton = resetButton;
|
|
this.text = text;
|
|
this.reflow = reflow;
|
|
}
|
|
|
|
@Override
|
|
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
|
|
super.render(context, index, y, x, entryWidth, entryHeight, mouseX, mouseY, hovered, tickDelta);
|
|
button.setY(y);
|
|
button.render(context, mouseX, mouseY, tickDelta);
|
|
context.drawTextWithShadow(textRenderer, text, 12, y + 5, 0xFFFFFF);
|
|
if (resetVisible.getAsBoolean()) {
|
|
resetButton.setY(y);
|
|
resetButton.render(context, mouseX, mouseY, tickDelta);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void reflow(int width, int height) {
|
|
reflow.reflow(width, height);
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Element> children() {
|
|
return List.of(button, resetButton);
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Selectable> selectableChildren() {
|
|
return List.of(button);
|
|
}
|
|
|
|
public Text getText() {
|
|
return text;
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static class ConfigUnknownEntry extends ConfigEntry {
|
|
private static final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
|
|
private final BooleanSupplier resetVisible;
|
|
private final ClickableWidget resetButton;
|
|
private final Text text;
|
|
private final Reflowable reflow;
|
|
|
|
public ConfigUnknownEntry(Text text, BooleanSupplier resetVisible, ClickableWidget resetButton, Reflowable reflow) {
|
|
this.resetVisible = resetVisible;
|
|
this.resetButton = resetButton;
|
|
this.text = text;
|
|
this.reflow = reflow;
|
|
}
|
|
|
|
@Override
|
|
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
|
|
super.render(context, index, y, x, entryWidth, entryHeight, mouseX, mouseY, hovered, tickDelta);
|
|
context.drawTextWithShadow(textRenderer, text, 12, y + 5, 0xFFFFFF);
|
|
if (resetVisible.getAsBoolean()) {
|
|
resetButton.setY(y);
|
|
resetButton.render(context, mouseX, mouseY, tickDelta);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void reflow(int width, int height) {
|
|
reflow.reflow(width, height);
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Element> children() {
|
|
return List.of(resetButton);
|
|
}
|
|
|
|
@Override
|
|
public List<? extends Selectable> selectableChildren() {
|
|
return List.of();
|
|
}
|
|
|
|
public Text getText() {
|
|
return text;
|
|
}
|
|
}
|
|
}
|