feat(config-ui-tiny): support category "tooltips" (rendered as labels and config file comments)
ci/woodpecker/push/docs Pipeline failed Details
ci/woodpecker/push/jfmod Pipeline was successful Details
ci/woodpecker/tag/docs Pipeline was successful Details
ci/woodpecker/tag/jfmod Pipeline failed Details

This commit is contained in:
Johannes Frohnmeyer 2023-08-13 19:48:21 +02:00
parent 60b7dbe82d
commit a312c86783
Signed by: Johannes
GPG Key ID: E76429612C2929F4
7 changed files with 98 additions and 23 deletions

View File

@ -44,7 +44,7 @@ As a parameter, you will be provided with a defaulted DSL with which you must in
## Comments
For enums, the possible values will automatically be written to the config as comments.
You can add additional comments for entries by registering tooltips in your language file as follows:
You can add additional comments for entries or categories by registering tooltips in your language file as follows:
```json
{
"<mod id>.jfconfig.<entry>.tooltip": "Some comment"

View File

@ -101,6 +101,10 @@ public class DefaultConfigIO {
private static void writeTo(JsonWriter writer, ConfigCategory category) throws IOException {
category.fix();
String commentText;
if ((commentText = JfConfigSafe.TRANSLATION_SUPPLIER.apply(category.getTranslationPrefix() + "tooltip")) != null) {
writer.comment(commentText);
}
writer.beginObject();
String val;
for (EntryInfo<?> entry : category.getEntries()) {

View File

@ -3,7 +3,6 @@ package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders;
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
import io.gitlab.jfronny.gson.JsonElement;
import io.gitlab.jfronny.gson.stream.*;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v1.Entry;
@ -170,9 +169,9 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
@Override
public void writeTo(JsonWriter writer, String translationPrefix) throws IOException, IllegalAccessException {
T value = getValue();
String val;
if ((val = JfConfigSafe.TRANSLATION_SUPPLIER.apply(translationPrefix + getName() + ".tooltip")) != null) {
writer.comment(val);
String commentText;
if ((commentText = JfConfigSafe.TRANSLATION_SUPPLIER.apply(translationPrefix + getName() + ".tooltip")) != null) {
writer.comment(commentText);
}
if (type.isEnum()) {
writer.comment("Valid: [" + Arrays.stream(((Type.TEnum<T>)type).options()).map(Objects::toString).collect(Collectors.joining(", ")) + "]");

View File

@ -58,7 +58,8 @@ public class TinyConfigScreen extends Screen {
this.considerTabs = config.getEntries().isEmpty()
&& config.getPresets().keySet().stream().allMatch(s -> s.equals(CategoryBuilder.CONFIG_PRESET_DEFAULT))
&& config.getReferencedConfigs().isEmpty();
&& config.getReferencedConfigs().isEmpty()
&& JfConfigSafe.TRANSLATION_SUPPLIER.apply(config.getTranslationPrefix() + "tooltip") == null;
}
@Override

View File

@ -3,6 +3,7 @@ package io.gitlab.jfronny.libjf.config.impl.ui.tiny;
import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory;
import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
import io.gitlab.jfronny.libjf.config.api.v1.ui.tiny.WidgetFactory;
import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.*;
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.presets.PresetsScreen;
import net.minecraft.client.font.TextRenderer;
@ -31,7 +32,12 @@ public class TinyConfigTab implements Tab {
}
// Sizing is also done in TinyConfigScreen. Keep these in sync!
this.list = new EntryListWidget(screen.getClient(), textRenderer, screen.width, screen.height - 68, 32, screen.height - 36, 25);
this.list = new EntryListWidget(screen.getClient(), textRenderer, screen.width, screen.height - 68, 32, screen.height - 36);
String tooltipPath = config.getTranslationPrefix() + "tooltip";
if (JfConfigSafe.TRANSLATION_SUPPLIER.apply(tooltipPath) != null) {
this.list.addText(Text.translatable(tooltipPath));
}
if (isRoot) {
for (Map.Entry<String, ConfigCategory> entry : config.getCategories().entrySet()) {

View File

@ -1,5 +1,6 @@
package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry;
import io.gitlab.jfronny.libjf.LibJf;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
@ -7,22 +8,18 @@ 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.util.math.MatrixStack;
import net.minecraft.text.Text;
import net.minecraft.text.*;
import org.jetbrains.annotations.Nullable;
import java.sql.Ref;
import java.util.List;
import java.util.Optional;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import java.util.*;
import java.util.function.*;
@Environment(EnvType.CLIENT)
public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEntry> {
TextRenderer textRenderer;
public EntryListWidget(MinecraftClient client, TextRenderer tr, int width, int height, int top, int bottom, int itemHeight) {
super(client, width, height, top, bottom, itemHeight);
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;
setRenderBackground(client.world == null);
@ -45,6 +42,10 @@ public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEnt
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;
@ -67,7 +68,7 @@ public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEnt
public void refreshGrid(ScreenRect tabArea) {
updateSize(tabArea.width(), tabArea.height(), tabArea.getTop(), tabArea.getBottom());
setLeftPos(tabArea.getLeft());
for (int i = 0, len = getEntryCount(); i < len; i++) {
for (int len = getEntryCount() - 1, i = len; i >= 0; i--) {
getEntry(i).reflow(width, height);
}
}
@ -82,6 +83,70 @@ public class EntryListWidget extends ElementListWidget<EntryListWidget.ConfigEnt
}
}
@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;

View File

@ -1,21 +1,21 @@
{
"libjf-config-ui-tiny-v1-testmod.jfconfig.title": "JfConfig example",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca1.title": "Category 1",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca1.tooltip": "This is category 1",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca1.tooltip": "This is category 1\nIt has an excessively long description to test multiline descriptions and wrapping, which are required for this to look good.\nThis is supported btw.",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca1.value1": "Value 1",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca2.title": "Category 2",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca2.tooltip": "This is category 2",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca2.value1": "Value 2",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca2.value2": "Value 2",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca3.title": "Category 3",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca3.tooltip": "This is category 3",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca3.value1": "Value 3",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca3.value3": "Value 3",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca4.title": "Category 4",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca4.tooltip": "This is category 4",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca4.value1": "Value 4",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca4.value4": "Value 4",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca5.title": "Category 5",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca5.tooltip": "This is category 5",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca5.value1": "Value 5",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca5.value5": "Value 5",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca6.title": "Category 6",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca6.tooltip": "This is category 6",
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca6.value1": "Value 6"
"libjf-config-ui-tiny-v1-testmod.jfconfig.ca6.value6": "Value 6"
}