LibJF/libjf-config-ui-tiny-v1/src/client/java/io/gitlab/jfronny/libjf/config/impl/ui/tiny/TinyConfigScreen.java

168 lines
6.5 KiB
Java

package io.gitlab.jfronny.libjf.config.impl.ui.tiny;
import io.gitlab.jfronny.commons.throwable.Try;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory;
import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder;
import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.EntryListWidget;
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.gui.screen.Screen;
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 java.util.*;
@Environment(EnvType.CLIENT)
public class TinyConfigScreen extends Screen {
public static Text getTitle(String categoryPath) {
final String titlePath = categoryPath + "title";
if (JfConfigSafe.TRANSLATION_SUPPLIER.apply(titlePath) != null) {
return Text.translatable(titlePath);
}
final String alternatePath = categoryPath.length() == 0 ? "" : categoryPath.substring(0, categoryPath.length() - 1);
if (JfConfigSafe.TRANSLATION_SUPPLIER.apply(alternatePath) != null) {
return Text.translatable(alternatePath);
}
return Text.translatable(titlePath);
}
private final Screen parent;
private final ConfigCategory config;
public final List<WidgetState<?>> widgets;
private final Placeholder<EntryListWidget> placeholder;
private final TabManager tabManager = new TabManager(a -> selectTab(((TinyConfigTabWrapper)a).getTab()), a -> {});
private List<TinyConfigTab> tabs;
public ButtonWidget done;
private boolean reload = false;
public TinyConfigScreen(ConfigCategory config, Screen parent) {
super(getTitle(config.getTranslationPrefix()));
this.parent = parent;
this.config = config;
this.widgets = new LinkedList<>();
this.placeholder = new Placeholder<>(null);
}
@Override
public void tick() {
super.tick();
tabManager.tick();
}
@Override
protected void init() {
super.init();
this.done = ButtonWidget.builder(ScreenTexts.DONE, button -> {
for (WidgetState<?> state : widgets) {
Try.orElse(state::writeToEntry, e -> LibJf.LOGGER.error("Could not write config data to class", e));
}
config.getRoot().write();
Objects.requireNonNull(client).setScreen(parent);
})
.position(this.width / 2 + 4, this.height - 28)
.size(150, 20)
.build();
if (!reload) {
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));
}
TabNavigationWidget tabNavigation = TabNavigationWidget.builder(tabManager, this.width)
.tabs(tabs.toArray(TinyConfigTab[]::new))
.build();
if (tabs.size() > 1) this.addDrawableChild(tabNavigation);
tabNavigation.selectTab(0, false);
tabNavigation.init();
if (tabs.size() == 1 && !config.getPresets().isEmpty()) {
this.addDrawableChild(ButtonWidget.builder(Text.translatable("libjf-config-v1.presets"),
button -> Objects.requireNonNull(client).setScreen(new PresetsScreen(this, config)))
.position(4, 6)
.size(80, 20)
.build());
}
this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL,
button -> Objects.requireNonNull(client).setScreen(parent))
.position(this.width / 2 - 154, this.height - 28)
.size(150, 20)
.build());
this.addSelectableChild(this.placeholder);
this.addDrawableChild(done);
reload = true;
}
private void selectTab(TinyConfigTab tab) {
placeholder.setChild(tab.getList());
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices);
this.placeholder.render(matrices, mouseX, mouseY, delta);
drawCenteredTextWithShadow(matrices, textRenderer, title, width / 2, 15, 0xFFFFFF);
Optional<Text> hovered = placeholder.getChild().getHoveredEntryTitle(mouseY);
if (hovered.isPresent()) {
for (WidgetState<?> info : widgets) {
Text text = hovered.get();
MutableText name = Text.translatable(info.id);
boolean showTooltip = text.equals(name);
String tooltipKey = info.id + ".tooltip";
if (showTooltip && info.error != null) {
showTooltip = false;
renderTooltip(matrices, info.error, mouseX, mouseY);
}
if (showTooltip && I18n.hasTranslation(tooltipKey)) {
showTooltip = false;
List<Text> tooltip = new ArrayList<>();
for (String str : I18n.translate(tooltipKey).split("\n"))
tooltip.add(Text.literal(str));
renderTooltip(matrices, tooltip, mouseX, mouseY);
}
}
}
super.render(matrices,mouseX,mouseY,delta);
}
@Override
public void close() {
Objects.requireNonNull(client).setScreen(parent);
}
public MinecraftClient getClient() {
return Objects.requireNonNull(client);
}
public boolean hasClient() {
return client != null;
}
}