Skip to content

Commit a7d7a18

Browse files
committed
Simplify creation of scrollbox widgets
1 parent 0f7bde7 commit a7d7a18

File tree

11 files changed

+168
-87
lines changed

11 files changed

+168
-87
lines changed

Common/src/main/java/mezz/jei/common/gui/elements/DrawableBlank.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import mezz.jei.api.gui.drawable.IDrawableStatic;
77

88
public record DrawableBlank(int width, int height) implements IDrawableStatic, IDrawableAnimated, IScalableDrawable {
9+
public static final DrawableBlank EMPTY = new DrawableBlank(0, 0);
10+
911
@Override
1012
public int getWidth() {
1113
return width;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package mezz.jei.common.gui.elements;
2+
3+
import mezz.jei.api.gui.drawable.IDrawable;
4+
import mezz.jei.common.util.StringUtil;
5+
import net.minecraft.client.Minecraft;
6+
import net.minecraft.client.gui.Font;
7+
import net.minecraft.client.gui.GuiGraphics;
8+
import net.minecraft.locale.Language;
9+
import net.minecraft.network.chat.FormattedText;
10+
import net.minecraft.util.FormattedCharSequence;
11+
12+
import java.util.List;
13+
14+
public class DrawableWrappedText implements IDrawable {
15+
private static final int lineSpacing = 2;
16+
17+
private final List<FormattedText> descriptionLines;
18+
private final int lineHeight;
19+
private final int width;
20+
private final int height;
21+
22+
public DrawableWrappedText(List<FormattedText> text, int maxWidth) {
23+
Minecraft minecraft = Minecraft.getInstance();
24+
this.lineHeight = minecraft.font.lineHeight + lineSpacing;
25+
this.descriptionLines = StringUtil.splitLines(text, maxWidth);
26+
this.width = maxWidth;
27+
this.height = lineHeight * descriptionLines.size() - lineSpacing;
28+
}
29+
30+
@Override
31+
public int getWidth() {
32+
return width;
33+
}
34+
35+
@Override
36+
public int getHeight() {
37+
return height;
38+
}
39+
40+
@Override
41+
public void draw(GuiGraphics guiGraphics, int xOffset, int yOffset) {
42+
Language language = Language.getInstance();
43+
Minecraft minecraft = Minecraft.getInstance();
44+
Font font = minecraft.font;
45+
46+
int yPos = 0;
47+
for (FormattedText descriptionLine : descriptionLines) {
48+
FormattedCharSequence charSequence = language.getVisualOrder(descriptionLine);
49+
guiGraphics.drawString(font, charSequence, 0, yPos, 0xFF000000, false);
50+
yPos += lineHeight;
51+
}
52+
}
53+
}

CommonApi/src/main/java/mezz/jei/api/gui/widgets/IRecipeExtrasBuilder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,14 @@ public interface IRecipeExtrasBuilder {
4141
* @since 19.6.0
4242
*/
4343
void addGuiEventListener(IJeiGuiEventListener guiEventListener);
44+
45+
/**
46+
* Create and add a new scroll box widget.
47+
* Handles displaying drawable contents in a scrolling area with a scrollbar.
48+
*
49+
* Set the contents by using the methods in {@link IScrollBoxWidget}.
50+
*
51+
* @since 19.18.9
52+
*/
53+
IScrollBoxWidget addScrollBoxWidget(int width, int height, int xPos, int yPos);
4454
}
Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,48 @@
11
package mezz.jei.api.gui.widgets;
22

3+
import mezz.jei.api.gui.drawable.IDrawable;
34
import mezz.jei.api.gui.inputs.IJeiInputHandler;
4-
import mezz.jei.api.helpers.IGuiHelper;
5-
import mezz.jei.api.recipe.category.IRecipeCategory;
5+
import net.minecraft.network.chat.FormattedText;
6+
7+
import java.util.List;
68

79
/**
810
* A smooth-scrolling area with a scrollbar.
911
*
10-
* Create one with {@link IGuiHelper#createScrollBoxWidget}, and then
11-
* add it to your recipe in {@link IRecipeCategory#createRecipeExtras}
12-
* using {@link IRecipeExtrasBuilder#addWidget} and {@link IRecipeExtrasBuilder#addInputHandler}.
12+
* Create one with {@link IRecipeExtrasBuilder#addScrollBoxWidget}.
1313
*
1414
* @since 19.8.0
1515
*/
1616
public interface IScrollBoxWidget extends IRecipeWidget, IJeiInputHandler {
17+
/**
18+
* Get the width available for displaying contents in the scroll box.
19+
* The scroll bar takes up some of the space, so this can be used in order to create accurately-sized contents.
20+
*
21+
* @since 19.18.9
22+
*/
23+
int getContentAreaWidth();
24+
25+
/**
26+
* Get the visible height for displaying contents in the scroll box.
27+
* The actual height of the contents can be taller, because the box can scroll to show more.
28+
*
29+
* @since 19.18.9
30+
*/
31+
int getContentAreaHeight();
32+
33+
/**
34+
* Set the contents to display inside the scroll box.
35+
* The drawable width should match {@link #getContentAreaWidth()}, and the height can be any height.
36+
*
37+
* @since 19.18.9
38+
*/
39+
IScrollBoxWidget setContents(IDrawable contents);
1740

41+
/**
42+
* Display text in the scroll box.
43+
* Text will be automatically wrapped in order to fit inside of {@link #getContentAreaWidth()}.
44+
*
45+
* @since 19.18.9
46+
*/
47+
IScrollBoxWidget setContents(List<FormattedText> text);
1848
}

CommonApi/src/main/java/mezz/jei/api/helpers/IGuiHelper.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import mezz.jei.api.gui.drawable.IDrawableBuilder;
99
import mezz.jei.api.gui.drawable.IDrawableStatic;
1010
import mezz.jei.api.gui.ingredient.ICraftingGridHelper;
11+
import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder;
1112
import mezz.jei.api.gui.widgets.IRecipeWidget;
1213
import mezz.jei.api.gui.widgets.IScrollBoxWidget;
1314
import mezz.jei.api.gui.widgets.IScrollGridWidgetFactory;
@@ -186,14 +187,20 @@ default IDrawable createDrawableItemLike(ItemLike itemLike) {
186187
* Handles displaying drawable contents in a scrolling area.
187188
*
188189
* @since 19.8.0
190+
*
191+
* @deprecated use {@link IRecipeExtrasBuilder#addScrollBoxWidget}
189192
*/
193+
@Deprecated(since = "19.18.9", forRemoval = true)
190194
IScrollBoxWidget createScrollBoxWidget(IDrawable contents, int visibleHeight, int xPos, int yPos);
191195

192196
/**
193197
* The amount of extra horizontal space that a {@link IScrollBoxWidget} takes up with its scroll bar.
194198
*
195199
* @since 19.8.0
200+
*
201+
* @deprecated use {@link IRecipeExtrasBuilder#addScrollBoxWidget}
196202
*/
203+
@Deprecated(since = "19.18.9", forRemoval = true)
197204
int getScrollBoxScrollbarExtraWidth();
198205

199206
/**

Library/src/main/java/mezz/jei/library/gui/helpers/GuiHelper.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,15 @@ public IScrollGridWidgetFactory<?> createScrollGridFactory(int columns, int visi
150150
return new ScrollGridWidgetFactory<>(this, columns, visibleRows);
151151
}
152152

153+
@SuppressWarnings("removal")
153154
@Override
154155
public IScrollBoxWidget createScrollBoxWidget(IDrawable contents, int visibleHeight, int xPos, int yPos) {
155-
return new ScrollBoxRecipeWidget(contents, visibleHeight, xPos, yPos);
156+
ScrollBoxRecipeWidget widget = new ScrollBoxRecipeWidget(contents.getWidth() + getScrollBoxScrollbarExtraWidth(), visibleHeight, xPos, yPos);
157+
widget.setContents(contents);
158+
return widget;
156159
}
157160

161+
@SuppressWarnings("removal")
158162
@Override
159163
public int getScrollBoxScrollbarExtraWidth() {
160164
return AbstractScrollWidget.getScrollBoxScrollbarExtraWidth();

Library/src/main/java/mezz/jei/library/gui/recipes/layout/builder/RecipeLayoutBuilder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import mezz.jei.api.gui.inputs.IJeiInputHandler;
1313
import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder;
1414
import mezz.jei.api.gui.widgets.IRecipeWidget;
15+
import mezz.jei.api.gui.widgets.IScrollBoxWidget;
1516
import mezz.jei.api.gui.widgets.ISlottedRecipeWidget;
1617
import mezz.jei.api.gui.widgets.ISlottedWidgetFactory;
1718
import mezz.jei.api.ingredients.ITypedIngredient;
@@ -30,6 +31,7 @@
3031
import mezz.jei.library.gui.recipes.OutputSlotTooltipCallback;
3132
import mezz.jei.library.gui.recipes.RecipeLayout;
3233
import mezz.jei.library.gui.recipes.ShapelessIcon;
34+
import mezz.jei.library.gui.widgets.ScrollBoxRecipeWidget;
3335
import mezz.jei.library.ingredients.DisplayIngredientAcceptor;
3436
import net.minecraft.resources.ResourceLocation;
3537
import org.jetbrains.annotations.Nullable;
@@ -128,6 +130,14 @@ public void addGuiEventListener(IJeiGuiEventListener guiEventListener) {
128130
this.guiEventListeners.add(guiEventListener);
129131
}
130132

133+
@Override
134+
public IScrollBoxWidget addScrollBoxWidget(int width, int height, int xPos, int yPos) {
135+
ScrollBoxRecipeWidget widget = new ScrollBoxRecipeWidget(width, height, xPos, yPos);
136+
addWidget(widget);
137+
addInputHandler(widget);
138+
return widget;
139+
}
140+
131141
@Override
132142
public void moveRecipeTransferButton(int posX, int posY) {
133143
this.recipeTransferX = posX;

Library/src/main/java/mezz/jei/library/gui/widgets/AbstractScrollWidget.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ protected static ImmutableRect2i calculateScrollArea(int width, int height) {
3131
);
3232
}
3333

34-
private final ScreenRectangle area;
34+
protected final ScreenRectangle area;
35+
protected final ScreenRectangle contentsArea;
36+
3537
private final ImmutableRect2i scrollArea;
3638
private final DrawableNineSliceTexture scrollbarMarker;
3739
private final DrawableNineSliceTexture scrollbarBackground;
@@ -50,6 +52,12 @@ public AbstractScrollWidget(ScreenRectangle area) {
5052
Textures textures = Internal.getTextures();
5153
this.scrollbarMarker = textures.getScrollbarMarker();
5254
this.scrollbarBackground = textures.getScrollbarBackground();
55+
this.contentsArea = new ScreenRectangle(
56+
0,
57+
0,
58+
area.width() - getScrollBoxScrollbarExtraWidth(),
59+
area.height()
60+
);
5361
}
5462

5563
protected ImmutableRect2i calculateScrollbarMarkerArea() {

Library/src/main/java/mezz/jei/library/gui/widgets/ScrollBoxRecipeWidget.java

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,53 @@
77
import mezz.jei.common.Internal;
88
import mezz.jei.common.config.IClientConfig;
99
import mezz.jei.common.config.IJeiClientConfigs;
10+
import mezz.jei.common.gui.elements.DrawableBlank;
11+
import mezz.jei.common.gui.elements.DrawableWrappedText;
1012
import mezz.jei.common.util.MathUtil;
1113
import net.minecraft.client.gui.GuiGraphics;
1214
import net.minecraft.client.gui.navigation.ScreenRectangle;
15+
import net.minecraft.network.chat.FormattedText;
1316
import org.joml.Matrix4f;
1417

18+
import java.util.List;
19+
1520
public class ScrollBoxRecipeWidget extends AbstractScrollWidget implements IScrollBoxWidget, IJeiInputHandler {
16-
private final int visibleHeight;
17-
private final int hiddenHeight;
18-
private final ScreenRectangle contentsArea;
19-
private final IDrawable contents;
21+
private IDrawable contents = DrawableBlank.EMPTY;
22+
23+
public ScrollBoxRecipeWidget(int width, int height, int xPos, int yPos) {
24+
super(new ScreenRectangle(xPos, yPos, width, height));
25+
}
26+
27+
@Override
28+
public int getContentAreaWidth() {
29+
return contentsArea.width();
30+
}
31+
32+
@Override
33+
public int getContentAreaHeight() {
34+
return contentsArea.height();
35+
}
2036

21-
public ScrollBoxRecipeWidget(IDrawable contents, int visibleHeight, int xPos, int yPos) {
22-
super(new ScreenRectangle(
23-
xPos,
24-
yPos,
25-
contents.getWidth() + AbstractScrollWidget.getScrollBoxScrollbarExtraWidth(),
26-
visibleHeight
27-
));
37+
@Override
38+
public IScrollBoxWidget setContents(IDrawable contents) {
2839
this.contents = contents;
29-
this.visibleHeight = visibleHeight;
30-
this.contentsArea = new ScreenRectangle(
31-
0,
32-
0,
33-
contents.getWidth(),
34-
visibleHeight
35-
);
36-
this.hiddenHeight = Math.max(contents.getHeight() - visibleHeight, 0);
40+
return this;
41+
}
42+
43+
@Override
44+
public IScrollBoxWidget setContents(List<FormattedText> text) {
45+
this.contents = new DrawableWrappedText(text, getContentAreaWidth());
46+
return this;
3747
}
3848

3949
@Override
4050
protected int getVisibleAmount() {
41-
return visibleHeight;
51+
return contentsArea.height();
4252
}
4353

4454
@Override
4555
protected int getHiddenAmount() {
46-
return hiddenHeight;
56+
return Math.max(contents.getHeight() - contentsArea.height(), 0);
4757
}
4858

4959
@Override
@@ -60,7 +70,7 @@ protected void drawContents(GuiGraphics guiGraphics, double mouseX, double mouse
6070
scissorArea.bottom()
6171
);
6272
poseStack.pushPose();
63-
float scrollAmount = hiddenHeight * scrollOffsetY;
73+
float scrollAmount = getHiddenAmount() * scrollOffsetY;
6474
poseStack.translate(0.0, -scrollAmount, 0.0);
6575
try {
6676
contents.draw(guiGraphics);

0 commit comments

Comments
 (0)