[config-ui-tiny] preliminary json editing support
This commit is contained in:
parent
df10f1bf47
commit
01481bb4df
|
@ -4,5 +4,6 @@
|
|||
"libjf-config-v1.see-also": "See also: %s",
|
||||
"libjf-config-v1.reset": "Reset",
|
||||
"libjf-config-core-v1.no-screen": "No screen",
|
||||
"libjf-config-core-v1.no-screen.description": "No mod for rendering config UIs was discovered. Install LibJF to add one."
|
||||
"libjf-config-core-v1.no-screen.description": "No mod for rendering config UIs was discovered. Install LibJF to add one.",
|
||||
"libjf-config-core-v1.edit": "Edit"
|
||||
}
|
|
@ -0,0 +1,505 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.ui.tiny;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import io.gitlab.jfronny.commons.ref.R;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.font.TextHandler;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.BookScreen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.util.NarratorManager;
|
||||
import net.minecraft.client.util.SelectionManager;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Rect2i;
|
||||
import net.minecraft.screen.ScreenTexts;
|
||||
import net.minecraft.text.Style;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Util;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EditorScreen extends Screen {
|
||||
//TODO simple box background
|
||||
//TODO scrollable
|
||||
private static final int MAX_TEXT_WIDTH = 114;
|
||||
private static final int MAX_TEXT_HEIGHT = 128;
|
||||
private static final int WIDTH = 192;
|
||||
private static final int HEIGHT = 192;
|
||||
|
||||
private int tickCounter;
|
||||
private final String initialText;
|
||||
private String text = "";
|
||||
private final SelectionManager currentPageSelectionManager = new SelectionManager(
|
||||
this::getText,
|
||||
this::setText,
|
||||
this::getClipboard,
|
||||
this::setClipboard,
|
||||
string -> string.length() < 1024 && this.textRenderer.getWrappedLinesHeight(string, MAX_TEXT_WIDTH) <= MAX_TEXT_HEIGHT
|
||||
);
|
||||
|
||||
private long lastClickTime;
|
||||
private int lastClickIndex = -1;
|
||||
|
||||
@Nullable
|
||||
private PageContent pageContent = PageContent.EMPTY;
|
||||
private final Screen parent;
|
||||
private final Consumer<String> onSave;
|
||||
|
||||
public EditorScreen(@Nullable Text title, @Nullable Screen parent, @Nullable String text, @Nullable Consumer<String> onSave) {
|
||||
super(title == null ? NarratorManager.EMPTY : title);
|
||||
this.parent = parent;
|
||||
this.initialText = text;
|
||||
if (text != null) this.text = text;
|
||||
this.onSave = onSave == null ? R::nop : onSave;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = Objects.requireNonNull(text);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
private void setClipboard(String clipboard) {
|
||||
if (this.client != null) {
|
||||
SelectionManager.setClipboard(this.client, clipboard);
|
||||
}
|
||||
}
|
||||
|
||||
private String getClipboard() {
|
||||
return this.client != null ? SelectionManager.getClipboard(this.client) : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
++this.tickCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
ButtonWidget cancelButton;
|
||||
ButtonWidget doneButton;
|
||||
this.invalidatePageContent();
|
||||
doneButton = this.addDrawableChild(
|
||||
ButtonWidget.builder(ScreenTexts.DONE, button -> quit(true))
|
||||
.dimensions(this.width / 2 + 2, HEIGHT + 4, 98, 20)
|
||||
.build()
|
||||
);
|
||||
cancelButton = this.addDrawableChild(
|
||||
ButtonWidget.builder(ScreenTexts.CANCEL, button -> quit(false))
|
||||
.dimensions(this.width / 2 - 102, HEIGHT + 4, 98, 20)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
private void quit(boolean save) {
|
||||
if (save && (this.initialText == null || !this.initialText.equals(this.text))) onSave.accept(text);
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Objects.requireNonNull(client).setScreen(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (super.keyPressed(keyCode, scanCode, modifiers)) {
|
||||
return true;
|
||||
}
|
||||
boolean bl = this.keyPressedEditMode(keyCode);
|
||||
if (bl) {
|
||||
this.invalidatePageContent();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped(char chr, int modifiers) {
|
||||
if (super.charTyped(chr, modifiers)) {
|
||||
return true;
|
||||
}
|
||||
if (SharedConstants.isValidChar(chr)) {
|
||||
this.currentPageSelectionManager.insert(Character.toString(chr));
|
||||
this.invalidatePageContent();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean keyPressedEditMode(int keyCode) {
|
||||
boolean ctrl = Screen.hasControlDown() && !Screen.hasShiftDown() && !Screen.hasAltDown();
|
||||
SelectionManager.SelectionType selectionType = Screen.hasControlDown() ? SelectionManager.SelectionType.WORD : SelectionManager.SelectionType.CHARACTER;
|
||||
return switch (keyCode) {
|
||||
case 65 -> {
|
||||
if (ctrl) {
|
||||
this.currentPageSelectionManager.selectAll();
|
||||
yield true;
|
||||
}
|
||||
yield false;
|
||||
}
|
||||
case 67 -> {
|
||||
if (ctrl) {
|
||||
this.currentPageSelectionManager.copy();
|
||||
yield true;
|
||||
}
|
||||
yield false;
|
||||
}
|
||||
case 83 -> {
|
||||
if (ctrl) {
|
||||
quit(true);
|
||||
yield true;
|
||||
}
|
||||
yield false;
|
||||
}
|
||||
case 86 -> {
|
||||
if (ctrl) {
|
||||
this.currentPageSelectionManager.paste();
|
||||
yield true;
|
||||
}
|
||||
yield false;
|
||||
}
|
||||
case 88 -> {
|
||||
if (ctrl) {
|
||||
this.currentPageSelectionManager.cut();
|
||||
yield true;
|
||||
}
|
||||
yield false;
|
||||
}
|
||||
case 259 -> {
|
||||
this.currentPageSelectionManager.delete(-1, selectionType);
|
||||
yield true;
|
||||
}
|
||||
case 261 -> {
|
||||
this.currentPageSelectionManager.delete(1, selectionType);
|
||||
yield true;
|
||||
}
|
||||
case 257, 335 -> {
|
||||
this.currentPageSelectionManager.insert("\n");
|
||||
yield true;
|
||||
}
|
||||
case 263 -> {
|
||||
this.currentPageSelectionManager.moveCursor(-1, Screen.hasShiftDown(), selectionType);
|
||||
yield true;
|
||||
}
|
||||
case 262 -> {
|
||||
this.currentPageSelectionManager.moveCursor(1, Screen.hasShiftDown(), selectionType);
|
||||
yield true;
|
||||
}
|
||||
case 265 -> {
|
||||
this.moveUpLine();
|
||||
yield true;
|
||||
}
|
||||
case 264 -> {
|
||||
this.moveDownLine();
|
||||
yield true;
|
||||
}
|
||||
case 268 -> {
|
||||
this.moveToLineStart();
|
||||
yield true;
|
||||
}
|
||||
case 269 -> {
|
||||
this.moveToLineEnd();
|
||||
yield true;
|
||||
}
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private void moveUpLine() {
|
||||
this.moveVertically(-1);
|
||||
}
|
||||
|
||||
private void moveDownLine() {
|
||||
this.moveVertically(1);
|
||||
}
|
||||
|
||||
private void moveVertically(int lines) {
|
||||
int i = this.currentPageSelectionManager.getSelectionStart();
|
||||
int j = this.getPageContent().getVerticalOffset(i, lines);
|
||||
this.currentPageSelectionManager.moveCursorTo(j, Screen.hasShiftDown());
|
||||
}
|
||||
|
||||
private void moveToLineStart() {
|
||||
if (Screen.hasControlDown()) {
|
||||
this.currentPageSelectionManager.moveCursorToStart(Screen.hasShiftDown());
|
||||
} else {
|
||||
int i = this.currentPageSelectionManager.getSelectionStart();
|
||||
int j = this.getPageContent().getLineStart(i);
|
||||
this.currentPageSelectionManager.moveCursorTo(j, Screen.hasShiftDown());
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToLineEnd() {
|
||||
if (Screen.hasControlDown()) {
|
||||
this.currentPageSelectionManager.moveCursorToEnd(Screen.hasShiftDown());
|
||||
} else {
|
||||
int i = this.currentPageSelectionManager.getSelectionStart();
|
||||
int j = this.getPageContent().getLineEnd(i);
|
||||
this.currentPageSelectionManager.moveCursorTo(j, Screen.hasShiftDown());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
this.renderBackground(matrices);
|
||||
this.setFocused(null);
|
||||
RenderSystem.setShaderTexture(0, BookScreen.BOOK_TEXTURE);
|
||||
int i = (this.width - WIDTH) / 2;
|
||||
drawTexture(matrices, i, 2, 0, 0, WIDTH, HEIGHT);
|
||||
PageContent pageContent = this.getPageContent();
|
||||
for (Line line : pageContent.lines) {
|
||||
this.textRenderer.draw(matrices, line.text, line.x, line.y, -16777216);
|
||||
}
|
||||
this.drawSelection(matrices, pageContent.selectionRectangles);
|
||||
this.drawCursor(matrices, pageContent.position, pageContent.atEnd);
|
||||
super.render(matrices, mouseX, mouseY, delta);
|
||||
}
|
||||
|
||||
private void drawCursor(MatrixStack matrices, Position position, boolean atEnd) {
|
||||
if (this.tickCounter / 6 % 2 == 0) {
|
||||
position = this.absolutePositionToScreenPosition(position);
|
||||
if (!atEnd) {
|
||||
DrawableHelper.fill(matrices, position.x, position.y - 1, position.x + 1, position.y + this.textRenderer.fontHeight, -16777216);
|
||||
} else {
|
||||
this.textRenderer.draw(matrices, "_", position.x, position.y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawSelection(MatrixStack matrices, Rect2i[] selectionRectangles) {
|
||||
RenderSystem.enableColorLogicOp();
|
||||
RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE);
|
||||
for (Rect2i rect2i : selectionRectangles) {
|
||||
int i = rect2i.getX();
|
||||
int j = rect2i.getY();
|
||||
int k = i + rect2i.getWidth();
|
||||
int l = j + rect2i.getHeight();
|
||||
fill(matrices, i, j, k, l, -16776961);
|
||||
}
|
||||
RenderSystem.disableColorLogicOp();
|
||||
}
|
||||
|
||||
private Position screenPositionToAbsolutePosition(Position position) {
|
||||
return new Position(position.x - (this.width - WIDTH) / 2 - 36, position.y - 32);
|
||||
}
|
||||
|
||||
private Position absolutePositionToScreenPosition(Position position) {
|
||||
return new Position(position.x + (this.width - WIDTH) / 2 + 36, position.y + 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
if (super.mouseClicked(mouseX, mouseY, button)) {
|
||||
return true;
|
||||
}
|
||||
if (button == 0) {
|
||||
long l = Util.getMeasuringTimeMs();
|
||||
int i = this.getPageContent().getCursorPosition(this.textRenderer, this.screenPositionToAbsolutePosition(new Position((int)mouseX, (int)mouseY)));
|
||||
if (i >= 0) {
|
||||
if (i == this.lastClickIndex && l - this.lastClickTime < 250L) {
|
||||
if (!this.currentPageSelectionManager.isSelecting()) {
|
||||
this.selectCurrentWord(i);
|
||||
} else {
|
||||
this.currentPageSelectionManager.selectAll();
|
||||
}
|
||||
} else {
|
||||
this.currentPageSelectionManager.moveCursorTo(i, Screen.hasShiftDown());
|
||||
}
|
||||
this.invalidatePageContent();
|
||||
}
|
||||
this.lastClickIndex = i;
|
||||
this.lastClickTime = l;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void selectCurrentWord(int cursor) {
|
||||
String string = this.getText();
|
||||
this.currentPageSelectionManager.setSelection(TextHandler.moveCursorByWords(string, -1, cursor, false), TextHandler.moveCursorByWords(string, 1, cursor, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
if (super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) {
|
||||
return true;
|
||||
}
|
||||
if (button == 0) {
|
||||
int i = this.getPageContent().getCursorPosition(this.textRenderer, this.screenPositionToAbsolutePosition(new Position((int)mouseX, (int)mouseY)));
|
||||
this.currentPageSelectionManager.moveCursorTo(i, true);
|
||||
this.invalidatePageContent();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private PageContent getPageContent() {
|
||||
if (this.pageContent == null) {
|
||||
this.pageContent = this.createPageContent();
|
||||
}
|
||||
return this.pageContent;
|
||||
}
|
||||
|
||||
private void invalidatePageContent() {
|
||||
this.pageContent = null;
|
||||
}
|
||||
|
||||
private PageContent createPageContent() {
|
||||
String content = this.getText();
|
||||
if (content.isEmpty()) {
|
||||
return PageContent.EMPTY;
|
||||
}
|
||||
int i = this.currentPageSelectionManager.getSelectionStart();
|
||||
int j = this.currentPageSelectionManager.getSelectionEnd();
|
||||
IntArrayList intList = new IntArrayList();
|
||||
ArrayList<Line> list = Lists.newArrayList();
|
||||
MutableInt lineIndexM = new MutableInt();
|
||||
MutableBoolean mutableBoolean = new MutableBoolean();
|
||||
TextHandler textHandler = this.textRenderer.getTextHandler();
|
||||
textHandler.wrapLines(content, MAX_TEXT_WIDTH, Style.EMPTY, true, (style, start, end) -> {
|
||||
int lineIndex = lineIndexM.getAndIncrement();
|
||||
String string = content.substring(start, end);
|
||||
mutableBoolean.setValue(string.endsWith("\n"));
|
||||
String string2 = StringUtils.stripEnd(string, " \n");
|
||||
int y = lineIndex * this.textRenderer.fontHeight;
|
||||
Position position = this.absolutePositionToScreenPosition(new Position(0, y));
|
||||
intList.add(start);
|
||||
list.add(new Line(style, string2, position.x, position.y));
|
||||
});
|
||||
int[] is = intList.toIntArray();
|
||||
boolean bl = i == content.length();
|
||||
int l;
|
||||
Position position;
|
||||
if (bl && mutableBoolean.isTrue()) {
|
||||
position = new Position(0, list.size() * this.textRenderer.fontHeight);
|
||||
} else {
|
||||
int k = getLineFromOffset(is, i);
|
||||
l = this.textRenderer.getWidth(content.substring(is[k], i));
|
||||
position = new Position(l, k * this.textRenderer.fontHeight);
|
||||
}
|
||||
ArrayList<Rect2i> list2 = Lists.newArrayList();
|
||||
if (i != j) {
|
||||
int o;
|
||||
l = Math.min(i, j);
|
||||
int m = Math.max(i, j);
|
||||
int n = getLineFromOffset(is, l);
|
||||
if (n == (o = getLineFromOffset(is, m))) {
|
||||
int p = n * this.textRenderer.fontHeight;
|
||||
int q = is[n];
|
||||
list2.add(this.getLineSelectionRectangle(content, textHandler, l, m, p, q));
|
||||
} else {
|
||||
int p = n + 1 > is.length ? content.length() : is[n + 1];
|
||||
list2.add(this.getLineSelectionRectangle(content, textHandler, l, p, n * this.textRenderer.fontHeight, is[n]));
|
||||
for (int q = n + 1; q < o; ++q) {
|
||||
int r = q * this.textRenderer.fontHeight;
|
||||
String string2 = content.substring(is[q], is[q + 1]);
|
||||
int s = (int)textHandler.getWidth(string2);
|
||||
list2.add(this.getRectFromCorners(new Position(0, r), new Position(s, r + this.textRenderer.fontHeight)));
|
||||
}
|
||||
list2.add(this.getLineSelectionRectangle(content, textHandler, is[o], m, o * this.textRenderer.fontHeight, is[o]));
|
||||
}
|
||||
}
|
||||
return new PageContent(content, position, bl, is, list.toArray(new Line[0]), list2.toArray(new Rect2i[0]));
|
||||
}
|
||||
|
||||
static int getLineFromOffset(int[] lineStarts, int position) {
|
||||
int i = Arrays.binarySearch(lineStarts, position);
|
||||
if (i < 0) {
|
||||
return -(i + 2);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private Rect2i getLineSelectionRectangle(String string, TextHandler handler, int selectionStart, int selectionEnd, int lineY, int lineStart) {
|
||||
String string2 = string.substring(lineStart, selectionStart);
|
||||
String string3 = string.substring(lineStart, selectionEnd);
|
||||
Position position = new Position((int)handler.getWidth(string2), lineY);
|
||||
Position position2 = new Position((int)handler.getWidth(string3), lineY + this.textRenderer.fontHeight);
|
||||
return this.getRectFromCorners(position, position2);
|
||||
}
|
||||
|
||||
private Rect2i getRectFromCorners(Position start, Position end) {
|
||||
Position position = this.absolutePositionToScreenPosition(start);
|
||||
Position position2 = this.absolutePositionToScreenPosition(end);
|
||||
int i = Math.min(position.x, position2.x);
|
||||
int j = Math.max(position.x, position2.x);
|
||||
int k = Math.min(position.y, position2.y);
|
||||
int l = Math.max(position.y, position2.y);
|
||||
return new Rect2i(i, k, j - i, l - k);
|
||||
}
|
||||
|
||||
static class PageContent {
|
||||
static final PageContent EMPTY = new PageContent("", new Position(0, 0), true, new int[]{0}, new Line[]{new Line(Style.EMPTY, "", 0, 0)}, new Rect2i[0]);
|
||||
private final String pageContent;
|
||||
final Position position;
|
||||
final boolean atEnd;
|
||||
private final int[] lineStarts;
|
||||
final Line[] lines;
|
||||
final Rect2i[] selectionRectangles;
|
||||
|
||||
public PageContent(String pageContent, Position position, boolean atEnd, int[] lineStarts, Line[] lines, Rect2i[] selectionRectangles) {
|
||||
this.pageContent = pageContent;
|
||||
this.position = position;
|
||||
this.atEnd = atEnd;
|
||||
this.lineStarts = lineStarts;
|
||||
this.lines = lines;
|
||||
this.selectionRectangles = selectionRectangles;
|
||||
}
|
||||
|
||||
public int getCursorPosition(TextRenderer renderer, Position position) {
|
||||
int i = position.y / renderer.fontHeight;
|
||||
if (i < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (i >= this.lines.length) {
|
||||
return this.pageContent.length();
|
||||
}
|
||||
Line line = this.lines[i];
|
||||
return this.lineStarts[i] + renderer.getTextHandler().getTrimmedLength(line.content, position.x, line.style);
|
||||
}
|
||||
|
||||
public int getVerticalOffset(int position, int lines) {
|
||||
int m;
|
||||
int i = getLineFromOffset(this.lineStarts, position);
|
||||
int j = i + lines;
|
||||
if (0 <= j && j < this.lineStarts.length) {
|
||||
int k = position - this.lineStarts[i];
|
||||
int l = this.lines[j].content.length();
|
||||
m = this.lineStarts[j] + Math.min(k, l);
|
||||
} else {
|
||||
m = position;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
public int getLineStart(int position) {
|
||||
int i = getLineFromOffset(this.lineStarts, position);
|
||||
return this.lineStarts[i];
|
||||
}
|
||||
|
||||
public int getLineEnd(int position) {
|
||||
int i = getLineFromOffset(this.lineStarts, position);
|
||||
return this.lineStarts[i] + this.lines[i].content.length();
|
||||
}
|
||||
}
|
||||
|
||||
record Line(Style style, String content, Text text, int x, int y) {
|
||||
public Line(Style style, String content, int x, int y) {
|
||||
this(style, content, Text.literal(content).setStyle(style), x, y);
|
||||
}
|
||||
}
|
||||
|
||||
record Position(int x, int y) { }
|
||||
}
|
|
@ -16,6 +16,7 @@ public class WidgetState<T> {
|
|||
public Text error;
|
||||
public boolean inLimits = true;
|
||||
public String tempValue;
|
||||
public boolean managedTemp = true;
|
||||
public T cachedValue;
|
||||
@Nullable public WidgetFactory factory;
|
||||
|
||||
|
@ -37,7 +38,7 @@ public class WidgetState<T> {
|
|||
|
||||
public void updateCache(T newValue) {
|
||||
cachedValue = newValue;
|
||||
tempValue = newValue == null ? null : newValue.toString();
|
||||
if (managedTemp) tempValue = newValue == null ? null : newValue.toString();
|
||||
}
|
||||
|
||||
public void writeToEntry() throws IllegalAccessException {
|
||||
|
|
|
@ -1,19 +1,26 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry;
|
||||
|
||||
import io.gitlab.jfronny.commons.ref.R;
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders;
|
||||
import io.gitlab.jfronny.commons.throwable.Try;
|
||||
import io.gitlab.jfronny.gson.JsonElement;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.libjf.LibJf;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.type.Type;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ui.tiny.WidgetFactory;
|
||||
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.EditorScreen;
|
||||
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.WidgetState;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import net.minecraft.client.toast.SystemToast;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
@ -75,8 +82,8 @@ public class EntryInfoWidgetBuilder {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
LibJf.LOGGER.error("Unsupported entry type in " + info.getName() + ": " + type.getName() + " - not displaying config control");
|
||||
factory = null;
|
||||
LibJf.LOGGER.error("Unsupported entry type in " + info.getName() + ": " + type.getName() + " - displaying fallback");
|
||||
factory = jsonScreen(config, info, state);
|
||||
}
|
||||
|
||||
Try.orThrow(() -> state.initialize(info, knownStates, factory, config.getTranslationPrefix()));
|
||||
|
@ -147,6 +154,55 @@ public class EntryInfoWidgetBuilder {
|
|||
};
|
||||
}
|
||||
|
||||
private static <T> WidgetFactory jsonScreen(ConfigCategory config, EntryInfo<T> info, WidgetState<T> state) {
|
||||
state.managedTemp = false;
|
||||
state.tempValue = null;
|
||||
return (screen, textRenderer) -> new WidgetFactory.Widget(
|
||||
R::nop,
|
||||
ButtonWidget.builder(Text.translatable("libjf-config-core-v1.edit"), button -> {
|
||||
final String jsonified;
|
||||
if (state.tempValue == null) {
|
||||
try {
|
||||
jsonified = GsonHolders.CONFIG.getGson().toJson(state.cachedValue);
|
||||
} catch (Throwable e) {
|
||||
LibJf.LOGGER.error("Could not stringify element", e);
|
||||
SystemToast.add(
|
||||
screen.getClient().getToastManager(),
|
||||
SystemToast.Type.PACK_LOAD_FAILURE,
|
||||
Text.translatable("libjf-config-ui-tiny-v1.entry.json.read.fail.title"),
|
||||
Text.translatable("libjf-config-ui-tiny-v1.entry.json.read.fail.description")
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
jsonified = state.tempValue;
|
||||
}
|
||||
screen.getClient().setScreen(new EditorScreen(
|
||||
Text.translatable(config.getTranslationPrefix() + info.getName()),
|
||||
screen,
|
||||
jsonified,
|
||||
json -> {
|
||||
try {
|
||||
state.updateCache(GsonHolders.CONFIG.getGson().fromJson(json, info.getValueType().asClass()));
|
||||
state.tempValue = null;
|
||||
} catch (Throwable e) {
|
||||
LibJf.LOGGER.error("Could not write element", e);
|
||||
SystemToast.add(
|
||||
screen.getClient().getToastManager(),
|
||||
SystemToast.Type.PACK_LOAD_FAILURE,
|
||||
Text.translatable("libjf-config-ui-tiny-v1.entry.json.write.fail.title"),
|
||||
Text.translatable("libjf-config-ui-tiny-v1.entry.json.write.fail.description")
|
||||
);
|
||||
state.tempValue = json;
|
||||
}
|
||||
}
|
||||
));
|
||||
})
|
||||
.dimensions(screen.width - 110, 0, info.getWidth(), 20)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
private static <T extends Number> WidgetFactory slider(EntryInfo info, WidgetState state, Function<T, Double> t2d, Function<Double, T> d2t, boolean wholeNumber) {
|
||||
double min = info.getMinValue();
|
||||
double max = info.getMaxValue();
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"libjf-config-ui-tiny-v1.entry.json.read.fail.title": "Could not read",
|
||||
"libjf-config-ui-tiny-v1.entry.json.read.fail.description": "The given entry could not be stringified. Please edit the config manually"
|
||||
}
|
Loading…
Reference in New Issue