2022-08-26 20:51:00 +02:00
|
|
|
package io.gitlab.jfronny.libjf.config.impl.ui.tiny;
|
2021-05-15 15:34:19 +02:00
|
|
|
|
2022-04-29 15:48:27 +02:00
|
|
|
import io.gitlab.jfronny.commons.throwable.Try;
|
2022-08-21 22:34:55 +02:00
|
|
|
import io.gitlab.jfronny.libjf.LibJf;
|
2022-08-26 20:51:00 +02:00
|
|
|
import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory;
|
2023-03-11 21:21:53 +01:00
|
|
|
import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder;
|
2022-08-28 21:24:26 +02:00
|
|
|
import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
|
2022-08-26 20:51:00 +02:00
|
|
|
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.EntryListWidget;
|
2023-03-18 13:57:01 +01:00
|
|
|
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry.WidgetState;
|
2022-08-26 20:51:00 +02:00
|
|
|
import io.gitlab.jfronny.libjf.config.impl.ui.tiny.presets.PresetsScreen;
|
2021-05-15 15:34:19 +02:00
|
|
|
import net.fabricmc.api.EnvType;
|
|
|
|
import net.fabricmc.api.Environment;
|
2023-03-11 21:21:53 +01:00
|
|
|
import net.minecraft.client.MinecraftClient;
|
2023-08-13 18:40:03 +02:00
|
|
|
import net.minecraft.client.font.TextRenderer;
|
2023-06-09 15:04:53 +02:00
|
|
|
import net.minecraft.client.gui.DrawContext;
|
2023-03-18 14:58:44 +01:00
|
|
|
import net.minecraft.client.gui.ScreenRect;
|
2021-05-15 15:34:19 +02:00
|
|
|
import net.minecraft.client.gui.screen.Screen;
|
2023-03-11 21:21:53 +01:00
|
|
|
import net.minecraft.client.gui.tab.TabManager;
|
2021-05-15 15:34:19 +02:00
|
|
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
2023-03-11 21:21:53 +01:00
|
|
|
import net.minecraft.client.gui.widget.TabNavigationWidget;
|
2021-05-15 15:34:19 +02:00
|
|
|
import net.minecraft.client.resource.language.I18n;
|
2022-08-28 21:24:26 +02:00
|
|
|
import net.minecraft.screen.ScreenTexts;
|
|
|
|
import net.minecraft.text.MutableText;
|
|
|
|
import net.minecraft.text.Text;
|
2023-08-13 18:40:03 +02:00
|
|
|
import net.minecraft.util.math.MathHelper;
|
2021-05-15 15:34:19 +02:00
|
|
|
|
2021-12-30 15:11:20 +01:00
|
|
|
import java.util.*;
|
2021-05-15 15:34:19 +02:00
|
|
|
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
|
|
public class TinyConfigScreen extends Screen {
|
2022-08-28 21:24:26 +02:00
|
|
|
public static Text getTitle(String categoryPath) {
|
|
|
|
final String titlePath = categoryPath + "title";
|
|
|
|
if (JfConfigSafe.TRANSLATION_SUPPLIER.apply(titlePath) != null) {
|
|
|
|
return Text.translatable(titlePath);
|
|
|
|
}
|
2023-08-13 18:40:03 +02:00
|
|
|
final String alternatePath = categoryPath.isEmpty() ? "" : categoryPath.substring(0, categoryPath.length() - 1);
|
2022-08-28 21:24:26 +02:00
|
|
|
if (JfConfigSafe.TRANSLATION_SUPPLIER.apply(alternatePath) != null) {
|
|
|
|
return Text.translatable(alternatePath);
|
|
|
|
}
|
|
|
|
return Text.translatable(titlePath);
|
|
|
|
}
|
2021-05-15 15:34:19 +02:00
|
|
|
private final Screen parent;
|
2022-08-21 22:34:55 +02:00
|
|
|
private final ConfigCategory config;
|
2023-03-22 15:01:55 +01:00
|
|
|
public final List<WidgetState<?>> widgets; // Filled in from TinyConfigTab
|
2023-03-11 21:21:53 +01:00
|
|
|
private final Placeholder<EntryListWidget> placeholder;
|
|
|
|
private final TabManager tabManager = new TabManager(a -> selectTab(((TinyConfigTabWrapper)a).getTab()), a -> {});
|
|
|
|
private List<TinyConfigTab> tabs;
|
2023-08-13 18:40:03 +02:00
|
|
|
private final boolean considerTabs;
|
2023-03-11 21:21:53 +01:00
|
|
|
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);
|
2023-08-13 18:40:03 +02:00
|
|
|
|
|
|
|
this.considerTabs = config.getEntries().isEmpty()
|
|
|
|
&& config.getPresets().keySet().stream().allMatch(s -> s.equals(CategoryBuilder.CONFIG_PRESET_DEFAULT))
|
2023-08-13 19:48:21 +02:00
|
|
|
&& config.getReferencedConfigs().isEmpty()
|
|
|
|
&& JfConfigSafe.TRANSLATION_SUPPLIER.apply(config.getTranslationPrefix() + "tooltip") == null;
|
2023-03-11 21:21:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void tick() {
|
|
|
|
super.tick();
|
|
|
|
tabManager.tick();
|
|
|
|
}
|
2021-05-15 15:34:19 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void init() {
|
|
|
|
super.init();
|
|
|
|
|
2023-03-11 21:21:53 +01:00
|
|
|
if (!reload) {
|
2023-03-18 14:58:44 +01:00
|
|
|
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);
|
|
|
|
})
|
|
|
|
.dimensions(this.width / 2 + 4, this.height - 28, 150, 20)
|
|
|
|
.build();
|
|
|
|
} else done.setPosition(width / 2 + 4, height - 28);
|
2022-01-08 20:02:15 +01:00
|
|
|
|
2023-08-13 18:40:03 +02:00
|
|
|
updateTabs();
|
|
|
|
|
2023-03-11 21:21:53 +01:00
|
|
|
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();
|
|
|
|
|
2023-03-18 14:58:44 +01:00
|
|
|
this.addDrawableChild(ButtonWidget.builder(ScreenTexts.CANCEL,
|
|
|
|
button -> Objects.requireNonNull(client).setScreen(parent))
|
|
|
|
.dimensions(this.width / 2 - 154, this.height - 28, 150, 20)
|
|
|
|
.build());
|
|
|
|
|
|
|
|
this.addDrawableChild(done);
|
|
|
|
|
2023-03-11 21:21:53 +01:00
|
|
|
if (tabs.size() == 1 && !config.getPresets().isEmpty()) {
|
2022-12-07 19:54:35 +01:00
|
|
|
this.addDrawableChild(ButtonWidget.builder(Text.translatable("libjf-config-v1.presets"),
|
2023-03-22 15:01:55 +01:00
|
|
|
button -> Objects.requireNonNull(client).setScreen(new PresetsScreen(this, config, this::afterSelectPreset)))
|
2023-03-18 14:58:44 +01:00
|
|
|
.dimensions(4, 6, 80, 20)
|
2022-12-07 19:54:35 +01:00
|
|
|
.build());
|
2022-08-27 17:41:56 +02:00
|
|
|
}
|
2022-01-08 20:02:15 +01:00
|
|
|
|
2023-03-11 21:21:53 +01:00
|
|
|
this.addSelectableChild(this.placeholder);
|
2023-03-18 14:58:44 +01:00
|
|
|
|
|
|
|
// Sizing is also done in TinyConfigTab. Keep these in sync!
|
2023-06-09 15:04:53 +02:00
|
|
|
tabManager.setTabArea(new ScreenRect(0, 32, width, height - 68));
|
2023-03-11 21:21:53 +01:00
|
|
|
|
|
|
|
reload = true;
|
|
|
|
}
|
|
|
|
|
2023-08-13 18:40:03 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-03-22 15:01:55 +01:00
|
|
|
public void afterSelectPreset() {
|
|
|
|
for (WidgetState<?> widget : widgets) {
|
|
|
|
widget.updateCache();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-11 21:21:53 +01:00
|
|
|
private void selectTab(TinyConfigTab tab) {
|
|
|
|
placeholder.setChild(tab.getList());
|
2021-05-15 15:34:19 +02:00
|
|
|
}
|
2022-01-08 20:02:15 +01:00
|
|
|
|
2021-05-15 15:34:19 +02:00
|
|
|
@Override
|
2023-06-09 15:04:53 +02:00
|
|
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
|
|
|
this.renderBackground(context);
|
|
|
|
this.placeholder.render(context, mouseX, mouseY, delta);
|
2021-05-15 15:34:19 +02:00
|
|
|
|
2023-07-18 21:13:03 +02:00
|
|
|
if (tabs.size() == 1) context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 16 - textRenderer.fontHeight, 0xFFFFFF);
|
2021-05-15 15:34:19 +02:00
|
|
|
|
2023-03-11 21:21:53 +01:00
|
|
|
Optional<Text> hovered = placeholder.getChild().getHoveredEntryTitle(mouseY);
|
2022-03-30 17:26:41 +02:00
|
|
|
if (hovered.isPresent()) {
|
2022-04-29 15:48:27 +02:00
|
|
|
for (WidgetState<?> info : widgets) {
|
2022-03-30 17:26:41 +02:00
|
|
|
Text text = hovered.get();
|
2023-03-11 21:21:53 +01:00
|
|
|
MutableText name = Text.translatable(info.id);
|
2021-12-30 15:11:20 +01:00
|
|
|
boolean showTooltip = text.equals(name);
|
2023-03-11 21:21:53 +01:00
|
|
|
String tooltipKey = info.id + ".tooltip";
|
2021-12-30 15:11:20 +01:00
|
|
|
if (showTooltip && info.error != null) {
|
|
|
|
showTooltip = false;
|
2023-06-09 15:04:53 +02:00
|
|
|
context.drawTooltip(textRenderer, info.error, mouseX, mouseY);
|
2021-12-30 15:11:20 +01:00
|
|
|
}
|
|
|
|
if (showTooltip && I18n.hasTranslation(tooltipKey)) {
|
|
|
|
showTooltip = false;
|
2023-03-11 21:21:53 +01:00
|
|
|
List<Text> tooltip = new ArrayList<>();
|
2021-12-30 15:11:20 +01:00
|
|
|
for (String str : I18n.translate(tooltipKey).split("\n"))
|
2023-03-11 21:21:53 +01:00
|
|
|
tooltip.add(Text.literal(str));
|
2023-06-09 15:04:53 +02:00
|
|
|
context.drawTooltip(textRenderer, tooltip, mouseX, mouseY);
|
2021-05-15 15:34:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-06-09 15:04:53 +02:00
|
|
|
super.render(context, mouseX, mouseY, delta);
|
2021-05-15 15:34:19 +02:00
|
|
|
}
|
2022-01-08 20:02:15 +01:00
|
|
|
|
|
|
|
@Override
|
2022-02-12 09:52:43 +01:00
|
|
|
public void close() {
|
2022-08-27 17:41:56 +02:00
|
|
|
Objects.requireNonNull(client).setScreen(parent);
|
2022-01-08 20:02:15 +01:00
|
|
|
}
|
2023-03-11 21:21:53 +01:00
|
|
|
|
|
|
|
public MinecraftClient getClient() {
|
|
|
|
return Objects.requireNonNull(client);
|
|
|
|
}
|
2021-05-15 15:34:19 +02:00
|
|
|
}
|