diff options
author | isXander <xandersmith2008@gmail.com> | 2023-05-21 12:41:45 +0100 |
---|---|---|
committer | isXander <xandersmith2008@gmail.com> | 2023-05-21 12:41:45 +0100 |
commit | 21afea0da3956f2d8cca81a54fa9820152e0c077 (patch) | |
tree | e5944f94a5f85d3fcbe048da633e62f5357fe835 /common/src/main/java/dev/isxander/yacl/gui/YACLScreen.java | |
parent | e51af159ba3eba5ebda976bea1c1957cddeee7c6 (diff) | |
download | YetAnotherConfigLib-21afea0da3956f2d8cca81a54fa9820152e0c077.tar.gz YetAnotherConfigLib-21afea0da3956f2d8cca81a54fa9820152e0c077.tar.bz2 YetAnotherConfigLib-21afea0da3956f2d8cca81a54fa9820152e0c077.zip |
Start overhauling UI
Diffstat (limited to 'common/src/main/java/dev/isxander/yacl/gui/YACLScreen.java')
-rw-r--r-- | common/src/main/java/dev/isxander/yacl/gui/YACLScreen.java | 315 |
1 files changed, 188 insertions, 127 deletions
diff --git a/common/src/main/java/dev/isxander/yacl/gui/YACLScreen.java b/common/src/main/java/dev/isxander/yacl/gui/YACLScreen.java index b3e614f..77090c8 100644 --- a/common/src/main/java/dev/isxander/yacl/gui/YACLScreen.java +++ b/common/src/main/java/dev/isxander/yacl/gui/YACLScreen.java @@ -2,10 +2,7 @@ package dev.isxander.yacl.gui; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; -import dev.isxander.yacl.api.Option; -import dev.isxander.yacl.api.OptionFlag; -import dev.isxander.yacl.api.PlaceholderCategory; -import dev.isxander.yacl.api.YetAnotherConfigLib; +import dev.isxander.yacl.api.*; import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.api.utils.MutableDimension; import dev.isxander.yacl.api.utils.OptionUtils; @@ -14,117 +11,81 @@ import dev.isxander.yacl.impl.utils.YACLConstants; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.MultiLineLabel; +import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.components.tabs.Tab; +import net.minecraft.client.gui.components.tabs.TabManager; +import net.minecraft.client.gui.components.tabs.TabNavigationBar; +import net.minecraft.client.gui.navigation.ScreenRectangle; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.tooltip.TooltipRenderUtil; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import java.io.*; import java.util.HashSet; +import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; public class YACLScreen extends Screen { public final YetAnotherConfigLib config; - private int currentCategoryIdx; private final Screen parent; - public OptionListWidget optionList; - public CategoryListWidget categoryList; - public TooltipButtonWidget finishedSaveButton, cancelResetButton, undoButton; - public SearchFieldWidget searchFieldWidget; + public final TabManager tabManager = new TabManager(this::addRenderableWidget, this::removeWidget); + public TabNavigationBar tabNavigationBar; + public Tab[] tabs; + public ScreenRectangle tabArea; public Component saveButtonMessage, saveButtonTooltipMessage; private int saveButtonMessageTime; - public YACLScreen(YetAnotherConfigLib config, Screen parent) { super(config.title()); this.config = config; this.parent = parent; - this.currentCategoryIdx = 0; } @Override protected void init() { - int columnWidth = width / 3; - int padding = columnWidth / 20; - columnWidth = Math.min(columnWidth, 400); - int paddedWidth = columnWidth - padding * 2; - - MutableDimension<Integer> actionDim = Dimension.ofInt(width / 3 / 2, height - padding - 20, paddedWidth, 20); - finishedSaveButton = new TooltipButtonWidget( - this, - actionDim.x() - actionDim.width() / 2, - actionDim.y(), - actionDim.width(), - actionDim.height(), - Component.empty(), - Component.empty(), - btn -> finishOrSave() - ); - actionDim.expand(-actionDim.width() / 2 - 2, 0).move(-actionDim.width() / 2 - 2, -22); - cancelResetButton = new TooltipButtonWidget( - this, - actionDim.x() - actionDim.width() / 2, - actionDim.y(), - actionDim.width(), - actionDim.height(), - Component.empty(), - Component.empty(), - btn -> cancelOrReset() - ); - actionDim.move(actionDim.width() + 4, 0); - undoButton = new TooltipButtonWidget( - this, - actionDim.x() - actionDim.width() / 2, - actionDim.y(), - actionDim.width(), - actionDim.height(), - Component.translatable("yacl.gui.undo"), - Component.translatable("yacl.gui.undo.tooltip"), - btn -> undo() - ); - - searchFieldWidget = new SearchFieldWidget( - this, - font, - width / 3 / 2 - paddedWidth / 2 + 1, - undoButton.getY() - 22, - paddedWidth - 2, 18, - Component.translatable("gui.recipebook.search_hint"), - Component.translatable("gui.recipebook.search_hint") - ); - - categoryList = new CategoryListWidget(minecraft, this, width, height); - addWidget(categoryList); - - updateActionAvailability(); - addRenderableWidget(searchFieldWidget); - addRenderableWidget(cancelResetButton); - addRenderableWidget(undoButton); - addRenderableWidget(finishedSaveButton); - - optionList = new OptionListWidget(this, minecraft, width, height); - addWidget(optionList); + if (tabs != null) { + closeTabs(); + } + + tabNavigationBar = TabNavigationBar.builder(tabManager, this.width) + .addTabs(tabs = config.categories() + .stream() + .map(category -> { + if (category instanceof PlaceholderCategory placeholder) + return new PlaceholderTab(placeholder); + return new CategoryTab(category); + }) + .toArray(Tab[]::new) + ) + .build(); + tabNavigationBar.selectTab(0, false); + tabNavigationBar.arrangeElements(); + ScreenRectangle navBarArea = tabNavigationBar.getRectangle(); + tabArea = new ScreenRectangle(0, navBarArea.height() - 1, this.width, this.height - navBarArea.height() + 1); + tabManager.setTabArea(tabArea); + addRenderableWidget(tabNavigationBar); config.initConsumer().accept(this); } @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { - renderBackground(graphics); + renderDirtBackground(graphics); super.render(graphics, mouseX, mouseY, delta); - categoryList.render(graphics, mouseX, mouseY, delta); - searchFieldWidget.render(graphics, mouseX, mouseY, delta); - optionList.render(graphics, mouseX, mouseY, delta); - - categoryList.postRender(graphics, mouseX, mouseY, delta); - optionList.postRender(graphics, mouseX, mouseY, delta); for (GuiEventListener child : children()) { if (child instanceof TooltipButtonWidget tooltipButtonWidget) { @@ -171,54 +132,8 @@ public class YACLScreen extends Screen { } @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (optionList.keyPressed(keyCode, scanCode, modifiers)) { - return true; - } - - return super.keyPressed(keyCode, scanCode, modifiers); - } - - @Override - public boolean charTyped(char chr, int modifiers) { - if (optionList.charTyped(chr, modifiers)) { - return true; - } - - return super.charTyped(chr, modifiers); - } - - public void changeCategory(int idx) { - if (idx == currentCategoryIdx) - return; - - if (idx != -1 && config.categories().get(idx) instanceof PlaceholderCategory placeholderCategory) { - minecraft.setScreen(placeholderCategory.screen().apply(minecraft, this)); - } else { - currentCategoryIdx = idx; - optionList.refreshOptions(); - } - } - - public int getCurrentCategoryIdx() { - return currentCategoryIdx; - } - - private void updateActionAvailability() { - boolean pendingChanges = pendingChanges(); - - undoButton.active = pendingChanges; - finishedSaveButton.setMessage(pendingChanges ? Component.translatable("yacl.gui.save") : GuiUtils.translatableFallback("yacl.gui.done", CommonComponents.GUI_DONE)); - finishedSaveButton.setTooltip(pendingChanges ? Component.translatable("yacl.gui.save.tooltip") : Component.translatable("yacl.gui.finished.tooltip")); - cancelResetButton.setMessage(pendingChanges ? GuiUtils.translatableFallback("yacl.gui.cancel", CommonComponents.GUI_CANCEL) : Component.translatable("controls.reset")); - cancelResetButton.setTooltip(pendingChanges ? Component.translatable("yacl.gui.cancel.tooltip") : Component.translatable("yacl.gui.reset.tooltip")); - } - - @Override public void tick() { - searchFieldWidget.tick(); - - updateActionAvailability(); + tabManager.tickCurrent(); if (saveButtonMessage != null) { if (saveButtonMessageTime > 140) { @@ -227,9 +142,9 @@ public class YACLScreen extends Screen { saveButtonMessageTime = 0; } else { saveButtonMessageTime++; - finishedSaveButton.setMessage(saveButtonMessage); + //finishedSaveButton.setMessage(saveButtonMessage); if (saveButtonTooltipMessage != null) { - finishedSaveButton.setTooltip(saveButtonTooltipMessage); + //finishedSaveButton.setTooltip(saveButtonTooltipMessage); } } } @@ -266,6 +181,19 @@ public class YACLScreen extends Screen { @Override public void onClose() { minecraft.setScreen(parent); + closeTabs(); + } + + private void closeTabs() { + for (Tab tab : tabs) { + if (tab instanceof Closeable closeable) { + try { + closeable.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } } public static void renderMultilineTooltip(GuiGraphics graphics, Font font, MultiLineLabel text, int centerX, int yAbove, int yBelow, int screenWidth, int screenHeight) { @@ -312,4 +240,137 @@ public class YACLScreen extends Screen { graphics.pose().popPose(); } } + + private class CategoryTab implements Tab, Closeable { + private final ConfigCategory category; + + private final TabListWidget<OptionListWidget> optionList; + private final Button saveFinishedButton; + private final Button cancelResetButton; + private final Button undoButton; + private final SearchFieldWidget searchField; + private OptionDescriptionWidget descriptionWidget; + + public CategoryTab(ConfigCategory category) { + this.category = category; + + this.optionList = new TabListWidget<>( + () -> new ScreenRectangle(tabArea.position(), tabArea.width() / 3 * 2 + 1, tabArea.height()), + new OptionListWidget(YACLScreen.this, category, minecraft, 0, 0, width / 3 * 2 + 1, height, hoveredOption -> { + descriptionWidget.setOptionDescription(hoveredOption.description()); + }) + ); + + int columnWidth = width / 3; + int padding = columnWidth / 20; + columnWidth = Math.min(columnWidth, 400); + int paddedWidth = columnWidth - padding * 2; + MutableDimension<Integer> actionDim = Dimension.ofInt(width / 3 * 2 + width / 6, height - padding - 20, paddedWidth, 20); + + saveFinishedButton = Button.builder(Component.literal("Done"), btn -> finishOrSave()) + .pos(actionDim.x() - actionDim.width() / 2, actionDim.y()) + .size(actionDim.width(), actionDim.height()) + .build(); + + actionDim.expand(-actionDim.width() / 2 - 2, 0).move(-actionDim.width() / 2 - 2, -22); + cancelResetButton = Button.builder(Component.literal("Cancel"), btn -> cancelOrReset()) + .pos(actionDim.x() - actionDim.width() / 2, actionDim.y()) + .size(actionDim.width(), actionDim.height()) + .build(); + + actionDim.move(actionDim.width() + 4, 0); + undoButton = Button.builder(Component.translatable("yacl.gui.undo"), btn -> undo()) + .pos(actionDim.x() - actionDim.width() / 2, actionDim.y()) + .size(actionDim.width(), actionDim.height()) + .tooltip(Tooltip.create(Component.translatable("yacl.gui.undo.tooltip"))) + .build(); + + searchField = new SearchFieldWidget( + YACLScreen.this, + font, + width / 3 * 2 + width / 6 - paddedWidth / 2 + 1, + undoButton.getY() - 22, + paddedWidth - 2, 18, + Component.translatable("gui.recipebook.search_hint"), + Component.translatable("gui.recipebook.search_hint"), + searchQuery -> optionList.getList().updateSearchQuery(searchQuery) + ); + + descriptionWidget = new OptionDescriptionWidget( + () -> new ScreenRectangle( + width / 3 * 2 + padding, + tabArea.top() + padding, + paddedWidth, + searchField.getY() - 1 - tabArea.top() - padding * 2 + ), + null + ); + + updateButtons(); + } + + @Override + public Component getTabTitle() { + return category.name(); + } + + @Override + public void visitChildren(Consumer<AbstractWidget> consumer) { + consumer.accept(optionList); + consumer.accept(saveFinishedButton); + consumer.accept(cancelResetButton); + consumer.accept(undoButton); + consumer.accept(searchField); + consumer.accept(descriptionWidget); + } + + @Override + public void doLayout(ScreenRectangle screenRectangle) { + + } + + @Override + public void tick() { + updateButtons(); + searchField.tick(); + } + + private void updateButtons() { + boolean pendingChanges = pendingChanges(); + + undoButton.active = pendingChanges; + saveFinishedButton.setMessage(pendingChanges ? Component.translatable("yacl.gui.save") : GuiUtils.translatableFallback("yacl.gui.done", CommonComponents.GUI_DONE)); + saveFinishedButton.setTooltip(Tooltip.create(pendingChanges ? Component.translatable("yacl.gui.save.tooltip") : Component.translatable("yacl.gui.finished.tooltip"))); + cancelResetButton.setMessage(pendingChanges ? GuiUtils.translatableFallback("yacl.gui.cancel", CommonComponents.GUI_CANCEL) : Component.translatable("controls.reset")); + cancelResetButton.setTooltip(Tooltip.create(pendingChanges ? Component.translatable("yacl.gui.cancel.tooltip") : Component.translatable("yacl.gui.reset.tooltip"))); + } + + @Override + public void close() { + descriptionWidget.close(); + } + } + + private class PlaceholderTab implements Tab { + private final PlaceholderCategory category; + + public PlaceholderTab(PlaceholderCategory category) { + this.category = category; + } + + @Override + public Component getTabTitle() { + return category.name(); + } + + @Override + public void visitChildren(Consumer<AbstractWidget> consumer) { + + } + + @Override + public void doLayout(ScreenRectangle screenRectangle) { + minecraft.setScreen(category.screen().apply(minecraft, YACLScreen.this)); + } + } } |