Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.vivecraft.client.gui.framework.screens;

import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import org.vivecraft.client.gui.framework.widgets.SettingsList;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public abstract class GuiListEditorScreen<T> extends GuiListScreen {

private final Supplier<List<T>> valuesSupplier;
private final Runnable loadDefaults;
private final Consumer<List<T>> save;

protected final boolean fixedEntryCount;

protected List<T> elements;

public GuiListEditorScreen(
Component title, Screen lastScreen, boolean fixedEntryCount, Supplier<List<T>> valuesSupplier,
Runnable loadDefaults, Consumer<List<T>> save)
{
super(title, lastScreen);
this.fixedEntryCount = fixedEntryCount;
this.valuesSupplier = valuesSupplier;
this.loadDefaults = loadDefaults;
this.save = save;
}

@Override
protected void addLowerButtons(int top) {
this.addRenderableWidget(
Button.builder(Component.translatable("vivecraft.gui.loaddefaults"), button -> {
this.loadDefaults.run();
this.elements = null;
this.reinit = true;
})
.bounds(this.width / 2 - 155, top, 150, 20)
.build());

this.addRenderableWidget(
Button.builder(Component.translatable("gui.back"), button -> this.onClose())
.bounds(this.width / 2 + 5, top, 150, 20)
.build());
}

@Override
public void onClose() {
this.save.accept(this.elements);
super.onClose();
}

@SuppressWarnings("unchecked")
protected List<T> getCurrentValues() {
return this.list.children().stream().map(entry -> {
if (entry instanceof ValueEntry<?> valueEntry) {
return (T) valueEntry.getValue();
} else {
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
}

@Override
protected List<SettingsList.BaseEntry> getEntries() {
List<SettingsList.BaseEntry> entries = new LinkedList<>();
if (this.elements == null) {
this.elements = new ArrayList<>(this.valuesSupplier.get());
}
int index = 0;
for (T item : this.elements) {
entries.add(this.toEntry(item, index++));
}

if (!this.fixedEntryCount) {
entries.add(new SettingsList.WidgetEntry(Component.literal(""),
Button.builder(Component.translatable("vivecraft.options.addnew"), button -> {
this.addNewValue();
}).size(SettingsList.WidgetEntry.VALUE_BUTTON_WIDTH, 20).build()));
}
return entries;
}

protected void addNewValue() {
this.elements = getCurrentValues();
this.reinit = true;
}

protected abstract ValueEntry<T> toEntry(T value, int index);

protected static abstract class ValueEntry<T> extends SettingsList.BaseEntry {
public ValueEntry(Component name, Supplier<String> tooltipSupplier) {
super(name, tooltipSupplier);
}

public abstract T getValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package org.vivecraft.client.gui.framework.screens;

import com.google.common.collect.ImmutableList;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;

public abstract class GuiOrderedListEditorScreen<T> extends GuiListEditorScreen<T> {

public GuiOrderedListEditorScreen(
Component title, Screen lastScreen, boolean fixedEntryCount, Supplier<List<T>> valuesSupplier,
Runnable loadDefaults, Consumer<List<T>> save)
{
super(title, lastScreen, fixedEntryCount, valuesSupplier, loadDefaults, save);

// the underlying list is ordered, so can't filter it
this.searchable = false;
}

private void moveEntry(int from, int offset, boolean remove) {
T value = this.elements.get(from);
this.elements.remove(from);
if (!remove) {
this.elements.add(Math.clamp(from + offset, 0, this.elements.size()), value);
}
this.reinit = true;
}

protected class OrderedEntry<T> extends ValueEntry<T> {

protected final T value;

private final int index;
private final Button upButton;
private final Button downButton;
private final Button removeButton;

public OrderedEntry(Component name, T value, int index) {
super(name, null);
this.value = value;
this.index = index;
this.upButton = Button.builder(Component.literal("\u2191"),
button -> moveEntry(index, -1, false))
.bounds(0, 0, 20, 20).build();
this.downButton = Button.builder(Component.literal("\u2193"),
button -> moveEntry(index, 1, false))
.bounds(0, 0, 20, 20).build();
this.removeButton = Button.builder(Component.literal("-"),
button -> moveEntry(index, 0, true))
.bounds(0, 0, 20, 20).build();
}

@Override
public void renderContent(
GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovering, float partialTick)
{
super.renderContent(guiGraphics, mouseX, mouseY, hovering, partialTick);

int textY = this.getY() + this.getHeight() / 2 - Minecraft.getInstance().font.lineHeight / 2 + 2;
guiGraphics.drawString(Minecraft.getInstance().font, this.name, this.getContentX(), textY,
this.textColor());

this.upButton.active = this.isActive() && this.index != 0;
this.downButton.active =
this.isActive() && this.index != GuiOrderedListEditorScreen.this.elements.size() - 1;
this.removeButton.active = this.isActive();

int i = 0;
for (GuiEventListener child : this.children()) {
Button b = (Button) child;
b.setX(this.getContentRight() - (2 - i) * 22 - 20);
b.setY(this.getContentY());
b.render(guiGraphics, mouseX, mouseY, partialTick);
i++;
}
}

@Override
public List<? extends NarratableEntry> narratables() {
return ImmutableList.of(this.upButton, this.downButton, this.removeButton);
}

@Override
public List<? extends GuiEventListener> children() {
return ImmutableList.of(this.upButton, this.downButton, this.removeButton);
}

@Override
public void setActive(boolean active) {
super.setActive(active);
this.upButton.active = active;
this.downButton.active = active;
this.removeButton.active = active;
}

@Override
public T getValue() {
return this.value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class GuiSelectionListScreen<T> extends GuiListScreen {
private final Function<T, Component> componentSupplier;
private final Function<T, String> categorySupplier;
private final Consumer<T> consumer;
private final boolean hasReset;
private final boolean resettable;
private final Function<T, AbstractWidget> widgetSupplier;

Expand All @@ -29,38 +30,47 @@ public class GuiSelectionListScreen<T> extends GuiListScreen {
* @param componentSupplier function that supplies a Component for the provided object to be able to show them in the list
* @param categorySupplier function that supplies a translation string that is used for the category the given object is in
* @param consumer called with the selected object, is called with {@code null} if it should reset
* @param hasReset determines if the reset/clear buton should show up
* @param resettable when true, the left button will say 'reset', else 'clear'
* @param widgetSupplier supplies an optional widget shown with the object
*/
public GuiSelectionListScreen(
Component title, Screen lastScreen, Supplier<List<T>> valuesSupplier, Function<T, Component> componentSupplier,
@Nullable Function<T, String> categorySupplier, Consumer<T> consumer, boolean resettable,
@Nullable Function<T, String> categorySupplier, Consumer<T> consumer, boolean hasReset, boolean resettable,
@Nullable Function<T, AbstractWidget> widgetSupplier)
{
super(title, lastScreen);
this.valuesSupplier = valuesSupplier;
this.componentSupplier = componentSupplier;
this.categorySupplier = categorySupplier != null ? categorySupplier : item -> "";
this.consumer = consumer;
this.hasReset = hasReset;
this.resettable = resettable;
this.widgetSupplier = widgetSupplier != null ? widgetSupplier : item -> null;
}

@Override
protected void addLowerButtons(int top) {
this.addRenderableWidget(
new Button.Builder(Component.translatable(this.resettable ? "controls.reset" : "vivecraft.gui.clear"),
p -> {
this.consumer.accept(null);
this.onClose();
})
.bounds(this.width / 2 - 155, top, 150, 20)
.build());
if (this.hasReset) {
this.addRenderableWidget(
new Button.Builder(Component.translatable(this.resettable ? "controls.reset" : "vivecraft.gui.clear"),
p -> {
this.consumer.accept(null);
this.onClose();
})
.bounds(this.width / 2 - 155, top, 150, 20)
.build());

this.addRenderableWidget(
new Button.Builder(Component.translatable("gui.cancel"), p -> onClose())
.bounds(this.width / 2 + 5, top, 150, 20)
.build());
this.addRenderableWidget(
new Button.Builder(Component.translatable("gui.cancel"), p -> onClose())
.bounds(this.width / 2 + 5, top, 150, 20)
.build());
} else {
this.addRenderableWidget(
new Button.Builder(Component.translatable("gui.cancel"), p -> onClose())
.bounds(this.width / 2 - 75, top, 150, 20)
.build());
}
}

@Override
Expand Down
Loading