Skip to content

Commit

Permalink
Improve Widgets creation
Browse files Browse the repository at this point in the history
  • Loading branch information
shedaniel committed Jul 16, 2023
1 parent 0f881db commit 0dc7000
Show file tree
Hide file tree
Showing 13 changed files with 441 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import com.mojang.blaze3d.vertex.PoseStack;
import me.shedaniel.math.Rectangle;
import org.jetbrains.annotations.ApiStatus;

public abstract class WidgetWithBounds extends Widget {
public abstract Rectangle getBounds();
Expand All @@ -42,4 +43,34 @@ public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY,
render(matrices, mouseX, mouseY, delta);
getBounds().setBounds(clone);
}

@ApiStatus.Experimental
public final WidgetWithBounds withPadding(int padding) {
return Widgets.padded(padding, this);
}

@ApiStatus.Experimental
public final WidgetWithBounds withPadding(int padX, int padY) {
return Widgets.padded(padX, padY, this);
}

@ApiStatus.Experimental
public final WidgetWithBounds withPaddingHorizontal(int padX) {
return Widgets.padded(padX, 0, this);
}

@ApiStatus.Experimental
public final WidgetWithBounds withPaddingVertical(int padY) {
return Widgets.padded(0, padY, this);
}

@ApiStatus.Experimental
public final WidgetWithBounds withPadding(int padLeft, int padRight, int padTop, int padBottom) {
return Widgets.padded(padLeft, padRight, padTop, padBottom, this);
}

@ApiStatus.Experimental
public final WidgetWithBounds withScissors() {
return Widgets.scissored(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@

@Environment(EnvType.CLIENT)
public final class Widgets {
private Widgets() {}
private Widgets() {
}

public static Widget createDrawableWidget(DrawableConsumer drawable) {
return ClientInternals.getWidgetsProvider().createDrawableWidget(drawable);
Expand All @@ -63,10 +64,11 @@ public static WidgetWithBounds withTooltip(WidgetWithBounds widget, Component...
}

public static WidgetWithBounds withTooltip(WidgetWithBounds widget, Collection<Component> texts) {
return withBounds(concat(
return concatWithBounds(
widget::getBounds,
widget,
createTooltip(widget::getBounds, texts)
), widget::getBounds);
);
}

public static Widget createTooltip(Rectangle bounds, Component... texts) {
Expand Down Expand Up @@ -161,11 +163,11 @@ public static WidgetWithBounds wrapWidgetWithBoundsSupplier(Widget widget, Suppl
}

public static WidgetWithBounds withBounds(Widget widget) {
return wrapWidgetWithBounds(widget, null);
return withBounds(widget, (Rectangle) null);
}

public static WidgetWithBounds withBounds(Widget widget, Rectangle bounds) {
return wrapWidgetWithBoundsSupplier(widget, bounds == null ? null : () -> bounds);
return withBounds(widget, bounds == null ? null : () -> bounds);
}

public static WidgetWithBounds withBounds(Widget widget, Supplier<Rectangle> bounds) {
Expand Down Expand Up @@ -304,6 +306,22 @@ public static Widget concat(List<Widget> widgets) {
return ClientInternals.getWidgetsProvider().concatWidgets(widgets);
}

public static WidgetWithBounds concatWithBounds(Rectangle bounds, Widget... widgets) {
return concatWithBounds(bounds, Arrays.asList(widgets));
}

public static WidgetWithBounds concatWithBounds(Rectangle bounds, List<Widget> widgets) {
return ClientInternals.getWidgetsProvider().concatWidgetsWithBounds(() -> bounds, widgets);
}

public static WidgetWithBounds concatWithBounds(Supplier<Rectangle> bounds, Widget... widgets) {
return concatWithBounds(bounds, Arrays.asList(widgets));
}

public static WidgetWithBounds concatWithBounds(Supplier<Rectangle> bounds, List<Widget> widgets) {
return ClientInternals.getWidgetsProvider().concatWidgetsWithBounds(bounds, widgets);
}

public static WidgetWithBounds noOp() {
return ClientInternals.getWidgetsProvider().noOp();
}
Expand All @@ -318,6 +336,11 @@ public static WidgetWithBounds scissored(Rectangle bounds, Widget widget) {
return ClientInternals.getWidgetsProvider().wrapScissored(bounds, widget);
}

@ApiStatus.Experimental
public static WidgetWithBounds scissored(WidgetWithBounds widget) {
return ClientInternals.getWidgetsProvider().wrapScissored(widget);
}

@ApiStatus.Experimental
public static WidgetWithBounds padded(int padding, WidgetWithBounds widget) {
return padded(padding, padding, padding, padding, widget);
Expand Down
4 changes: 4 additions & 0 deletions api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,16 @@ public interface WidgetsProvider {

Widget concatWidgets(List<Widget> widgets);

WidgetWithBounds concatWidgetsWithBounds(Supplier<Rectangle> bounds, List<Widget> widgets);

WidgetWithBounds noOp();

WidgetWithBounds wrapOverflow(Rectangle bounds, WidgetWithBounds widget);

WidgetWithBounds wrapScissored(Rectangle bounds, Widget widget);

WidgetWithBounds wrapScissored(WidgetWithBounds widget);

WidgetWithBounds wrapPadded(int padLeft, int padRight, int padTop, int padBottom, WidgetWithBounds widget);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,25 @@
package me.shedaniel.rei.impl.client.gui.config.components;

import dev.architectury.utils.value.IntValue;
import me.shedaniel.clothconfig2.api.scroll.ScrollingContainer;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.gui.widgets.Widget;
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds;
import me.shedaniel.rei.impl.client.gui.config.options.OptionCategory;
import me.shedaniel.rei.impl.client.gui.widget.ListWidget;
import me.shedaniel.rei.impl.client.gui.widget.ScrollableViewWidget;
import me.shedaniel.rei.impl.common.util.RectangleUtils;

import java.util.List;

public class ConfigCategoriesListWidget {
public static Widget create(Rectangle bounds, List<OptionCategory> categories, IntValue selected) {
return ListWidget.builderOf(bounds, categories,
(index, entry) -> ConfigCategoryEntryWidget.create(entry))
.paddingHorizontal(3)
.paddingVertical(5)
WidgetWithBounds list = ListWidget.builderOf(RectangleUtils.inset(bounds, 3, 5), categories,
(index, entry) -> ConfigCategoryEntryWidget.create(entry))
.gap(3)
.isSelectable((index, entry) -> true)
.selected(selected)
.build();
return ScrollableViewWidget.create(bounds, list, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ public static WidgetWithBounds create(OptionCategory category) {
.leftAligned();
Font font = Minecraft.getInstance().font;
Rectangle bounds = new Rectangle(0, 0, label.getBounds().getMaxX(), 7 * 3);
return Widgets.withBounds(Widgets.concat(
return Widgets.concatWithBounds(
bounds,
label,
Widgets.createTexturedWidget(category.getIcon(), new Rectangle(3, 3, 16, 16), 0, 0, 1, 1, 1, 1)
), bounds);
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public DelegateWidgetWithTranslate(WidgetWithBounds widget, Supplier<Matrix4f> t
this.translate = translate;
}

public DelegateWidgetWithTranslate(Widget widget, Supplier<Matrix4f> translate) {
super(widget);
this.translate = translate;
}

protected Matrix4f translate() {
return translate.get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
@ApiStatus.Internal
@Environment(EnvType.CLIENT)
public final class InternalWidgets {
private InternalWidgets() {}
private InternalWidgets() {
}

public static Widget createAutoCraftingButtonWidget(Rectangle displayBounds, Rectangle rectangle, Component text, Supplier<Display> displaySupplier, Supplier<Collection<ResourceLocation>> idsSupplier, List<Widget> setupDisplay, DisplayCategory<?> category) {
Button autoCraftingButton = Widgets.createButton(rectangle, text)
Expand Down Expand Up @@ -162,6 +163,10 @@ public static Widget concatWidgets(List<Widget> widgets) {
return new MergedWidget(widgets);
}

public static WidgetWithBounds concatWidgetsWithBounds(Supplier<Rectangle> bounds, List<Widget> widgets) {
return new MergedWidgetWithBounds(bounds, widgets);
}

private static class LateRenderableWidget extends DelegateWidget implements LateRenderable {
private LateRenderableWidget(Widget widget) {
super(widget);
Expand Down Expand Up @@ -272,6 +277,11 @@ public Widget concatWidgets(List<Widget> widgets) {
return InternalWidgets.concatWidgets(widgets);
}

@Override
public WidgetWithBounds concatWidgetsWithBounds(Supplier<Rectangle> bounds, List<Widget> widgets) {
return InternalWidgets.concatWidgetsWithBounds(bounds, widgets);
}

@Override
public WidgetWithBounds noOp() {
return NoOpWidget.INSTANCE;
Expand All @@ -287,6 +297,11 @@ public WidgetWithBounds wrapScissored(Rectangle bounds, Widget widget) {
return new ScissoredWidget(bounds, widget);
}

@Override
public WidgetWithBounds wrapScissored(WidgetWithBounds widget) {
return new ScissoredWidget(widget);
}

@Override
public WidgetWithBounds wrapPadded(int padLeft, int padRight, int padTop, int padBottom, WidgetWithBounds widget) {
return new PaddedWidget(padLeft, padRight, padTop, padBottom, widget);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ public static <T extends WidgetWithBounds> WidgetBuilder<T> builderOfWidgets(Rec

public static abstract class AbstractBuilder<T extends WidgetWithBounds, SELF extends AbstractBuilder<T, SELF>> {
protected final Rectangle bounds;
protected int paddingHorizontal = 0;
protected int paddingVertical = 0;
protected IntValue selected = new IntValue() {
private int value;

Expand All @@ -64,22 +62,11 @@ public int getAsInt() {
};
protected int gap = 4;
protected boolean calculateTotalHeightDynamically = false;
protected boolean background = true;

protected AbstractBuilder(Rectangle bounds) {
this.bounds = bounds;
}

public SELF paddingHorizontal(int paddingHorizontal) {
this.paddingHorizontal = paddingHorizontal;
return (SELF) this;
}

public SELF paddingVertical(int paddingVertical) {
this.paddingVertical = paddingVertical;
return (SELF) this;
}

public SELF selected(IntValue selected) {
this.selected = selected;
return (SELF) this;
Expand All @@ -100,11 +87,6 @@ public SELF calculateTotalHeightDynamically(boolean calculateTotalHeightDynamica
return (SELF) this;
}

public SELF background(boolean background) {
this.background = background;
return (SELF) this;
}

public abstract WidgetWithBounds build();
}

Expand All @@ -126,8 +108,8 @@ public Builder<T> isSelectable(ListEntryPredicate<T> isSelectable) {

@Override
public WidgetWithBounds build() {
return ListWidget.create(bounds, entries, paddingHorizontal, paddingVertical, selected, gap, calculateTotalHeightDynamically,
cellRenderer, isSelectable, background);
return ListWidget.create(bounds, entries, selected, gap, calculateTotalHeightDynamically,
cellRenderer, isSelectable);
}
}

Expand All @@ -147,46 +129,45 @@ public WidgetBuilder<T> isSelectable(ListEntryPredicate<T> isSelectable) {

@Override
public WidgetWithBounds build() {
return ListWidget.create(bounds, entries, paddingHorizontal, paddingVertical, selected, gap, calculateTotalHeightDynamically,
isSelectable, background);
return ListWidget.create(bounds, entries, selected, gap, calculateTotalHeightDynamically,
isSelectable);
}
}

public static <T> WidgetWithBounds create(Rectangle bounds, List<T> entries, int paddingHorizontal, int paddingVertical,
IntValue selected, int gap, boolean calculateTotalHeightDynamically, ListCellRenderer<T> cellRenderer,
ListEntryPredicate<T> isSelectable, boolean background) {
public static <T> WidgetWithBounds create(Rectangle bounds, List<T> entries, IntValue selected, int gap,
boolean calculateTotalHeightDynamically, ListCellRenderer<T> cellRenderer,
ListEntryPredicate<T> isSelectable) {
int[] i = {0};
return create(bounds, CollectionUtils.map(entries, entry -> cellRenderer.create(i[0]++, entry)), paddingHorizontal, paddingVertical,
selected, gap, calculateTotalHeightDynamically, (index, entry) -> isSelectable.test(index, entries.get(index)), background);
return create(bounds, CollectionUtils.map(entries, entry -> cellRenderer.create(i[0]++, entry)),
selected, gap, calculateTotalHeightDynamically, (index, entry) -> isSelectable.test(index, entries.get(index)));
}

public static <T extends WidgetWithBounds> WidgetWithBounds create(Rectangle bounds, List<T> entries, int paddingHorizontal, int paddingVertical,
IntValue selected, int gap, boolean calculateTotalHeightDynamically,
ListEntryPredicate<T> isSelectable, boolean background) {
int[] height = {collectTotalHeight(entries, gap) + paddingVertical * 2};
public static <T extends WidgetWithBounds> WidgetWithBounds create(Rectangle bounds, List<T> entries, IntValue selected, int gap,
boolean calculateTotalHeightDynamically, ListEntryPredicate<T> isSelectable) {
int[] height = {collectTotalHeight(entries, gap)};

Rectangle innerBounds = bounds.clone();
if (height[0] > bounds.getHeight()) {
innerBounds.width -= 6;
}

int[] i = {0};
List<CellWidget<T>> wrapped = CollectionUtils.map(entries, cell -> new CellWidget<>(innerBounds, paddingHorizontal, i[0]++, cell, selected, entries, isSelectable));
List<CellWidget<T>> wrapped = CollectionUtils.map(entries, cell -> new CellWidget<>(innerBounds, i[0]++, cell, selected, entries, isSelectable));
Widget update = Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
if (calculateTotalHeightDynamically) {
height[0] = collectTotalHeight(entries, gap) + paddingVertical * 2;
height[0] = collectTotalHeight(entries, gap);
innerBounds.width = height[0] > bounds.getHeight() ? bounds.width - 6 : bounds.width;
}

int y = bounds.y + paddingVertical;
int y = bounds.y;
for (CellWidget<T> cell : wrapped) {
cell.position.move(bounds.x + paddingHorizontal, y);
cell.position.move(bounds.x, y);
y += (calculateTotalHeightDynamically ? cell.getBounds().getHeight() : cell.height) + gap;
}

if (selected.getAsInt() != -1) {
CellWidget<T> cellWidget = wrapped.get(selected.getAsInt());
int x1 = innerBounds.x + paddingHorizontal, x2 = innerBounds.getMaxX() - paddingHorizontal;
int x1 = innerBounds.x, x2 = innerBounds.getMaxX();
boolean contains = new Rectangle(x1 - 1, cellWidget.position.y - 1, x2 - x1 + 2, cellWidget.getBounds().height + 2).contains(mouseX, mouseY);
GuiComponent.fill(matrices, x1 - 1, cellWidget.position.y - 1, x2 + 1,
cellWidget.position.y + cellWidget.getBounds().height + 1, contains ? 0xFFD0D0D0 : 0xFF8F8F8F);
Expand All @@ -197,24 +178,22 @@ public static <T extends WidgetWithBounds> WidgetWithBounds create(Rectangle bou
List<Widget> innerWidgets = new ArrayList<>();
innerWidgets.add(update);
innerWidgets.addAll(wrapped);
return ScrollableViewWidget.create(bounds, Widgets.withBounds(Widgets.concat(innerWidgets),
() -> new Rectangle(bounds.x, bounds.y, bounds.width, height[0])), background);
return Widgets.concatWithBounds(() -> new Rectangle(bounds.x, bounds.y, bounds.width, height[0]),
innerWidgets);
}

private static class CellWidget<T> extends DelegateWidgetWithTranslate {
private final Rectangle bounds;
private final int paddingHorizontal;
private final int index;
private final Point position = new Point();
private final int height;
private final IntValue selected;
private final List<T> list;
private final ListEntryPredicate<T> isSelectable;

public CellWidget(Rectangle bounds, int paddingHorizontal, int index, WidgetWithBounds widget, IntValue selected, List<T> list, ListEntryPredicate<T> isSelectable) {
public CellWidget(Rectangle bounds, int index, WidgetWithBounds widget, IntValue selected, List<T> list, ListEntryPredicate<T> isSelectable) {
super(widget, Matrix4f::new);
this.bounds = bounds;
this.paddingHorizontal = paddingHorizontal;
this.index = index;
this.height = widget.getBounds().getHeight();
this.selected = selected;
Expand All @@ -232,7 +211,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
boolean clicked = super.mouseClicked(mouseX, mouseY, button);
Rectangle bounds = delegate().getBounds();

if (clicked || new Rectangle(position.x, position.y, this.bounds.width - paddingHorizontal * 2, bounds.height).contains(mouseX, mouseY)) {
if (clicked || new Rectangle(position.x, position.y, this.bounds.width, bounds.height).contains(mouseX, mouseY)) {
if (isSelectable.test(index, list.get(index))) {
selected.accept(index);
if (!clicked) {
Expand Down
Loading

0 comments on commit 0dc7000

Please sign in to comment.