package net.minecraft.client.gui.components; import java.util.ArrayList; import java.util.List; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.locale.Language; import net.minecraft.network.chat.Component; import net.minecraft.util.FormattedCharSequence; import org.jetbrains.annotations.Nullable; @Environment(EnvType.CLIENT) public interface MultiLineLabel { MultiLineLabel EMPTY = new MultiLineLabel() { @Override public void renderCentered(GuiGraphics guiGraphics, int x, int y) { } @Override public void renderCentered(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color) { } @Override public void renderLeftAligned(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color) { } @Override public int renderLeftAlignedNoShadow(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color) { return y; } @Override public int getLineCount() { return 0; } @Override public int getWidth() { return 0; } }; static MultiLineLabel create(Font font, Component... components) { return create(font, Integer.MAX_VALUE, Integer.MAX_VALUE, components); } static MultiLineLabel create(Font font, int maxWidth, Component... components) { return create(font, maxWidth, Integer.MAX_VALUE, components); } static MultiLineLabel create(Font font, Component component, int maxWidth) { return create(font, maxWidth, Integer.MAX_VALUE, component); } static MultiLineLabel create(Font font, int maxWidth, int maxRows, Component... components) { return components.length == 0 ? EMPTY : new MultiLineLabel() { @Nullable private List cachedTextAndWidth; @Nullable private Language splitWithLanguage; @Override public void renderCentered(GuiGraphics guiGraphics, int x, int y) { this.renderCentered(guiGraphics, x, y, 9, -1); } @Override public void renderCentered(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color) { int i = y; for (MultiLineLabel.TextAndWidth textAndWidth : this.getSplitMessage()) { guiGraphics.drawCenteredString(font, textAndWidth.text, x, i, color); i += lineHeight; } } @Override public void renderLeftAligned(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color) { int i = y; for (MultiLineLabel.TextAndWidth textAndWidth : this.getSplitMessage()) { guiGraphics.drawString(font, textAndWidth.text, x, i, color); i += lineHeight; } } @Override public int renderLeftAlignedNoShadow(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color) { int i = y; for (MultiLineLabel.TextAndWidth textAndWidth : this.getSplitMessage()) { guiGraphics.drawString(font, textAndWidth.text, x, i, color, false); i += lineHeight; } return i; } private List getSplitMessage() { Language language = Language.getInstance(); if (this.cachedTextAndWidth != null && language == this.splitWithLanguage) { return this.cachedTextAndWidth; } else { this.splitWithLanguage = language; List list = new ArrayList(); for (Component component : components) { list.addAll(font.split(component, maxWidth)); } this.cachedTextAndWidth = new ArrayList(); for (FormattedCharSequence formattedCharSequence : list.subList(0, Math.min(list.size(), maxRows))) { this.cachedTextAndWidth.add(new MultiLineLabel.TextAndWidth(formattedCharSequence, font.width(formattedCharSequence))); } return this.cachedTextAndWidth; } } @Override public int getLineCount() { return this.getSplitMessage().size(); } @Override public int getWidth() { return Math.min(maxWidth, this.getSplitMessage().stream().mapToInt(MultiLineLabel.TextAndWidth::width).max().orElse(0)); } }; } void renderCentered(GuiGraphics guiGraphics, int x, int y); void renderCentered(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color); void renderLeftAligned(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color); int renderLeftAlignedNoShadow(GuiGraphics guiGraphics, int x, int y, int lineHeight, int color); int getLineCount(); int getWidth(); @Environment(EnvType.CLIENT) public record TextAndWidth(FormattedCharSequence text, int width) { } }