Skip to content

Commit 20b6c9f

Browse files
committed
port gui option editor draggable list to components
1 parent 6d395ff commit 20b6c9f

File tree

13 files changed

+488
-300
lines changed

13 files changed

+488
-300
lines changed

common/src/main/java/io/github/notenoughupdates/moulconfig/TitleRenderingBehaviour.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
public enum TitleRenderingBehaviour {
44
WIDE_CENTERED,
5+
WIDE_CENTERED_UNDERLINED,
56
LEFT,
67
;
78
}

common/src/main/java/io/github/notenoughupdates/moulconfig/common/NinePatches.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ object NinePatches {
1111
.mode(NinePatch.Mode.STRETCHING)
1212
.build()
1313
}
14+
fun createWhiteButton(): NinePatch<MyResourceLocation> {
15+
return NinePatch.builder(GuiTextures.BUTTON_WHITE)
16+
.cornerSize(14)
17+
.cornerUv(14 / 32f, 14 / 96F)
18+
.mode(NinePatch.Mode.STRETCHING)
19+
.build()
20+
}
1421

1522
fun createVanillaPanel(): NinePatch<MyResourceLocation> {
1623
return NinePatch.builder(GuiTextures.VANILLA_PANEL)
@@ -19,4 +26,4 @@ object NinePatches {
1926
.mode(NinePatch.Mode.STRETCHING)
2027
.build()
2128
}
22-
}
29+
}

common/src/main/java/io/github/notenoughupdates/moulconfig/gui/GuiOptionEditor.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
package io.github.notenoughupdates.moulconfig.gui;
2222

2323
import io.github.notenoughupdates.moulconfig.DescriptionRendereringBehaviour;
24+
import io.github.notenoughupdates.moulconfig.TitleRenderingBehaviour;
2425
import io.github.notenoughupdates.moulconfig.annotations.SearchTag;
2526
import io.github.notenoughupdates.moulconfig.common.IMinecraft;
2627
import io.github.notenoughupdates.moulconfig.common.RenderContext;
@@ -66,11 +67,20 @@ public void render(RenderContext context, int x, int y, int width) {
6667

6768
var minecraft = context.getMinecraft();
6869
var fr = minecraft.getDefaultFontRenderer();
70+
boolean wideTitle = option.getConfig().getTitleRenderingBehaviour(option) != TitleRenderingBehaviour.LEFT;
71+
int yOffset = wideTitle
72+
? fr.getHeight() + 1 : 5;
6973

7074
context.drawDarkRect(x, y, width, height, true);
71-
context.drawStringCenteredScaledMaxWidth(option.getName(),
72-
fr, x + width / 6, y + 13, true, width / 3 - 10, 0xc0c0c0
73-
);
75+
if (wideTitle) {
76+
context.drawStringCenteredScaledMaxWidth(option.getName(),
77+
fr, x + width / 2, y + 13, true, width - 10, 0xe0e0e0
78+
);
79+
} else {
80+
context.drawStringCenteredScaledMaxWidth(option.getName(),
81+
fr, x + width / 6, y + 13, true, width / 3 - 10, 0xe0e0e0
82+
);
83+
}
7484

7585
float scale = 1;
7686
List<StructuredText> lines;
@@ -83,7 +93,7 @@ public void render(RenderContext context, int x, int y, int width) {
8393
if (scale < 1 / 16f) break;
8494
}
8595
context.pushMatrix();
86-
context.translate(x + 5 + width / 3, y + 5);
96+
context.translate(x + 5 + width / 3, y + yOffset);
8797
context.scale(scale, scale);
8898
context.translate(0, ((descriptionHeight - 10) - (fr.getHeight() + 1) * (lines.size() - 1) * scale) / 2F);
8999
for (var line : lines) {
@@ -94,6 +104,10 @@ public void render(RenderContext context, int x, int y, int width) {
94104
}
95105

96106
public int getHeight() {
107+
return getDescriptionHeight() + (option.getConfig().getTitleRenderingBehaviour(option) != TitleRenderingBehaviour.LEFT ? IMinecraft.INSTANCE.getDefaultFontRenderer().getHeight() + 1 : 5);
108+
}
109+
110+
public int getDescriptionHeight() {
97111
if (option.getConfig().getDescriptionBehaviour(option) != DescriptionRendereringBehaviour.EXPAND_PANEL)
98112
return HEIGHT;
99113
var fr = IMinecraft.INSTANCE.getDefaultFontRenderer();

common/src/main/java/io/github/notenoughupdates/moulconfig/gui/component/ButtonComponent.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
77
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
88
import io.github.notenoughupdates.moulconfig.gui.MouseEvent.Click
99

10-
class ButtonComponent(
10+
class ButtonComponent @JvmOverloads constructor(
1111
element: GuiComponent,
1212
insets: Int,
13-
val onClick: Runnable
14-
) : PanelComponent(element, insets, DefaultBackgroundRenderer.DARK_RECT) {
13+
val onClick: Runnable,
14+
panel: BackgroundRenderer = DefaultBackgroundRenderer.DARK_RECT
15+
) : PanelComponent(element, insets, panel) {
1516
override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean {
1617
if (context.isHovered && mouseEvent is Click) {
1718
val (mouseButton, mouseState) = mouseEvent
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package io.github.notenoughupdates.moulconfig.gui.component;
2+
3+
import io.github.notenoughupdates.moulconfig.gui.GuiComponent;
4+
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext;
5+
import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent;
6+
import io.github.notenoughupdates.moulconfig.gui.MouseEvent;
7+
import lombok.EqualsAndHashCode;
8+
import lombok.Value;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
import java.util.function.BiFunction;
12+
13+
@Value
14+
@EqualsAndHashCode(callSuper = false)
15+
public class FixedComponent extends GuiComponent {
16+
GuiComponent inner;
17+
int width, height;
18+
19+
@Override
20+
public <T> T foldChildren(T initial, @NotNull BiFunction<@NotNull GuiComponent, T, T> visitor) {
21+
return visitor.apply(inner, initial);
22+
}
23+
24+
@Override
25+
public boolean mouseEvent(@NotNull MouseEvent mouseEvent, @NotNull GuiImmediateContext context) {
26+
return inner.mouseEvent(mouseEvent, context);
27+
}
28+
29+
@Override
30+
public boolean keyboardEvent(@NotNull KeyboardEvent event, @NotNull GuiImmediateContext context) {
31+
return inner.keyboardEvent(event, context);
32+
}
33+
34+
@Override
35+
public void render(@NotNull GuiImmediateContext context) {
36+
inner.render(context);
37+
}
38+
}

common/src/main/java/io/github/notenoughupdates/moulconfig/gui/component/PanelComponent.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ public void render(RenderContext renderContext, int x, int y, int width, int hei
5353
renderContext.drawNinePatch(NinePatches.INSTANCE.createButton(), x, y, width, height);
5454
}
5555
},
56+
BUTTON_WHITE {
57+
@Override
58+
public void render(RenderContext renderContext, int x, int y, int width, int height) {
59+
renderContext.drawNinePatch(NinePatches.INSTANCE.createWhiteButton(), x, y, width, height);
60+
}
61+
},
5662
VANILLA {
5763
@Override
5864
public void render(RenderContext renderContext, int x, int y, int width, int height) {

common/src/main/java/io/github/notenoughupdates/moulconfig/gui/editors/ComponentEditor.java

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import lombok.var;
1515
import org.jetbrains.annotations.NotNull;
1616
import org.jetbrains.annotations.Nullable;
17+
import org.jspecify.annotations.NullMarked;
1718

1819
import java.util.List;
1920

@@ -67,9 +68,17 @@ public GuiImmediateContext getImmContext(
6768
);
6869
}
6970

71+
@NullMarked
7072
public class EditorComponentWrapper extends PanelComponent {
73+
public final @Nullable GuiComponent bottomComponent;
74+
7175
public EditorComponentWrapper(GuiComponent component) {
76+
this(component, null);
77+
}
78+
79+
public EditorComponentWrapper(GuiComponent component, @Nullable GuiComponent bottomComponent) {
7280
super(component);
81+
this.bottomComponent = bottomComponent;
7382
}
7483

7584
@Override
@@ -84,74 +93,124 @@ protected int getDescriptionHeight() {
8493
return Math.max(45, fr.splitText(option.getDescription(), 250 * 2 / 3 - 10).size() * (fr.getHeight() + 1) + 10);
8594
}
8695

87-
@Override
88-
public int getHeight() {
96+
public int getTopHeight() {
8997
int height = getDescriptionHeight();
90-
if (option.getConfig().getTitleRenderingBehaviour(option) == TitleRenderingBehaviour.WIDE_CENTERED)
98+
if (option.getConfig().getTitleRenderingBehaviour(option) != TitleRenderingBehaviour.LEFT)
9199
height += IMinecraft.INSTANCE.getDefaultFontRenderer().getHeight() + 1;
92-
return height;
100+
return Math.max(HEIGHT, height);
101+
}
102+
103+
@Override
104+
public int getHeight() {
105+
return getTopHeight() + (bottomComponent != null ? bottomComponent.getHeight() + 10 : 0);
93106
}
94107

95108
@Override
96109
protected GuiImmediateContext getChildContext(GuiImmediateContext context) {
97-
return context.translated(5, 13, context.getWidth() / 3 - 10, context.getHeight() - 13);
110+
return context.translated(5, 15, context.getWidth() / 3 - 10, context.getHeight() - 15);
98111
}
99112

113+
protected int getEffectiveTopHeight(GuiImmediateContext context) {
114+
return Math.min(context.getHeight(), (getTopHeight()));
115+
}
116+
117+
protected GuiImmediateContext getBottomContext(GuiImmediateContext context) {
118+
int effectiveTopHeight = getEffectiveTopHeight(context);
119+
return context.translated(5, effectiveTopHeight + bottomOffset, context.getWidth() - 10, context.getHeight() - effectiveTopHeight - bottomOffset - 8);
120+
}
121+
122+
protected GuiImmediateContext getTopContext(GuiImmediateContext context) {
123+
return context.translated(0, 0, context.getWidth(), getEffectiveTopHeight(context));
124+
}
125+
126+
int bottomOffset = 0;
127+
100128
@Override
101-
public void render(@NotNull GuiImmediateContext context) {
129+
public void render(GuiImmediateContext context) {
102130
context.getRenderContext().drawDarkRect(0, 0, context.getWidth(), context.getHeight() - 2);
103131

104-
renderTitle(context);
132+
var topContext = getTopContext(context);
133+
renderTitle(topContext);
105134

106-
renderDescription(context);
135+
renderDescription(topContext);
107136

108-
renderElement(context);
137+
renderElement(topContext);
138+
139+
context.getRenderContext().pushMatrix();
140+
context.getRenderContext().translate(5, getEffectiveTopHeight(context) + bottomOffset);
141+
renderBottomElement(getBottomContext(context));
142+
context.getRenderContext().popMatrix();
143+
}
144+
145+
protected void renderBottomElement(GuiImmediateContext context) {
146+
if (bottomComponent != null)
147+
bottomComponent.render(context);
109148
}
110149

111-
protected void renderElement(@NotNull GuiImmediateContext context) {
150+
protected void renderElement(GuiImmediateContext context) {
112151
context.getRenderContext().pushMatrix();
113-
context.getRenderContext().translate(5, 13);
152+
context.getRenderContext().translate(5, 15);
114153
this.getElement().render(getChildContext(context));
115154
context.getRenderContext().popMatrix();
116155
}
117156

118-
protected void renderTitle(@NotNull GuiImmediateContext context) {
157+
protected void renderTitle(GuiImmediateContext context) {
119158
int width = context.getWidth();
120159
var minecraft = context.getRenderContext().getMinecraft();
121160
var fr = minecraft.getDefaultFontRenderer();
122161
switch (option.getConfig().getTitleRenderingBehaviour(option)) {
162+
case WIDE_CENTERED_UNDERLINED:
163+
context.getRenderContext().drawHorizontalLine(16, 10, width - 10, 0xFF404040);
164+
// fallthrough;
123165
case WIDE_CENTERED:
124166
context.getRenderContext().drawStringCenteredScaledMaxWidth(
125-
option.getName(), fr, width / 2, 13, true, width - 10, 0xe0e0e0
167+
option.getName(), fr, width / 2, 10, true, width - 10, 0xe0e0e0
126168
);
127169
break;
128170
case LEFT:
129171
context.getRenderContext().drawStringCenteredScaledMaxWidth(
130-
option.getName(), fr, width / 6, 13, true, width / 3 - 10, 0xe0e0e0
172+
option.getName(), fr, width / 6, 10, true, width / 3 - 10, 0xe0e0e0
131173
);
132174
break;
133175
}
134176
}
135177

178+
@Override
179+
public boolean mouseEvent(MouseEvent mouseEvent, GuiImmediateContext context) {
180+
if (super.mouseEvent(mouseEvent, getTopContext(context)))
181+
return true;
182+
if (bottomComponent != null && bottomComponent.mouseEvent(mouseEvent, getBottomContext(context)))
183+
return true;
184+
return false;
185+
}
186+
187+
@Override
188+
public boolean keyboardEvent(KeyboardEvent event, GuiImmediateContext context) {
189+
if (super.keyboardEvent(event, getTopContext(context)))
190+
return true;
191+
if (bottomComponent != null && bottomComponent.keyboardEvent(event, getBottomContext(context)))
192+
return true;
193+
return false;
194+
}
195+
136196
protected void renderDescription(@NotNull GuiImmediateContext context) {
137197
int width = context.getWidth();
138198
var minecraft = context.getRenderContext().getMinecraft();
139199
var fr = minecraft.getDefaultFontRenderer();
140-
int yOffset = option.getConfig().getTitleRenderingBehaviour(option) == TitleRenderingBehaviour.WIDE_CENTERED ? fr.getHeight() + 1 : 5;
200+
int yOffset = option.getConfig().getTitleRenderingBehaviour(option) != TitleRenderingBehaviour.LEFT ? fr.getHeight() + 13 : 5;
141201
float scale = 1;
142202
List<StructuredText> lines;
143-
int descriptionHeight = (option.getConfig().getDescriptionBehaviour(option) != DescriptionRendereringBehaviour.EXPAND_PANEL ? HEIGHT : context.getHeight()) - yOffset;
203+
int descriptionHeight = context.getHeight() - yOffset;
144204
while (true) {
145205
lines = fr.splitText(option.getDescription(), (int) (width * 2 / 3 / scale - 10));
146-
if (lines.size() * scale * (fr.getHeight() + 1) + 10 < descriptionHeight)
206+
if (lines.size() * scale * (fr.getHeight() + 1) < descriptionHeight)
147207
break;
148208
scale -= 1 / 8f;
149209
if (scale < 1 / 16f) break;
150210
}
151211
context.getRenderContext().pushMatrix();
152212
context.getRenderContext().translate(5 + width / 3, yOffset);
153213
context.getRenderContext().scale(scale, scale);
154-
context.getRenderContext().translate(0, ((descriptionHeight - 10) - (fr.getHeight() + 1) * (lines.size() - 1) * scale) / 2F);
155214
for (var line : lines) {
156215
context.getRenderContext().drawString(fr, line, 0, 0, 0xc0c0c0, false);
157216
context.getRenderContext().translate(0, fr.getHeight() + 1);
@@ -160,6 +219,13 @@ protected void renderDescription(@NotNull GuiImmediateContext context) {
160219
}
161220
}
162221

222+
protected GuiComponent wrapComponent(GuiComponent component, @Nullable GuiComponent bottomComponent) {
223+
return new EditorComponentWrapper(
224+
new CenterComponent(component),
225+
bottomComponent
226+
);
227+
}
228+
163229
protected GuiComponent wrapComponent(GuiComponent component) {
164230
return new EditorComponentWrapper(
165231
new CenterComponent(component)

0 commit comments

Comments
 (0)