minecraft-src/net/minecraft/client/gui/screens/worldselection/SwitchGrid.java
2025-07-04 03:15:13 +03:00

188 lines
6.8 KiB
Java

package net.minecraft.client.gui.screens.worldselection;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.CycleButton;
import net.minecraft.client.gui.components.MultiLineTextWidget;
import net.minecraft.client.gui.components.StringWidget;
import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.client.gui.layouts.GridLayout;
import net.minecraft.client.gui.layouts.Layout;
import net.minecraft.client.gui.layouts.SpacerElement;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
class SwitchGrid {
private static final int DEFAULT_SWITCH_BUTTON_WIDTH = 44;
private final List<SwitchGrid.LabeledSwitch> switches;
private final Layout layout;
SwitchGrid(List<SwitchGrid.LabeledSwitch> switches, Layout layout) {
this.switches = switches;
this.layout = layout;
}
public Layout layout() {
return this.layout;
}
public void refreshStates() {
this.switches.forEach(SwitchGrid.LabeledSwitch::refreshState);
}
public static SwitchGrid.Builder builder(int width) {
return new SwitchGrid.Builder(width);
}
@Environment(EnvType.CLIENT)
public static class Builder {
final int width;
private final List<SwitchGrid.SwitchBuilder> switchBuilders = new ArrayList();
int paddingLeft;
int rowSpacing = 4;
int rowCount;
Optional<SwitchGrid.InfoUnderneathSettings> infoUnderneath = Optional.empty();
public Builder(int width) {
this.width = width;
}
void increaseRow() {
this.rowCount++;
}
public SwitchGrid.SwitchBuilder addSwitch(Component label, BooleanSupplier stateSupplier, Consumer<Boolean> onClicked) {
SwitchGrid.SwitchBuilder switchBuilder = new SwitchGrid.SwitchBuilder(label, stateSupplier, onClicked, 44);
this.switchBuilders.add(switchBuilder);
return switchBuilder;
}
public SwitchGrid.Builder withPaddingLeft(int paddingLeft) {
this.paddingLeft = paddingLeft;
return this;
}
public SwitchGrid.Builder withRowSpacing(int rowSpacing) {
this.rowSpacing = rowSpacing;
return this;
}
public SwitchGrid build() {
GridLayout gridLayout = new GridLayout().rowSpacing(this.rowSpacing);
gridLayout.addChild(SpacerElement.width(this.width - 44), 0, 0);
gridLayout.addChild(SpacerElement.width(44), 0, 1);
List<SwitchGrid.LabeledSwitch> list = new ArrayList();
this.rowCount = 0;
for (SwitchGrid.SwitchBuilder switchBuilder : this.switchBuilders) {
list.add(switchBuilder.build(this, gridLayout, 0));
}
gridLayout.arrangeElements();
SwitchGrid switchGrid = new SwitchGrid(list, gridLayout);
switchGrid.refreshStates();
return switchGrid;
}
public SwitchGrid.Builder withInfoUnderneath(int maxInfoRows, boolean alwaysMaxHeight) {
this.infoUnderneath = Optional.of(new SwitchGrid.InfoUnderneathSettings(maxInfoRows, alwaysMaxHeight));
return this;
}
}
@Environment(EnvType.CLIENT)
record InfoUnderneathSettings(int maxInfoRows, boolean alwaysMaxHeight) {
}
@Environment(EnvType.CLIENT)
record LabeledSwitch(CycleButton<Boolean> button, BooleanSupplier stateSupplier, @Nullable BooleanSupplier isActiveCondition) {
public void refreshState() {
this.button.setValue(this.stateSupplier.getAsBoolean());
if (this.isActiveCondition != null) {
this.button.active = this.isActiveCondition.getAsBoolean();
}
}
}
@Environment(EnvType.CLIENT)
public static class SwitchBuilder {
private final Component label;
private final BooleanSupplier stateSupplier;
private final Consumer<Boolean> onClicked;
@Nullable
private Component info;
@Nullable
private BooleanSupplier isActiveCondition;
private final int buttonWidth;
SwitchBuilder(Component label, BooleanSupplier stateSupplier, Consumer<Boolean> onClicked, int buttonWidth) {
this.label = label;
this.stateSupplier = stateSupplier;
this.onClicked = onClicked;
this.buttonWidth = buttonWidth;
}
public SwitchGrid.SwitchBuilder withIsActiveCondition(BooleanSupplier isActiveCondition) {
this.isActiveCondition = isActiveCondition;
return this;
}
public SwitchGrid.SwitchBuilder withInfo(Component info) {
this.info = info;
return this;
}
SwitchGrid.LabeledSwitch build(SwitchGrid.Builder builder, GridLayout gridLayout, int column) {
builder.increaseRow();
StringWidget stringWidget = new StringWidget(this.label, Minecraft.getInstance().font).alignLeft();
gridLayout.addChild(stringWidget, builder.rowCount, column, gridLayout.newCellSettings().align(0.0F, 0.5F).paddingLeft(builder.paddingLeft));
Optional<SwitchGrid.InfoUnderneathSettings> optional = builder.infoUnderneath;
CycleButton.Builder<Boolean> builder2 = CycleButton.onOffBuilder(this.stateSupplier.getAsBoolean());
builder2.displayOnlyValue();
boolean bl = this.info != null && optional.isEmpty();
if (bl) {
Tooltip tooltip = Tooltip.create(this.info);
builder2.withTooltip(boolean_ -> tooltip);
}
if (this.info != null && !bl) {
builder2.withCustomNarration(cycleButtonx -> CommonComponents.joinForNarration(this.label, cycleButtonx.createDefaultNarrationMessage(), this.info));
} else {
builder2.withCustomNarration(cycleButtonx -> CommonComponents.joinForNarration(this.label, cycleButtonx.createDefaultNarrationMessage()));
}
CycleButton<Boolean> cycleButton = builder2.create(
0, 0, this.buttonWidth, 20, Component.empty(), (cycleButtonx, boolean_) -> this.onClicked.accept(boolean_)
);
if (this.isActiveCondition != null) {
cycleButton.active = this.isActiveCondition.getAsBoolean();
}
gridLayout.addChild(cycleButton, builder.rowCount, column + 1, gridLayout.newCellSettings().alignHorizontallyRight());
if (this.info != null) {
optional.ifPresent(infoUnderneathSettings -> {
Component component = this.info.copy().withStyle(ChatFormatting.GRAY);
Font font = Minecraft.getInstance().font;
MultiLineTextWidget multiLineTextWidget = new MultiLineTextWidget(component, font);
multiLineTextWidget.setMaxWidth(builder.width - builder.paddingLeft - this.buttonWidth);
multiLineTextWidget.setMaxRows(infoUnderneathSettings.maxInfoRows());
builder.increaseRow();
int j = infoUnderneathSettings.alwaysMaxHeight ? 9 * infoUnderneathSettings.maxInfoRows - multiLineTextWidget.getHeight() : 0;
gridLayout.addChild(multiLineTextWidget, builder.rowCount, column, gridLayout.newCellSettings().paddingTop(-builder.rowSpacing).paddingBottom(j));
});
}
return new SwitchGrid.LabeledSwitch(cycleButton, this.stateSupplier, this.isActiveCondition);
}
}
}