From bebd7e1c702c5429ca4a0346be957cd58136715b Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 16 Jul 2022 13:55:02 +0200 Subject: [PATCH] [Change] Migrated ModMenu Screen to new Layout Engine --- .../bclib/client/gui/modmenu/MainScreen.java | 58 +++++++++------- .../bclib/client/gui/modmenu/TestScreen.java | 28 ++++---- .../ui/layout/components/AbstractStack.java | 66 +++++++++++++++---- .../components/AbstractVanillaComponent.java | 8 +-- .../betterx/ui/layout/components/Button.java | 6 +- .../ui/layout/components/Checkbox.java | 6 +- .../components/CustomRenderComponent.java | 8 +-- .../betterx/ui/layout/components/Empty.java | 8 +-- .../ui/layout/components/HorizontalStack.java | 33 ++++++---- .../betterx/ui/layout/components/Image.java | 6 +- .../{Component.java => LayoutComponent.java} | 22 +++---- .../ui/layout/components/MultiLineText.java | 8 +-- .../betterx/ui/layout/components/Panel.java | 4 +- .../betterx/ui/layout/components/Range.java | 10 +-- .../betterx/ui/layout/components/Text.java | 8 +-- .../ui/layout/components/VerticalScroll.java | 22 +++---- .../ui/layout/components/VerticalStack.java | 32 +++++---- .../org/betterx/ui/layout/values/Size.java | 7 ++ .../values/{DynamicSize.java => Value.java} | 26 ++++---- .../org/betterx/ui/vanilla/LayoutScreen.java | 23 ++++--- .../ui/vanilla/LayoutScreenWithIcon.java | 52 +++++++++++++++ 21 files changed, 289 insertions(+), 152 deletions(-) rename src/main/java/org/betterx/ui/layout/components/{Component.java => LayoutComponent.java} (87%) rename src/main/java/org/betterx/ui/layout/values/{DynamicSize.java => Value.java} (78%) create mode 100644 src/main/java/org/betterx/ui/vanilla/LayoutScreenWithIcon.java diff --git a/src/main/java/org/betterx/bclib/client/gui/modmenu/MainScreen.java b/src/main/java/org/betterx/bclib/client/gui/modmenu/MainScreen.java index 8cd1fb56..d32f5027 100644 --- a/src/main/java/org/betterx/bclib/client/gui/modmenu/MainScreen.java +++ b/src/main/java/org/betterx/bclib/client/gui/modmenu/MainScreen.java @@ -1,60 +1,65 @@ package org.betterx.bclib.client.gui.modmenu; -import org.betterx.bclib.client.gui.gridlayout.*; +import org.betterx.bclib.BCLib; import org.betterx.bclib.config.ConfigKeeper; import org.betterx.bclib.config.Configs; import org.betterx.bclib.config.NamedPathConfig; import org.betterx.bclib.config.NamedPathConfig.ConfigTokenDescription; import org.betterx.bclib.config.NamedPathConfig.DependendConfigToken; +import org.betterx.ui.layout.components.*; +import org.betterx.ui.layout.values.Value; +import org.betterx.ui.vanilla.LayoutScreenWithIcon; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; -public class MainScreen extends GridScreen { +public class MainScreen extends LayoutScreenWithIcon { + static final ResourceLocation BCLIB_LOGO_LOCATION = new ResourceLocation(BCLib.MOD_ID, "icon.png"); public MainScreen(@Nullable Screen parent) { - super(parent, Component.translatable("title.bclib.modmenu.main"), 10, false); + super(parent, BCLIB_LOGO_LOCATION, Component.translatable("title.bclib.modmenu.main"), 10, 10, 20); } protected Component getComponent(NamedPathConfig config, ConfigTokenDescription option, String type) { return Component.translatable(type + ".config." + config.configID + option.getPath()); } - Map> dependentWidgets = new HashMap<>(); + Map> dependentWidgets = new HashMap<>(); protected void updateEnabledState() { dependentWidgets.forEach((cb, supl) -> cb.setEnabled(supl.get())); } @SuppressWarnings("unchecked") - protected void addRow(GridColumn grid, NamedPathConfig config, ConfigTokenDescription option) { + protected void addRow(VerticalStack grid, NamedPathConfig config, ConfigTokenDescription option) { if (ConfigKeeper.BooleanEntry.class.isAssignableFrom(option.token.type)) { addCheckbox(grid, config, (ConfigTokenDescription) option); } - grid.addSpacerRow(2); + grid.addSpacer(2); } - protected void addCheckbox(GridColumn grid, NamedPathConfig config, ConfigTokenDescription option) { + protected void addCheckbox(VerticalStack grid, NamedPathConfig config, ConfigTokenDescription option) { if (option.topPadding > 0) { - grid.addSpacerRow(option.topPadding); + grid.addSpacer(option.topPadding); } - GridRow row = grid.addRow(); + HorizontalStack row = grid.addRow(); if (option.leftPadding > 0) { row.addSpacer(option.leftPadding); } - GridCheckboxCell cb = row.addCheckbox( + Checkbox cb = row.addCheckbox( + Value.fit(), Value.fit(), getComponent(config, option, "title"), config.getRaw(option.token), - font, - (state) -> { + (caller, state) -> { config.set(option.token, state); updateEnabledState(); } @@ -71,34 +76,39 @@ public class MainScreen extends GridScreen { return false; } + @Override - protected void initLayout() { - final int BUTTON_HEIGHT = 20; + protected LayoutComponent initContent() { + + VerticalStack content = new VerticalStack(Value.fit(), Value.fit()); Configs.GENERATOR_CONFIG.getAllOptions() .stream() .filter(o -> !o.hidden) - .forEach(o -> addRow(grid, Configs.GENERATOR_CONFIG, o)); - grid.addSpacerRow(12); + .forEach(o -> addRow(content, Configs.GENERATOR_CONFIG, o)); + content.addSpacer(12); Configs.MAIN_CONFIG.getAllOptions() .stream() .filter(o -> !o.hidden) - .forEach(o -> addRow(grid, Configs.MAIN_CONFIG, o)); - grid.addSpacerRow(12); + .forEach(o -> addRow(content, Configs.MAIN_CONFIG, o)); + content.addSpacer(12); Configs.CLIENT_CONFIG.getAllOptions() .stream() .filter(o -> !o.hidden) - .forEach(o -> addRow(grid, Configs.CLIENT_CONFIG, o)); + .forEach(o -> addRow(content, Configs.CLIENT_CONFIG, o)); - grid.addSpacerRow(15); - GridRow row = grid.addRow(); + + VerticalStack grid = new VerticalStack(Value.fill(), Value.fill()); + grid.add(VerticalScroll.create(Value.fill(), Value.fill(), content)); + grid.addSpacer(8); + HorizontalStack row = grid.addRow(); row.addFiller(); - row.addButton(CommonComponents.GUI_DONE, BUTTON_HEIGHT, font, (button) -> { + grid.addButton(Value.fit(), Value.fit(), CommonComponents.GUI_DONE, (button) -> { Configs.CLIENT_CONFIG.saveChanges(); Configs.GENERATOR_CONFIG.saveChanges(); Configs.MAIN_CONFIG.saveChanges(); onClose(); - }); - grid.addSpacerRow(10); + }).alignRight(); + return grid; } } diff --git a/src/main/java/org/betterx/bclib/client/gui/modmenu/TestScreen.java b/src/main/java/org/betterx/bclib/client/gui/modmenu/TestScreen.java index d3d69dfb..a9dea023 100644 --- a/src/main/java/org/betterx/bclib/client/gui/modmenu/TestScreen.java +++ b/src/main/java/org/betterx/bclib/client/gui/modmenu/TestScreen.java @@ -3,8 +3,8 @@ package org.betterx.bclib.client.gui.modmenu; import org.betterx.bclib.BCLib; import org.betterx.ui.ColorUtil; import org.betterx.ui.layout.components.*; -import org.betterx.ui.layout.values.DynamicSize; import org.betterx.ui.layout.values.Size; +import org.betterx.ui.layout.values.Value; import org.betterx.ui.vanilla.LayoutScreen; import net.minecraft.client.gui.screens.Screen; @@ -24,36 +24,36 @@ public class TestScreen extends LayoutScreen { } @Override - protected org.betterx.ui.layout.components.Component initContent() { - VerticalStack rows = new VerticalStack(DynamicSize.fit(), DynamicSize.fitOrFill()); + protected LayoutComponent initContent() { + VerticalStack rows = new VerticalStack(Value.fit(), Value.fitOrFill()); rows.addFiller(); rows.add(new Text( - DynamicSize.fitOrFill(), DynamicSize.fixed(20), + Value.fitOrFill(), Value.fixed(20), Component.literal("Some Text") ).alignRight() ); rows.add(new Text( - DynamicSize.fitOrFill(), DynamicSize.fixed(20), + Value.fitOrFill(), Value.fixed(20), Component.literal("Some other, longer Text") ).centerHorizontal() ); rows.addSpacer(16); rows.add(new Image( - DynamicSize.fixed(24), DynamicSize.fixed(24), + Value.fixed(24), Value.fixed(24), BCLib.makeID("icon.png"), new Size(512, 512) ).centerHorizontal() ); rows.add(new MultiLineText( - DynamicSize.fill(), DynamicSize.fit(), + Value.fill(), Value.fit(), Component.literal( "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.") ).setColor(ColorUtil.LIGHT_PURPLE).centerHorizontal() ); rows.addSpacer(16); rows.add(new Range<>( - DynamicSize.fill(), DynamicSize.fit(), + Value.fill(), Value.fit(), Component.literal("Integer"), 10, 90, 20, (slider, value) -> { @@ -62,7 +62,7 @@ public class TestScreen extends LayoutScreen { )); rows.addSpacer(8); rows.add(new Range<>( - DynamicSize.fill(), DynamicSize.fit(), + Value.fill(), Value.fit(), Component.literal("Float"), 10f, 90f, 20f, (slider, value) -> { @@ -71,7 +71,7 @@ public class TestScreen extends LayoutScreen { )); rows.addSpacer(16); Checkbox cb1 = new Checkbox( - DynamicSize.fit(), DynamicSize.fit(), + Value.fit(), Value.fit(), Component.literal("Some Sub-State"), false, true, (checkbox, value) -> { @@ -79,7 +79,7 @@ public class TestScreen extends LayoutScreen { } ); rows.add(new Checkbox( - DynamicSize.fit(), DynamicSize.fit(), + Value.fit(), Value.fit(), Component.literal("Some Selectable State"), false, true, (checkbox, value) -> { @@ -90,7 +90,7 @@ public class TestScreen extends LayoutScreen { rows.add(cb1); rows.addSpacer(16); rows.add(new Button( - DynamicSize.fit(), DynamicSize.fit(), + Value.fit(), Value.fit(), Component.literal("test"), (bt) -> { System.out.println("clicked test"); @@ -101,7 +101,7 @@ public class TestScreen extends LayoutScreen { ); rows.addSpacer(8); rows.add(new Button( - DynamicSize.fit(), DynamicSize.fit(), + Value.fit(), Value.fit(), Component.literal("Hello World"), (bt) -> { System.out.println("clicked hello"); @@ -112,6 +112,6 @@ public class TestScreen extends LayoutScreen { ); rows.addFiller(); - return HorizontalStack.centered(VerticalScroll.create(DynamicSize.fit(), DynamicSize.relative(1), rows)); + return HorizontalStack.centered(VerticalScroll.create(Value.fit(), Value.relative(1), rows)); } } diff --git a/src/main/java/org/betterx/ui/layout/components/AbstractStack.java b/src/main/java/org/betterx/ui/layout/components/AbstractStack.java index f6267262..5ca093be 100644 --- a/src/main/java/org/betterx/ui/layout/components/AbstractStack.java +++ b/src/main/java/org/betterx/ui/layout/components/AbstractStack.java @@ -2,11 +2,14 @@ package org.betterx.ui.layout.components; import org.betterx.ui.layout.components.input.RelativeContainerEventHandler; import org.betterx.ui.layout.components.render.ComponentRenderer; -import org.betterx.ui.layout.values.DynamicSize; import org.betterx.ui.layout.values.Rectangle; +import org.betterx.ui.layout.values.Size; +import org.betterx.ui.layout.values.Value; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -16,14 +19,14 @@ import java.util.List; import org.jetbrains.annotations.Nullable; @Environment(EnvType.CLIENT) -public abstract class AbstractStack> extends Component implements RelativeContainerEventHandler { - protected final List> components = new LinkedList<>(); +public abstract class AbstractStack> extends LayoutComponent implements RelativeContainerEventHandler { + protected final List> components = new LinkedList<>(); - public AbstractStack(DynamicSize width, DynamicSize height) { + public AbstractStack(Value width, Value height) { this(width, height, null); } - public AbstractStack(DynamicSize width, DynamicSize height, R renderer) { + public AbstractStack(Value width, Value height, R renderer) { super(width, height, renderer); } @@ -53,28 +56,28 @@ public abstract class AbstractStack c : components) { + for (LayoutComponent c : components) { c.render(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect); } } - public T add(Component c) { + public T add(LayoutComponent c) { this.components.add(c); return (T) this; } - protected abstract T addEmpty(DynamicSize size); + protected abstract T addEmpty(Value size); public T addSpacer(int size) { - return addEmpty(DynamicSize.fixed(size)); + return addEmpty(Value.fixed(size)); } public T addSpacer(float percentage) { - return addEmpty(DynamicSize.relative(percentage)); + return addEmpty(Value.relative(percentage)); } public T addFiller() { - return addEmpty(DynamicSize.fill()); + return addEmpty(Value.fill()); } @Override @@ -111,5 +114,46 @@ public abstract class AbstractStack> extends Component> { +public abstract class AbstractVanillaComponent> extends LayoutComponent> { protected C vanillaComponent; protected final net.minecraft.network.chat.Component component; protected float alpha = 1.0f; protected boolean enabled = true; public AbstractVanillaComponent( - DynamicSize width, - DynamicSize height, + Value width, + Value height, AbstractVanillaComponentRenderer renderer, net.minecraft.network.chat.Component component ) { diff --git a/src/main/java/org/betterx/ui/layout/components/Button.java b/src/main/java/org/betterx/ui/layout/components/Button.java index fa5b0e77..0cecdcd3 100644 --- a/src/main/java/org/betterx/ui/layout/components/Button.java +++ b/src/main/java/org/betterx/ui/layout/components/Button.java @@ -1,7 +1,7 @@ package org.betterx.ui.layout.components; import org.betterx.ui.layout.components.render.ButtonRenderer; -import org.betterx.ui.layout.values.DynamicSize; +import org.betterx.ui.layout.values.Value; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -12,8 +12,8 @@ public class Button extends AbstractVanillaComponent> extends Component> { +public abstract class CustomRenderComponent> extends LayoutComponent> { public CustomRenderComponent( - DynamicSize width, - DynamicSize height + Value width, + Value height ) { super(width, height, new CustomRenderRenderer<>()); renderer.linkedComponent = (C) this; diff --git a/src/main/java/org/betterx/ui/layout/components/Empty.java b/src/main/java/org/betterx/ui/layout/components/Empty.java index 7c74ae3a..e2e512d5 100644 --- a/src/main/java/org/betterx/ui/layout/components/Empty.java +++ b/src/main/java/org/betterx/ui/layout/components/Empty.java @@ -1,15 +1,15 @@ package org.betterx.ui.layout.components; -import org.betterx.ui.layout.values.DynamicSize; +import org.betterx.ui.layout.values.Value; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @Environment(EnvType.CLIENT) -public class Empty extends Component { +public class Empty extends LayoutComponent { public Empty( - DynamicSize width, - DynamicSize height + Value width, + Value height ) { super(width, height, null); } diff --git a/src/main/java/org/betterx/ui/layout/components/HorizontalStack.java b/src/main/java/org/betterx/ui/layout/components/HorizontalStack.java index df2368fe..8fb141ee 100644 --- a/src/main/java/org/betterx/ui/layout/components/HorizontalStack.java +++ b/src/main/java/org/betterx/ui/layout/components/HorizontalStack.java @@ -3,14 +3,14 @@ package org.betterx.ui.layout.components; import org.betterx.ui.layout.components.input.RelativeContainerEventHandler; import org.betterx.ui.layout.components.render.NullRenderer; import org.betterx.ui.layout.values.Alignment; -import org.betterx.ui.layout.values.DynamicSize; +import org.betterx.ui.layout.values.Value; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @Environment(EnvType.CLIENT) public class HorizontalStack extends AbstractStack implements RelativeContainerEventHandler { - public HorizontalStack(DynamicSize width, DynamicSize height) { + public HorizontalStack(Value width, Value height) { super(width, height); } @@ -22,7 +22,7 @@ public class HorizontalStack extends AbstractStack c : components) { + for (LayoutComponent c : components) { c.updateContainerWidth(c.width.calculatedSize()); } @@ -33,7 +33,7 @@ public class HorizontalStack extends AbstractStack c.height.calculateOrFill(myHeight)); - for (Component c : components) { + for (LayoutComponent c : components) { c.updateContainerHeight(c.height.calculatedSize()); } return myHeight; @@ -45,7 +45,7 @@ public class HorizontalStack extends AbstractStack c : components) { + for (LayoutComponent c : components) { int delta = relativeBounds.height - c.height.calculatedSize(); if (c.hAlign == Alignment.MIN) delta = 0; else if (c.hAlign == Alignment.CENTER) delta /= 2; @@ -67,16 +67,27 @@ public class HorizontalStack extends AbstractStack c.height.calculateFixed()).reduce(0, Integer::max); } - public static HorizontalStack centered(Component c) { - return new HorizontalStack(DynamicSize.fill(), DynamicSize.fill()).addFiller().add(c).addFiller(); + public static HorizontalStack centered(LayoutComponent c) { + return new HorizontalStack(Value.fill(), Value.fill()).addFiller().add(c).addFiller(); } - public static HorizontalStack bottom(Component c) { - return new HorizontalStack(DynamicSize.fill(), DynamicSize.fill()).add(c).addFiller(); + public static HorizontalStack bottom(LayoutComponent c) { + return new HorizontalStack(Value.fill(), Value.fill()).add(c).addFiller(); } - protected HorizontalStack addEmpty(DynamicSize size) { - this.components.add(new Empty(size, DynamicSize.fixed(0))); + protected HorizontalStack addEmpty(Value size) { + this.components.add(new Empty(size, Value.fixed(0))); return this; } + + public VerticalStack addColumn(Value width, Value height) { + VerticalStack stack = new VerticalStack(width, height); + add(stack); + return stack; + } + + + public VerticalStack addColumn() { + return addColumn(Value.fit(), Value.fit()); + } } diff --git a/src/main/java/org/betterx/ui/layout/components/Image.java b/src/main/java/org/betterx/ui/layout/components/Image.java index bf84b3f8..5b9f3313 100644 --- a/src/main/java/org/betterx/ui/layout/components/Image.java +++ b/src/main/java/org/betterx/ui/layout/components/Image.java @@ -1,8 +1,8 @@ package org.betterx.ui.layout.components; -import org.betterx.ui.layout.values.DynamicSize; import org.betterx.ui.layout.values.Rectangle; import org.betterx.ui.layout.values.Size; +import org.betterx.ui.layout.values.Value; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; @@ -21,11 +21,11 @@ public class Image extends CustomRenderComponent { protected float alpha; protected Size resourceSize; - public Image(DynamicSize width, DynamicSize height, ResourceLocation location) { + public Image(Value width, Value height, ResourceLocation location) { this(width, height, location, new Size(16, 16)); } - public Image(DynamicSize width, DynamicSize height, ResourceLocation location, Size resourceSize) { + public Image(Value width, Value height, ResourceLocation location, Size resourceSize) { super(width, height); this.location = location; this.uvRect = new Rectangle(0, 0, resourceSize.width(), resourceSize.height()); diff --git a/src/main/java/org/betterx/ui/layout/components/Component.java b/src/main/java/org/betterx/ui/layout/components/LayoutComponent.java similarity index 87% rename from src/main/java/org/betterx/ui/layout/components/Component.java rename to src/main/java/org/betterx/ui/layout/components/LayoutComponent.java index 57178bb6..1d63c761 100644 --- a/src/main/java/org/betterx/ui/layout/components/Component.java +++ b/src/main/java/org/betterx/ui/layout/components/LayoutComponent.java @@ -2,8 +2,8 @@ package org.betterx.ui.layout.components; import org.betterx.ui.layout.components.render.ComponentRenderer; import org.betterx.ui.layout.values.Alignment; -import org.betterx.ui.layout.values.DynamicSize; import org.betterx.ui.layout.values.Rectangle; +import org.betterx.ui.layout.values.Value; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; @@ -14,15 +14,15 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @Environment(EnvType.CLIENT) -public abstract class Component implements ComponentWithBounds, GuiEventListener { +public abstract class LayoutComponent implements ComponentWithBounds, GuiEventListener { protected final R renderer; - protected final DynamicSize width; - protected final DynamicSize height; + protected final Value width; + protected final Value height; protected Rectangle relativeBounds; protected Alignment vAlign = Alignment.MIN; protected Alignment hAlign = Alignment.MIN; - public Component(DynamicSize width, DynamicSize height, R renderer) { + public LayoutComponent(Value width, Value height, R renderer) { this.width = width.attachComponent(this::getContentWidth); this.height = height.attachComponent(this::getContentHeight); this.renderer = renderer; @@ -120,32 +120,32 @@ public abstract class Component implements Componen return super.toString() + "(" + relativeBounds + ", " + width.calculatedSize() + "x" + height.calculatedSize() + ")"; } - public Component alignTop() { + public LayoutComponent alignTop() { vAlign = Alignment.MIN; return this; } - public Component alignBottom() { + public LayoutComponent alignBottom() { vAlign = Alignment.MAX; return this; } - public Component centerVertical() { + public LayoutComponent centerVertical() { vAlign = Alignment.CENTER; return this; } - public Component alignLeft() { + public LayoutComponent alignLeft() { hAlign = Alignment.MIN; return this; } - public Component alignRight() { + public LayoutComponent alignRight() { hAlign = Alignment.MAX; return this; } - public Component centerHorizontal() { + public LayoutComponent centerHorizontal() { hAlign = Alignment.CENTER; return this; } diff --git a/src/main/java/org/betterx/ui/layout/components/MultiLineText.java b/src/main/java/org/betterx/ui/layout/components/MultiLineText.java index abbc3bbd..e1cf832c 100644 --- a/src/main/java/org/betterx/ui/layout/components/MultiLineText.java +++ b/src/main/java/org/betterx/ui/layout/components/MultiLineText.java @@ -4,20 +4,20 @@ import org.betterx.ui.ColorUtil; import org.betterx.ui.layout.components.render.ComponentRenderer; import org.betterx.ui.layout.components.render.TextProvider; import org.betterx.ui.layout.values.Alignment; -import org.betterx.ui.layout.values.DynamicSize; import org.betterx.ui.layout.values.Rectangle; +import org.betterx.ui.layout.values.Value; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.gui.components.MultiLineLabel; -public class MultiLineText extends Component { +public class MultiLineText extends LayoutComponent { final net.minecraft.network.chat.Component text; int color = ColorUtil.DEFAULT_TEXT; protected MultiLineLabel multiLineLabel; public MultiLineText( - DynamicSize width, - DynamicSize height, + Value width, + Value height, final net.minecraft.network.chat.Component text ) { super(width, height, new MultiLineTextRenderer()); diff --git a/src/main/java/org/betterx/ui/layout/components/Panel.java b/src/main/java/org/betterx/ui/layout/components/Panel.java index c8dd99ba..614eb0f7 100644 --- a/src/main/java/org/betterx/ui/layout/components/Panel.java +++ b/src/main/java/org/betterx/ui/layout/components/Panel.java @@ -18,7 +18,7 @@ import org.jetbrains.annotations.Nullable; @Environment(EnvType.CLIENT) public class Panel implements ComponentWithBounds, RelativeContainerEventHandler, NarratableEntry, Widget { - protected Component child; + protected LayoutComponent child; List listeners = List.of(); public final Rectangle bounds; @@ -30,7 +30,7 @@ public class Panel implements ComponentWithBounds, RelativeContainerEventHandler bounds = new Rectangle(left, top, width, height); } - public void setChild(Component c) { + public void setChild(LayoutComponent c) { this.child = c; listeners = List.of(c); } diff --git a/src/main/java/org/betterx/ui/layout/components/Range.java b/src/main/java/org/betterx/ui/layout/components/Range.java index 143cc55b..ab14116c 100644 --- a/src/main/java/org/betterx/ui/layout/components/Range.java +++ b/src/main/java/org/betterx/ui/layout/components/Range.java @@ -1,7 +1,7 @@ package org.betterx.ui.layout.components; import org.betterx.ui.layout.components.render.RangeRenderer; -import org.betterx.ui.layout.values.DynamicSize; +import org.betterx.ui.layout.values.Value; import org.betterx.ui.vanilla.Slider; import net.minecraft.network.chat.Component; @@ -17,8 +17,8 @@ public class Range extends AbstractVanillaComponent, private final N initialValue; public Range( - DynamicSize width, - DynamicSize height, + Value width, + Value height, Component component, N minValue, N maxValue, @@ -33,8 +33,8 @@ public class Range extends AbstractVanillaComponent, } public Range( - DynamicSize width, - DynamicSize height, + Value width, + Value height, N minValue, N maxValue, N initialValue, diff --git a/src/main/java/org/betterx/ui/layout/components/Text.java b/src/main/java/org/betterx/ui/layout/components/Text.java index 1e675d7a..53d05da6 100644 --- a/src/main/java/org/betterx/ui/layout/components/Text.java +++ b/src/main/java/org/betterx/ui/layout/components/Text.java @@ -4,19 +4,19 @@ import org.betterx.ui.ColorUtil; import org.betterx.ui.layout.components.render.ComponentRenderer; import org.betterx.ui.layout.components.render.TextProvider; import org.betterx.ui.layout.values.Alignment; -import org.betterx.ui.layout.values.DynamicSize; import org.betterx.ui.layout.values.Rectangle; +import org.betterx.ui.layout.values.Value; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.gui.GuiComponent; -public class Text extends Component { +public class Text extends LayoutComponent { final net.minecraft.network.chat.Component text; int color = ColorUtil.DEFAULT_TEXT; public Text( - DynamicSize width, - DynamicSize height, + Value width, + Value height, net.minecraft.network.chat.Component text ) { diff --git a/src/main/java/org/betterx/ui/layout/components/VerticalScroll.java b/src/main/java/org/betterx/ui/layout/components/VerticalScroll.java index 51d051fe..ff94050c 100644 --- a/src/main/java/org/betterx/ui/layout/components/VerticalScroll.java +++ b/src/main/java/org/betterx/ui/layout/components/VerticalScroll.java @@ -4,8 +4,8 @@ import org.betterx.ui.layout.components.render.ComponentRenderer; import org.betterx.ui.layout.components.render.NullRenderer; import org.betterx.ui.layout.components.render.ScrollerRenderer; import org.betterx.ui.layout.values.Alignment; -import org.betterx.ui.layout.values.DynamicSize; import org.betterx.ui.layout.values.Rectangle; +import org.betterx.ui.layout.values.Value; import org.betterx.ui.vanilla.VanillaScrollerRenderer; import com.mojang.blaze3d.vertex.PoseStack; @@ -14,8 +14,8 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @Environment(EnvType.CLIENT) -public class VerticalScroll extends Component { - protected Component child; +public class VerticalScroll extends LayoutComponent { + protected LayoutComponent child; protected final RS scrollerRenderer; protected int dist; @@ -24,23 +24,23 @@ public class VerticalScroll create(Component c) { - return create(DynamicSize.relative(1), DynamicSize.relative(1), c); + public static VerticalScroll create(LayoutComponent c) { + return create(Value.relative(1), Value.relative(1), c); } public static VerticalScroll create( - DynamicSize width, - DynamicSize height, - Component c + Value width, + Value height, + LayoutComponent c ) { VerticalScroll res = new VerticalScroll<>( width, @@ -52,7 +52,7 @@ public class VerticalScroll c) { + public void setChild(LayoutComponent c) { this.child = c; } diff --git a/src/main/java/org/betterx/ui/layout/components/VerticalStack.java b/src/main/java/org/betterx/ui/layout/components/VerticalStack.java index de07a897..206a5236 100644 --- a/src/main/java/org/betterx/ui/layout/components/VerticalStack.java +++ b/src/main/java/org/betterx/ui/layout/components/VerticalStack.java @@ -4,14 +4,14 @@ package org.betterx.ui.layout.components; import org.betterx.ui.layout.components.input.RelativeContainerEventHandler; import org.betterx.ui.layout.components.render.NullRenderer; import org.betterx.ui.layout.values.Alignment; -import org.betterx.ui.layout.values.DynamicSize; +import org.betterx.ui.layout.values.Value; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @Environment(EnvType.CLIENT) public class VerticalStack extends AbstractStack implements RelativeContainerEventHandler { - public VerticalStack(DynamicSize width, DynamicSize height) { + public VerticalStack(Value width, Value height) { super(width, height); } @@ -19,7 +19,7 @@ public class VerticalStack extends AbstractStack im protected int updateContainerWidth(int containerWidth) { int myWidth = width.calculateOrFill(containerWidth); components.stream().forEach(c -> c.width.calculateOrFill(myWidth)); - for (Component c : components) { + for (LayoutComponent c : components) { c.updateContainerWidth(c.width.calculatedSize()); } return myWidth; @@ -33,7 +33,7 @@ public class VerticalStack extends AbstractStack im int freeHeight = Math.max(0, myHeight - fixedHeight); fillHeight(myHeight, freeHeight); - for (Component c : components) { + for (LayoutComponent c : components) { c.updateContainerHeight(c.height.calculatedSize()); } @@ -45,7 +45,7 @@ public class VerticalStack extends AbstractStack im super.setRelativeBounds(left, top); int offset = 0; - for (Component c : components) { + for (LayoutComponent c : components) { int delta = relativeBounds.width - c.width.calculatedSize(); if (c.hAlign == Alignment.MIN) delta = 0; else if (c.hAlign == Alignment.CENTER) delta /= 2; @@ -67,16 +67,26 @@ public class VerticalStack extends AbstractStack im return (int) (fixedHeight / (1 - percentage)); } - public static VerticalStack centered(Component c) { - return new VerticalStack(DynamicSize.relative(1), DynamicSize.relative(1)).addFiller().add(c).addFiller(); + public static VerticalStack centered(LayoutComponent c) { + return new VerticalStack(Value.relative(1), Value.relative(1)).addFiller().add(c).addFiller(); } - public static VerticalStack bottom(Component c) { - return new VerticalStack(DynamicSize.relative(1), DynamicSize.relative(1)).add(c).addFiller(); + public static VerticalStack bottom(LayoutComponent c) { + return new VerticalStack(Value.relative(1), Value.relative(1)).add(c).addFiller(); } - protected VerticalStack addEmpty(DynamicSize size) { - this.components.add(new Empty(DynamicSize.fixed(0), size)); + protected VerticalStack addEmpty(Value size) { + this.components.add(new Empty(Value.fixed(0), size)); return this; } + + public HorizontalStack addRow(Value width, Value height) { + HorizontalStack stack = new HorizontalStack(width, height); + add(stack); + return stack; + } + + public HorizontalStack addRow() { + return addRow(Value.fit(), Value.fit()); + } } diff --git a/src/main/java/org/betterx/ui/layout/values/Size.java b/src/main/java/org/betterx/ui/layout/values/Size.java index 3100a6f0..fa2fec22 100644 --- a/src/main/java/org/betterx/ui/layout/values/Size.java +++ b/src/main/java/org/betterx/ui/layout/values/Size.java @@ -1,4 +1,11 @@ package org.betterx.ui.layout.values; public record Size(int width, int height) { + public static Size of(int size) { + return new Size(size, size); + } + + public static Size of(int width, int height) { + return new Size(width, height); + } } diff --git a/src/main/java/org/betterx/ui/layout/values/DynamicSize.java b/src/main/java/org/betterx/ui/layout/values/Value.java similarity index 78% rename from src/main/java/org/betterx/ui/layout/values/DynamicSize.java rename to src/main/java/org/betterx/ui/layout/values/Value.java index 86ba669a..f870ffea 100644 --- a/src/main/java/org/betterx/ui/layout/values/DynamicSize.java +++ b/src/main/java/org/betterx/ui/layout/values/Value.java @@ -4,33 +4,33 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @Environment(EnvType.CLIENT) -public class DynamicSize { +public class Value { private SizeType sizeType; private int calculatedSize; - public DynamicSize(SizeType sizeType) { + public Value(SizeType sizeType) { this.sizeType = sizeType; this.calculatedSize = 0; } - public static DynamicSize fixed(int size) { - return new DynamicSize(new SizeType.Fixed(size)); + public static Value fixed(int size) { + return new Value(new SizeType.Fixed(size)); } - public static DynamicSize relative(double percentage) { - return new DynamicSize(new SizeType.Relative(percentage)); + public static Value relative(double percentage) { + return new Value(new SizeType.Relative(percentage)); } - public static DynamicSize fill() { - return new DynamicSize(SizeType.FILL); + public static Value fill() { + return new Value(SizeType.FILL); } - public static DynamicSize fit() { - return new DynamicSize(SizeType.FIT_CONTENT); + public static Value fit() { + return new Value(SizeType.FIT_CONTENT); } - public static DynamicSize fitOrFill() { - return new DynamicSize(SizeType.FIT_CONTENT_OR_FILL); + public static Value fitOrFill() { + return new Value(SizeType.FIT_CONTENT_OR_FILL); } public int calculatedSize() { @@ -42,7 +42,7 @@ public class DynamicSize { return value; } - public DynamicSize attachComponent(SizeType.FitContent.ContentSizeSupplier c) { + public Value attachComponent(SizeType.FitContent.ContentSizeSupplier c) { if (sizeType instanceof SizeType.FitContent fit && fit.contentSize() == null) { sizeType = fit.copyForSupplier(c); } diff --git a/src/main/java/org/betterx/ui/vanilla/LayoutScreen.java b/src/main/java/org/betterx/ui/vanilla/LayoutScreen.java index cbd894f9..53cd651b 100644 --- a/src/main/java/org/betterx/ui/vanilla/LayoutScreen.java +++ b/src/main/java/org/betterx/ui/vanilla/LayoutScreen.java @@ -1,10 +1,7 @@ package org.betterx.ui.vanilla; -import org.betterx.ui.layout.components.HorizontalStack; -import org.betterx.ui.layout.components.Panel; -import org.betterx.ui.layout.components.Text; -import org.betterx.ui.layout.components.VerticalStack; -import org.betterx.ui.layout.values.DynamicSize; +import org.betterx.ui.layout.components.*; +import org.betterx.ui.layout.values.Value; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.gui.screens.Screen; @@ -49,7 +46,7 @@ public abstract class LayoutScreen extends Screen { @Nullable public final Screen parent; - protected abstract org.betterx.ui.layout.components.Component initContent(); + protected abstract LayoutComponent initContent(); @Override protected final void init() { @@ -61,18 +58,24 @@ public abstract class LayoutScreen extends Screen { addRenderableWidget(main); } - protected org.betterx.ui.layout.components.Component addTitle(org.betterx.ui.layout.components.Component content) { - VerticalStack rows = new VerticalStack(DynamicSize.fill(), DynamicSize.fill()); + protected LayoutComponent buildTitle() { + + var text = new Text(Value.fill(), Value.fit(), title).centerHorizontal(); + return text; + } + + protected LayoutComponent addTitle(LayoutComponent content) { + VerticalStack rows = new VerticalStack(Value.fill(), Value.fill()); if (topPadding > 0) rows.addSpacer(topPadding); - rows.add(new Text(DynamicSize.fill(), DynamicSize.fit(), title).centerHorizontal()); + rows.add(buildTitle()); rows.addSpacer(15); rows.add(content); if (bottomPadding > 0) rows.addSpacer(bottomPadding); if (sidePadding <= 0) return rows; - HorizontalStack cols = new HorizontalStack(DynamicSize.fill(), DynamicSize.fill()); + HorizontalStack cols = new HorizontalStack(Value.fill(), Value.fill()); cols.addSpacer(sidePadding); cols.add(rows); cols.addSpacer(sidePadding); diff --git a/src/main/java/org/betterx/ui/vanilla/LayoutScreenWithIcon.java b/src/main/java/org/betterx/ui/vanilla/LayoutScreenWithIcon.java new file mode 100644 index 00000000..471d80be --- /dev/null +++ b/src/main/java/org/betterx/ui/vanilla/LayoutScreenWithIcon.java @@ -0,0 +1,52 @@ +package org.betterx.ui.vanilla; + +import org.betterx.ui.layout.components.HorizontalStack; +import org.betterx.ui.layout.components.LayoutComponent; +import org.betterx.ui.layout.values.Size; +import org.betterx.ui.layout.values.Value; + +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +import org.jetbrains.annotations.Nullable; + +public abstract class LayoutScreenWithIcon extends LayoutScreen { + protected final ResourceLocation icon; + + public LayoutScreenWithIcon(ResourceLocation icon, Component component) { + this(null, icon, component); + } + + public LayoutScreenWithIcon( + @Nullable Screen parent, + ResourceLocation icon, + Component component + ) { + this(parent, icon, component, 20, 10, 20); + } + + public LayoutScreenWithIcon( + @Nullable Screen parent, + ResourceLocation icon, + Component component, + int topPadding, + int bottomPadding, + int sidePadding + ) { + super(parent, component, topPadding, bottomPadding, sidePadding); + this.icon = icon; + } + + @Override + protected LayoutComponent buildTitle() { + LayoutComponent title = super.buildTitle(); + HorizontalStack row = new HorizontalStack(Value.fill(), Value.fit()); + row.addFiller(); + row.addIcon(icon, Size.of(512)); + row.addSpacer(4); + row.add(title); + row.addFiller(); + return row; + } +}