From 4c1ac893211e0b0475bb70d4e50910c1e6b12c93 Mon Sep 17 00:00:00 2001 From: The Panda Oliver Date: Mon, 9 Dec 2024 21:38:26 +0100 Subject: [PATCH] Refactor UI components for flexible layout handling Replaced static stack length management with dynamic gap sizing and layout direction handling in `StackContainer`. Updated `FocusHandler` to remove dependency on `ParentUIComponent`, simplifying the initialization and management of focus. Adjusted screen initialization in `TestScreen` to utilize a vertical layout with a configurable gap, enhancing UI modularity and maintainability. --- .../test/client/screen/TestScreen.java | 6 +- .../client/screen/BaseParentUIComponent.java | 12 ++- .../client/screen/layouts/StackContainer.java | 90 +++++++++++++++---- .../client/screen/utils/FocusHandler.java | 13 +-- 4 files changed, 88 insertions(+), 33 deletions(-) diff --git a/common-testmod/src/main/java/me/pandamods/test/client/screen/TestScreen.java b/common-testmod/src/main/java/me/pandamods/test/client/screen/TestScreen.java index 8fe17a2..f70b62b 100644 --- a/common-testmod/src/main/java/me/pandamods/test/client/screen/TestScreen.java +++ b/common-testmod/src/main/java/me/pandamods/test/client/screen/TestScreen.java @@ -23,7 +23,11 @@ public class TestScreen extends BasePLScreen { public TestScreen() { - super(StackContainer::new); + super(() -> { + StackContainer stack = StackContainer.createVerticalLayout(); + stack.setGapSize(4); + return stack; + }); } @Override diff --git a/common/src/main/java/me/pandamods/pandalib/client/screen/BaseParentUIComponent.java b/common/src/main/java/me/pandamods/pandalib/client/screen/BaseParentUIComponent.java index 52c00bf..bb48b0d 100644 --- a/common/src/main/java/me/pandamods/pandalib/client/screen/BaseParentUIComponent.java +++ b/common/src/main/java/me/pandamods/pandalib/client/screen/BaseParentUIComponent.java @@ -16,10 +16,9 @@ import me.pandamods.pandalib.client.screen.core.UIComponent; import me.pandamods.pandalib.client.screen.utils.FocusHandler; import me.pandamods.pandalib.client.screen.utils.RenderContext; -import org.jetbrains.annotations.Nullable; public abstract class BaseParentUIComponent extends BaseUIComponent implements ParentUIComponent { - protected FocusHandler focusHandler = new FocusHandler(this); + protected FocusHandler focusHandler; @Override public void render(RenderContext context, int mouseX, int mouseY, float partialTicks) { @@ -55,9 +54,14 @@ public void updateChildState(UIComponent uiComponent) { protected abstract void addChild(UIComponent UIComponent); protected abstract void removeChild(UIComponent UIComponent); + @Override + public void mount(ParentUIComponent parent) { + super.mount(parent); + this.focusHandler = parent != null ? parent.getFocusHandler() : new FocusHandler(); + } + @Override public FocusHandler getFocusHandler() { - FocusHandler focusHandler = super.getFocusHandler(); - return focusHandler != null ? focusHandler : this.focusHandler; + return this.focusHandler; } } diff --git a/common/src/main/java/me/pandamods/pandalib/client/screen/layouts/StackContainer.java b/common/src/main/java/me/pandamods/pandalib/client/screen/layouts/StackContainer.java index 60ec331..eb73047 100644 --- a/common/src/main/java/me/pandamods/pandalib/client/screen/layouts/StackContainer.java +++ b/common/src/main/java/me/pandamods/pandalib/client/screen/layouts/StackContainer.java @@ -14,30 +14,34 @@ import me.pandamods.pandalib.client.screen.BaseParentUIComponent; import me.pandamods.pandalib.client.screen.core.UIComponent; -import me.pandamods.pandalib.client.screen.utils.RenderContext; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; public class StackContainer extends BaseParentUIComponent { private final List children = new ArrayList<>(); private final List viewChildren = Collections.unmodifiableList(children); - private boolean realign = true; - private int stackLength = 0; + protected Direction direction; + protected int gapSize = 0; - @Override - protected void renderChildren(RenderContext context, int mouseX, int mouseY, float partialTicks) { - if (realign) stackLength = 0; - super.renderChildren(context, mouseX, mouseY, partialTicks); + private int contentWidth = 0; + private int contentHeight = 0; + + public static StackContainer createHorizontalLayout() { + return new StackContainer(Direction.HORIZONTAL); } - @Override - public void renderChild(UIComponent child, RenderContext context, int mouseX, int mouseY, float partialTicks) { - if (realign) child.setY(stackLength); - super.renderChild(child, context, mouseX, mouseY, partialTicks); - if (realign) stackLength += child.getHeight(); + public static StackContainer createVerticalLayout() { + return new StackContainer(Direction.VERTICAL); + } + + public StackContainer(Direction direction) { + this.direction = direction; } @Override @@ -61,10 +65,64 @@ protected void removeChild(UIComponent UIComponent) { children.remove(UIComponent); } - /** - * Realigns children next frame - */ + public void setDirection(Direction direction) { + this.direction = direction; + this.align(); + } + + public Direction getDirection() { + return direction; + } + + public void setGapSize(int gapSize) { + this.gapSize = gapSize; + } + + public int getGapSize() { + return gapSize; + } + public void align() { - realign = true; + int contentLength = 0; + int contentSize = 0; + + Iterator iterator = this.children.iterator(); + while (iterator.hasNext()) { + UIComponent child = iterator.next(); + Consumer setPos = this.direction == Direction.HORIZONTAL ? child::setX : child::setY; + Supplier getLength = this.direction == Direction.HORIZONTAL ? child::getWidth : child::getHeight; + Supplier getSize = this.direction == Direction.HORIZONTAL ? child::getHeight : child::getWidth; + + setPos.accept(contentLength); + contentLength += getLength.get(); + if (iterator.hasNext()) { + contentLength += gapSize; + } + contentSize = Math.max(contentSize, getSize.get()); + } + + switch (this.direction) { + case HORIZONTAL -> { + contentWidth = contentLength; + contentHeight = contentSize; + } + case VERTICAL -> { + contentHeight = contentLength; + contentWidth = contentSize; + } + } + } + + public int getContentWidth() { + return contentWidth; + } + + public int getContentHeight() { + return contentHeight; + } + + public enum Direction { + HORIZONTAL, + VERTICAL } } diff --git a/common/src/main/java/me/pandamods/pandalib/client/screen/utils/FocusHandler.java b/common/src/main/java/me/pandamods/pandalib/client/screen/utils/FocusHandler.java index 0aace36..25b93e7 100644 --- a/common/src/main/java/me/pandamods/pandalib/client/screen/utils/FocusHandler.java +++ b/common/src/main/java/me/pandamods/pandalib/client/screen/utils/FocusHandler.java @@ -12,22 +12,15 @@ package me.pandamods.pandalib.client.screen.utils; -import me.pandamods.pandalib.client.screen.BaseParentUIComponent; -import me.pandamods.pandalib.client.screen.core.ParentUIComponent; import me.pandamods.pandalib.client.screen.core.UIComponent; import org.jetbrains.annotations.Nullable; public class FocusHandler { - private final ParentUIComponent root; - @Nullable protected UIComponent focused; - public FocusHandler(ParentUIComponent root) { - this.root = root; - } - public void focus(UIComponent focused) { + if (this.focused == focused) return; if (this.focused != null) this.focused.onFocusLost(); this.focused = focused; if (this.focused != null) this.focused.onFocusGained(); @@ -45,8 +38,4 @@ public UIComponent getFocused() { public boolean isFocused(UIComponent component) { return focused == component; } - - public ParentUIComponent getRoot() { - return root; - } }