feat(config-ui-tiny): support category "tooltips" (rendered as labels and config file comments)
This commit is contained in:
parent
60b7dbe82d
commit
a312c86783
|
@ -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"
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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(", ")) + "]");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
}
|
Loading…
Reference in New Issue