fix(config-ui-tiny): don't use tabs if they would overflow

This commit is contained in:
Johannes Frohnmeyer 2023-08-13 18:40:03 +02:00
parent 7d1de74eed
commit 60b7dbe82d
Signed by: Johannes
GPG Key ID: E76429612C2929F4
7 changed files with 117 additions and 26 deletions

View File

@ -6,18 +6,18 @@ allprojects {
group = "io.gitlab.jfronny.libjf"
}
val fabricVersion by extra("0.86.0+1.20.1")
val fabricVersion by extra("0.86.1+1.20.1")
val commonsVersion by extra("1.3-SNAPSHOT")
val gsonCompileVersion by extra("1.3-SNAPSHOT")
val modmenuVersion by extra("7.0.1")
val modmenuVersion by extra("7.2.1")
val annotationsVersion by extra("24.0.1")
val javapoetVersion by extra("1.13.0")
jfMod {
minecraftVersion = "1.20.1"
yarn("build.9")
loaderVersion = "0.14.21"
yarn("build.10")
loaderVersion = "0.14.22"
modrinth {
projectId = "libjf"

View File

@ -1,7 +1,6 @@
package io.gitlab.jfronny.libjf.config.api.v1.dsl;
import io.gitlab.jfronny.gson.JsonElement;
import io.gitlab.jfronny.gson.stream.JsonReader;
import io.gitlab.jfronny.commons.SamWithReceiver;
import io.gitlab.jfronny.libjf.config.api.v1.*;
import io.gitlab.jfronny.libjf.config.api.v1.type.Type;
import org.jetbrains.annotations.ApiStatus;
@ -46,6 +45,7 @@ public interface CategoryBuilder<Builder extends CategoryBuilder<Builder>> {
ConfigCategory build(Supplier<ConfigInstance> root);
@FunctionalInterface
@SamWithReceiver
interface CategoryBuilderFunction {
CategoryBuilder<?> apply(CategoryBuilder<?> builder);
}

View File

@ -1,5 +1,6 @@
package io.gitlab.jfronny.libjf.config.api.v1.dsl;
import io.gitlab.jfronny.commons.SamWithReceiver;
import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
import java.nio.file.Path;
@ -18,6 +19,7 @@ public interface ConfigBuilder<Builder extends ConfigBuilder<Builder>> extends C
ConfigInstance build();
@FunctionalInterface
@SamWithReceiver
interface ConfigBuilderFunction {
ConfigBuilder<?> apply(ConfigBuilder<?> builder);
}

View File

@ -11,6 +11,7 @@ import io.gitlab.jfronny.libjf.config.impl.ui.tiny.presets.PresetsScreen;
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.DrawContext;
import net.minecraft.client.gui.ScreenRect;
import net.minecraft.client.gui.screen.Screen;
@ -18,10 +19,10 @@ import net.minecraft.client.gui.tab.TabManager;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TabNavigationWidget;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.ScreenTexts;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
import java.util.*;
@ -32,7 +33,7 @@ public class TinyConfigScreen extends Screen {
if (JfConfigSafe.TRANSLATION_SUPPLIER.apply(titlePath) != null) {
return Text.translatable(titlePath);
}
final String alternatePath = categoryPath.length() == 0 ? "" : categoryPath.substring(0, categoryPath.length() - 1);
final String alternatePath = categoryPath.isEmpty() ? "" : categoryPath.substring(0, categoryPath.length() - 1);
if (JfConfigSafe.TRANSLATION_SUPPLIER.apply(alternatePath) != null) {
return Text.translatable(alternatePath);
}
@ -44,6 +45,7 @@ public class TinyConfigScreen extends Screen {
private final Placeholder<EntryListWidget> placeholder;
private final TabManager tabManager = new TabManager(a -> selectTab(((TinyConfigTabWrapper)a).getTab()), a -> {});
private List<TinyConfigTab> tabs;
private final boolean considerTabs;
public ButtonWidget done;
private boolean reload = false;
@ -53,6 +55,10 @@ public class TinyConfigScreen extends Screen {
this.config = config;
this.widgets = new LinkedList<>();
this.placeholder = new Placeholder<>(null);
this.considerTabs = config.getEntries().isEmpty()
&& config.getPresets().keySet().stream().allMatch(s -> s.equals(CategoryBuilder.CONFIG_PRESET_DEFAULT))
&& config.getReferencedConfigs().isEmpty();
}
@Override
@ -75,22 +81,10 @@ public class TinyConfigScreen extends Screen {
})
.dimensions(this.width / 2 + 4, this.height - 28, 150, 20)
.build();
if (config.getEntries().isEmpty()
&& config.getPresets().keySet().stream().allMatch(s -> s.equals(CategoryBuilder.CONFIG_PRESET_DEFAULT))
&& config.getReferencedConfigs().isEmpty()
) {
this.tabs = config.getCategories()
.values()
.stream()
.map(c -> new TinyConfigTab(this, c, textRenderer, false))
.toList();
} else {
this.tabs = List.of();
}
if (this.tabs.isEmpty()) this.tabs = List.of(new TinyConfigTab(this, config, textRenderer, true));
} else done.setPosition(width / 2 + 4, height - 28);
updateTabs();
TabNavigationWidget tabNavigation = TabNavigationWidget.builder(tabManager, this.width)
.tabs(tabs.toArray(TinyConfigTab[]::new))
.build();
@ -121,6 +115,35 @@ public class TinyConfigScreen extends Screen {
reload = true;
}
private boolean wasTabs = false;
private void updateTabs() {
boolean useTabs = considerTabs && !tabsWouldOverflow(config.getCategories().values());
if (reload) {
if (!considerTabs) return;
if (wasTabs == useTabs) return;
}
wasTabs = useTabs;
tabs = !useTabs ? List.of() : config.getCategories()
.values()
.stream()
.map(c -> new TinyConfigTab(this, c, textRenderer, false))
.toList();
if (tabs.isEmpty()) tabs = List.of(new TinyConfigTab(this, config, textRenderer, true));
}
private boolean tabsWouldOverflow(Collection<ConfigCategory> categories) {
int tabNavWidth = this.width;
int headerWidth = Math.min(400, tabNavWidth) - 28;
int singleHeaderWidth = MathHelper.roundUpToMultiple(headerWidth / categories.size(), 2);
int singleTextWidth = singleHeaderWidth - 2;
TextRenderer tr = MinecraftClient.getInstance().textRenderer;
for (ConfigCategory category : categories) {
if (tr.getWidth(getTitle(category.getTranslationPrefix())) > singleTextWidth) return true;
}
return false;
}
public void afterSelectPreset() {
for (WidgetState<?> widget : widgets) {
widget.updateCache();
@ -169,8 +192,4 @@ public class TinyConfigScreen extends Screen {
public MinecraftClient getClient() {
return Objects.requireNonNull(client);
}
public boolean hasClient() {
return client != null;
}
}

View File

@ -0,0 +1,32 @@
package io.gitlab.jfronny.libjf.config.test.tiny;
import io.gitlab.jfronny.libjf.config.api.v1.JfCustomConfig;
import io.gitlab.jfronny.libjf.config.api.v1.dsl.DSL;
public class TestConfig implements JfCustomConfig {
private int value1 = 0;
private String value2 = "";
private boolean value3 = false;
private int value4 = 0;
private String value5 = "";
private boolean value6 = false;
@Override
public void register(DSL.Defaulted dsl) {
dsl.register(builder -> builder
.category("ca1", builder1 -> builder1
.value("value1", value1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, () -> value1, v -> value1 = v)
).category("ca2", builder1 -> builder1
.value("value2", value2, () -> value2, v -> value2 = v)
).category("ca3", builder1 -> builder1
.value("value3", value3, () -> value3, v -> value3 = v)
).category("ca4", builder1 -> builder1
.value("value4", value4, -5, 12, () -> value4, v -> value4 = v)
).category("ca5", builder1 -> builder1
.value("value5", value5, () -> value5, v -> value5 = v)
).category("ca6", builder1 -> builder1
.value("value6", value6, () -> value6, v -> value6 = v)
)
);
}
}

View File

@ -0,0 +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.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.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.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.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.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"
}

View File

@ -0,0 +1,17 @@
{
"schemaVersion": 1,
"id": "libjf-config-ui-tiny-v1-testmod",
"name": "LibJF Config UI: Tiny",
"version": "1.0",
"environment": "*",
"entrypoints": {
"libjf:config": [
"io.gitlab.jfronny.libjf.config.test.tiny.TestConfig"
]
},
"custom": {
"modmenu": {
"parent": "libjf-testmod"
}
}
}