diff --git a/Common/src/main/java/mezz/jei/common/gui/elements/DrawableBlank.java b/Common/src/main/java/mezz/jei/common/gui/elements/DrawableBlank.java index a586d53e8..77144f893 100644 --- a/Common/src/main/java/mezz/jei/common/gui/elements/DrawableBlank.java +++ b/Common/src/main/java/mezz/jei/common/gui/elements/DrawableBlank.java @@ -6,6 +6,8 @@ import mezz.jei.api.gui.drawable.IDrawableStatic; public record DrawableBlank(int width, int height) implements IDrawableStatic, IDrawableAnimated, IScalableDrawable { + public static final DrawableBlank EMPTY = new DrawableBlank(0, 0); + @Override public int getWidth() { return width; diff --git a/Common/src/main/java/mezz/jei/common/gui/elements/DrawableWrappedText.java b/Common/src/main/java/mezz/jei/common/gui/elements/DrawableWrappedText.java new file mode 100644 index 000000000..e7780ca00 --- /dev/null +++ b/Common/src/main/java/mezz/jei/common/gui/elements/DrawableWrappedText.java @@ -0,0 +1,53 @@ +package mezz.jei.common.gui.elements; + +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.common.util.StringUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.util.FormattedCharSequence; + +import java.util.List; + +public class DrawableWrappedText implements IDrawable { + private static final int lineSpacing = 2; + + private final List descriptionLines; + private final int lineHeight; + private final int width; + private final int height; + + public DrawableWrappedText(List text, int maxWidth) { + Minecraft minecraft = Minecraft.getInstance(); + this.lineHeight = minecraft.font.lineHeight + lineSpacing; + this.descriptionLines = StringUtil.splitLines(text, maxWidth); + this.width = maxWidth; + this.height = lineHeight * descriptionLines.size() - lineSpacing; + } + + @Override + public int getWidth() { + return width; + } + + @Override + public int getHeight() { + return height; + } + + @Override + public void draw(GuiGraphics guiGraphics, int xOffset, int yOffset) { + Language language = Language.getInstance(); + Minecraft minecraft = Minecraft.getInstance(); + Font font = minecraft.font; + + int yPos = 0; + for (FormattedText descriptionLine : descriptionLines) { + FormattedCharSequence charSequence = language.getVisualOrder(descriptionLine); + guiGraphics.drawString(font, charSequence, 0, yPos, 0xFF000000, false); + yPos += lineHeight; + } + } +} diff --git a/CommonApi/src/main/java/mezz/jei/api/gui/widgets/IRecipeExtrasBuilder.java b/CommonApi/src/main/java/mezz/jei/api/gui/widgets/IRecipeExtrasBuilder.java index 58e53faa8..855e7e7fe 100644 --- a/CommonApi/src/main/java/mezz/jei/api/gui/widgets/IRecipeExtrasBuilder.java +++ b/CommonApi/src/main/java/mezz/jei/api/gui/widgets/IRecipeExtrasBuilder.java @@ -41,4 +41,14 @@ public interface IRecipeExtrasBuilder { * @since 19.6.0 */ void addGuiEventListener(IJeiGuiEventListener guiEventListener); + + /** + * Create and add a new scroll box widget. + * Handles displaying drawable contents in a scrolling area with a scrollbar. + * + * Set the contents by using the methods in {@link IScrollBoxWidget}. + * + * @since 19.18.9 + */ + IScrollBoxWidget addScrollBoxWidget(int width, int height, int xPos, int yPos); } diff --git a/CommonApi/src/main/java/mezz/jei/api/gui/widgets/IScrollBoxWidget.java b/CommonApi/src/main/java/mezz/jei/api/gui/widgets/IScrollBoxWidget.java index 18635ff66..9a480c3f2 100644 --- a/CommonApi/src/main/java/mezz/jei/api/gui/widgets/IScrollBoxWidget.java +++ b/CommonApi/src/main/java/mezz/jei/api/gui/widgets/IScrollBoxWidget.java @@ -1,18 +1,48 @@ package mezz.jei.api.gui.widgets; +import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.inputs.IJeiInputHandler; -import mezz.jei.api.helpers.IGuiHelper; -import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.network.chat.FormattedText; + +import java.util.List; /** * A smooth-scrolling area with a scrollbar. * - * Create one with {@link IGuiHelper#createScrollBoxWidget}, and then - * add it to your recipe in {@link IRecipeCategory#createRecipeExtras} - * using {@link IRecipeExtrasBuilder#addWidget} and {@link IRecipeExtrasBuilder#addInputHandler}. + * Create one with {@link IRecipeExtrasBuilder#addScrollBoxWidget}. * * @since 19.8.0 */ public interface IScrollBoxWidget extends IRecipeWidget, IJeiInputHandler { + /** + * Get the width available for displaying contents in the scroll box. + * The scroll bar takes up some of the space, so this can be used in order to create accurately-sized contents. + * + * @since 19.18.9 + */ + int getContentAreaWidth(); + + /** + * Get the visible height for displaying contents in the scroll box. + * The actual height of the contents can be taller, because the box can scroll to show more. + * + * @since 19.18.9 + */ + int getContentAreaHeight(); + + /** + * Set the contents to display inside the scroll box. + * The drawable width should match {@link #getContentAreaWidth()}, and the height can be any height. + * + * @since 19.18.9 + */ + IScrollBoxWidget setContents(IDrawable contents); + /** + * Display text in the scroll box. + * Text will be automatically wrapped in order to fit inside of {@link #getContentAreaWidth()}. + * + * @since 19.18.9 + */ + IScrollBoxWidget setContents(List text); } diff --git a/CommonApi/src/main/java/mezz/jei/api/helpers/IGuiHelper.java b/CommonApi/src/main/java/mezz/jei/api/helpers/IGuiHelper.java index 0fd96d92f..2ea0d5428 100644 --- a/CommonApi/src/main/java/mezz/jei/api/helpers/IGuiHelper.java +++ b/CommonApi/src/main/java/mezz/jei/api/helpers/IGuiHelper.java @@ -8,6 +8,7 @@ import mezz.jei.api.gui.drawable.IDrawableBuilder; import mezz.jei.api.gui.drawable.IDrawableStatic; import mezz.jei.api.gui.ingredient.ICraftingGridHelper; +import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder; import mezz.jei.api.gui.widgets.IRecipeWidget; import mezz.jei.api.gui.widgets.IScrollBoxWidget; import mezz.jei.api.gui.widgets.IScrollGridWidgetFactory; @@ -186,14 +187,20 @@ default IDrawable createDrawableItemLike(ItemLike itemLike) { * Handles displaying drawable contents in a scrolling area. * * @since 19.8.0 + * + * @deprecated use {@link IRecipeExtrasBuilder#addScrollBoxWidget} */ + @Deprecated(since = "19.18.9", forRemoval = true) IScrollBoxWidget createScrollBoxWidget(IDrawable contents, int visibleHeight, int xPos, int yPos); /** * The amount of extra horizontal space that a {@link IScrollBoxWidget} takes up with its scroll bar. * * @since 19.8.0 + * + * @deprecated use {@link IRecipeExtrasBuilder#addScrollBoxWidget} */ + @Deprecated(since = "19.18.9", forRemoval = true) int getScrollBoxScrollbarExtraWidth(); /** diff --git a/Library/src/main/java/mezz/jei/library/gui/helpers/GuiHelper.java b/Library/src/main/java/mezz/jei/library/gui/helpers/GuiHelper.java index 9b5417a28..74a589fe9 100644 --- a/Library/src/main/java/mezz/jei/library/gui/helpers/GuiHelper.java +++ b/Library/src/main/java/mezz/jei/library/gui/helpers/GuiHelper.java @@ -150,11 +150,15 @@ public IScrollGridWidgetFactory createScrollGridFactory(int columns, int visi return new ScrollGridWidgetFactory<>(this, columns, visibleRows); } + @SuppressWarnings("removal") @Override public IScrollBoxWidget createScrollBoxWidget(IDrawable contents, int visibleHeight, int xPos, int yPos) { - return new ScrollBoxRecipeWidget(contents, visibleHeight, xPos, yPos); + ScrollBoxRecipeWidget widget = new ScrollBoxRecipeWidget(contents.getWidth() + getScrollBoxScrollbarExtraWidth(), visibleHeight, xPos, yPos); + widget.setContents(contents); + return widget; } + @SuppressWarnings("removal") @Override public int getScrollBoxScrollbarExtraWidth() { return AbstractScrollWidget.getScrollBoxScrollbarExtraWidth(); diff --git a/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java b/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java index 9d127190c..cc7794323 100644 --- a/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java +++ b/Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java @@ -12,6 +12,7 @@ import mezz.jei.api.gui.inputs.IJeiInputHandler; import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder; import mezz.jei.api.gui.widgets.IRecipeWidget; +import mezz.jei.api.gui.widgets.IScrollBoxWidget; import mezz.jei.api.gui.widgets.ISlottedRecipeWidget; import mezz.jei.api.gui.widgets.ISlottedWidgetFactory; import mezz.jei.api.ingredients.ITypedIngredient; @@ -30,6 +31,7 @@ import mezz.jei.library.gui.recipes.OutputSlotTooltipCallback; import mezz.jei.library.gui.recipes.RecipeLayout; import mezz.jei.library.gui.recipes.ShapelessIcon; +import mezz.jei.library.gui.widgets.ScrollBoxRecipeWidget; import mezz.jei.library.ingredients.DisplayIngredientAcceptor; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; @@ -128,6 +130,14 @@ public void addGuiEventListener(IJeiGuiEventListener guiEventListener) { this.guiEventListeners.add(guiEventListener); } + @Override + public IScrollBoxWidget addScrollBoxWidget(int width, int height, int xPos, int yPos) { + ScrollBoxRecipeWidget widget = new ScrollBoxRecipeWidget(width, height, xPos, yPos); + addWidget(widget); + addInputHandler(widget); + return widget; + } + @Override public void moveRecipeTransferButton(int posX, int posY) { this.recipeTransferX = posX; diff --git a/Library/src/main/java/mezz/jei/library/gui/widgets/AbstractScrollWidget.java b/Library/src/main/java/mezz/jei/library/gui/widgets/AbstractScrollWidget.java index be6f25cfd..10e6beaea 100644 --- a/Library/src/main/java/mezz/jei/library/gui/widgets/AbstractScrollWidget.java +++ b/Library/src/main/java/mezz/jei/library/gui/widgets/AbstractScrollWidget.java @@ -31,7 +31,9 @@ protected static ImmutableRect2i calculateScrollArea(int width, int height) { ); } - private final ScreenRectangle area; + protected final ScreenRectangle area; + protected final ScreenRectangle contentsArea; + private final ImmutableRect2i scrollArea; private final DrawableNineSliceTexture scrollbarMarker; private final DrawableNineSliceTexture scrollbarBackground; @@ -50,6 +52,12 @@ public AbstractScrollWidget(ScreenRectangle area) { Textures textures = Internal.getTextures(); this.scrollbarMarker = textures.getScrollbarMarker(); this.scrollbarBackground = textures.getScrollbarBackground(); + this.contentsArea = new ScreenRectangle( + 0, + 0, + area.width() - getScrollBoxScrollbarExtraWidth(), + area.height() + ); } protected ImmutableRect2i calculateScrollbarMarkerArea() { diff --git a/Library/src/main/java/mezz/jei/library/gui/widgets/ScrollBoxRecipeWidget.java b/Library/src/main/java/mezz/jei/library/gui/widgets/ScrollBoxRecipeWidget.java index 48be28bcf..8aa65faa3 100644 --- a/Library/src/main/java/mezz/jei/library/gui/widgets/ScrollBoxRecipeWidget.java +++ b/Library/src/main/java/mezz/jei/library/gui/widgets/ScrollBoxRecipeWidget.java @@ -7,43 +7,53 @@ import mezz.jei.common.Internal; import mezz.jei.common.config.IClientConfig; import mezz.jei.common.config.IJeiClientConfigs; +import mezz.jei.common.gui.elements.DrawableBlank; +import mezz.jei.common.gui.elements.DrawableWrappedText; import mezz.jei.common.util.MathUtil; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.navigation.ScreenRectangle; +import net.minecraft.network.chat.FormattedText; import org.joml.Matrix4f; +import java.util.List; + public class ScrollBoxRecipeWidget extends AbstractScrollWidget implements IScrollBoxWidget, IJeiInputHandler { - private final int visibleHeight; - private final int hiddenHeight; - private final ScreenRectangle contentsArea; - private final IDrawable contents; + private IDrawable contents = DrawableBlank.EMPTY; + + public ScrollBoxRecipeWidget(int width, int height, int xPos, int yPos) { + super(new ScreenRectangle(xPos, yPos, width, height)); + } + + @Override + public int getContentAreaWidth() { + return contentsArea.width(); + } + + @Override + public int getContentAreaHeight() { + return contentsArea.height(); + } - public ScrollBoxRecipeWidget(IDrawable contents, int visibleHeight, int xPos, int yPos) { - super(new ScreenRectangle( - xPos, - yPos, - contents.getWidth() + AbstractScrollWidget.getScrollBoxScrollbarExtraWidth(), - visibleHeight - )); + @Override + public IScrollBoxWidget setContents(IDrawable contents) { this.contents = contents; - this.visibleHeight = visibleHeight; - this.contentsArea = new ScreenRectangle( - 0, - 0, - contents.getWidth(), - visibleHeight - ); - this.hiddenHeight = Math.max(contents.getHeight() - visibleHeight, 0); + return this; + } + + @Override + public IScrollBoxWidget setContents(List text) { + this.contents = new DrawableWrappedText(text, getContentAreaWidth()); + return this; } @Override protected int getVisibleAmount() { - return visibleHeight; + return contentsArea.height(); } @Override protected int getHiddenAmount() { - return hiddenHeight; + return Math.max(contents.getHeight() - contentsArea.height(), 0); } @Override @@ -60,7 +70,7 @@ protected void drawContents(GuiGraphics guiGraphics, double mouseX, double mouse scissorArea.bottom() ); poseStack.pushPose(); - float scrollAmount = hiddenHeight * scrollOffsetY; + float scrollAmount = getHiddenAmount() * scrollOffsetY; poseStack.translate(0.0, -scrollAmount, 0.0); try { contents.draw(guiGraphics); diff --git a/Library/src/main/java/mezz/jei/library/plugins/jei/info/IngredientInfoRecipeCategory.java b/Library/src/main/java/mezz/jei/library/plugins/jei/info/IngredientInfoRecipeCategory.java index 91f9cf959..65ebdadb1 100644 --- a/Library/src/main/java/mezz/jei/library/plugins/jei/info/IngredientInfoRecipeCategory.java +++ b/Library/src/main/java/mezz/jei/library/plugins/jei/info/IngredientInfoRecipeCategory.java @@ -6,7 +6,6 @@ import mezz.jei.api.gui.builder.IRecipeSlotBuilder; import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder; -import mezz.jei.api.gui.widgets.IScrollBoxWidget; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.recipe.IFocusGroup; @@ -15,33 +14,21 @@ import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.recipe.vanilla.IJeiIngredientInfoRecipe; import mezz.jei.common.gui.textures.Textures; -import mezz.jei.common.util.StringUtil; -import net.minecraft.client.Minecraft; -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.network.chat.FormattedText; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.FormattedCharSequence; import org.jetbrains.annotations.Nullable; -import java.util.List; - public class IngredientInfoRecipeCategory implements IRecipeCategory { private static final int recipeWidth = 170; private static final int recipeHeight = 125; - private static final int lineSpacing = 2; private final IDrawable background; - private final IGuiHelper guiHelper; private final IDrawable icon; private final IDrawable slotBackground; private final Component localizedName; public IngredientInfoRecipeCategory(IGuiHelper guiHelper, Textures textures) { this.background = guiHelper.createBlankDrawable(recipeWidth, recipeHeight); - this.guiHelper = guiHelper; this.icon = textures.getInfoIcon(); this.slotBackground = guiHelper.getSlotDrawable(); this.localizedName = Component.translatable("gui.jei.category.itemInformation"); @@ -71,15 +58,13 @@ public IDrawable getBackground() { public void createRecipeExtras(IRecipeExtrasBuilder builder, IJeiIngredientInfoRecipe recipe, IFocusGroup focuses) { int yPos = slotBackground.getHeight() + 4; int height = recipeHeight - yPos; - int width = recipeWidth - guiHelper.getScrollBoxScrollbarExtraWidth(); - IScrollBoxWidget scrollBoxWidget = guiHelper.createScrollBoxWidget( - new Contents(recipe, width), + builder.addScrollBoxWidget( + recipeWidth, height, 0, yPos - ); - builder.addWidget(scrollBoxWidget); - builder.addInputHandler(scrollBoxWidget); + ) + .setContents(recipe.getDescription()); } @Override @@ -106,42 +91,4 @@ private static void addIngredient(ITypedIngredient typedIngredient, IIngr slotBuilder.addIngredient(typedIngredient.getType(), typedIngredient.getIngredient()); } - private static class Contents implements IDrawable { - private final List descriptionLines; - private final int lineHeight; - private final int width; - private final int height; - - public Contents(IJeiIngredientInfoRecipe recipe, int width) { - Minecraft minecraft = Minecraft.getInstance(); - this.lineHeight = minecraft.font.lineHeight + lineSpacing; - this.descriptionLines = StringUtil.splitLines(recipe.getDescription(), width); - this.width = width; - this.height = lineHeight * descriptionLines.size() - lineSpacing; - } - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public void draw(GuiGraphics guiGraphics, int xOffset, int yOffset) { - Language language = Language.getInstance(); - Minecraft minecraft = Minecraft.getInstance(); - Font font = minecraft.font; - - int yPos = 0; - for (FormattedText descriptionLine : descriptionLines) { - FormattedCharSequence charSequence = language.getVisualOrder(descriptionLine); - guiGraphics.drawString(font, charSequence, 0, yPos, 0xFF000000, false); - yPos += lineHeight; - } - } - } } diff --git a/gradle.properties b/gradle.properties index c65654a63..96b2c4f73 100644 --- a/gradle.properties +++ b/gradle.properties @@ -74,4 +74,4 @@ modrinthId=u6dRKJwZ jUnitVersion=5.8.2 # Version -specificationVersion=19.18.8 +specificationVersion=19.18.9