Skip to content

Commit 236c68f

Browse files
committed
Add experimental IntegerFieldWidget
1 parent 61c62a2 commit 236c68f

File tree

5 files changed

+109
-5
lines changed

5 files changed

+109
-5
lines changed

src/main/java/com/cleanroommc/modularui/test/TestTile.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.cleanroommc.modularui.widgets.layout.Flow;
2929
import com.cleanroommc.modularui.widgets.layout.Row;
3030
import com.cleanroommc.modularui.widgets.slot.*;
31+
import com.cleanroommc.modularui.widgets.textfield.IntegerFieldWidget;
3132
import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget;
3233

3334
import net.minecraft.init.Blocks;
@@ -53,6 +54,7 @@ public class TestTile extends TileEntity implements IGuiHolder<PosGuiData>, ITic
5354
private long time = 0;
5455
private int val, val2 = 0;
5556
private String value = "";
57+
private int intValue = 1234567;
5658
private double doubleValue = 1;
5759
private final int duration = 80;
5860
private int progress = 0;
@@ -221,8 +223,16 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager,
221223
.child(new FluidSlot()
222224
.margin(2)
223225
.width(30)
224-
.syncHandler(SyncHandlers.fluidSlot(this.fluidTankPhantom).phantom(true)))
225-
)))
226+
.syncHandler(SyncHandlers.fluidSlot(this.fluidTankPhantom).phantom(true))))
227+
.child(new Column()
228+
.debugName("button and slots test 3")
229+
.coverChildren()
230+
.alignY(Alignment.START)
231+
.child(new IntegerFieldWidget()
232+
.size(60, 20)
233+
.value(SyncHandlers.intNumber(() -> this.intValue, val -> this.intValue = val))
234+
.setNumbers(0, 9999999)
235+
.hintText("integer")))))
226236
.addPage(new Column()
227237
.debugName("Slots test page")
228238
.coverChildren()

src/main/java/com/cleanroommc/modularui/widgets/textfield/BaseTextFieldWidget.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import net.minecraft.client.gui.GuiScreen;
1818

19+
import org.jetbrains.annotations.ApiStatus;
1920
import org.jetbrains.annotations.NotNull;
2021
import org.lwjgl.input.Keyboard;
2122

@@ -44,7 +45,7 @@ public class BaseTextFieldWidget<W extends BaseTextFieldWidget<W>> extends Abstr
4445
private static final int CURSOR_BLINK_RATE = 10;
4546

4647
protected TextFieldHandler handler = new TextFieldHandler(this);
47-
protected TextFieldRenderer renderer = new TextFieldRenderer(this.handler);
48+
protected final TextFieldRenderer renderer;
4849
protected Alignment textAlignment = Alignment.CenterLeft;
4950
protected List<String> lastText;
5051
protected int scrollOffset = 0;
@@ -59,11 +60,17 @@ public class BaseTextFieldWidget<W extends BaseTextFieldWidget<W>> extends Abstr
5960

6061
public BaseTextFieldWidget() {
6162
super(new HorizontalScrollData(), null);
63+
this.renderer = initializeTextFieldRenderer();
6264
this.handler.setRenderer(this.renderer);
6365
this.handler.setScrollArea(getScrollArea());
6466
padding(4, 0);
6567
}
6668

69+
@ApiStatus.Experimental
70+
protected TextFieldRenderer initializeTextFieldRenderer() {
71+
return new TextFieldRenderer(this.handler);
72+
}
73+
6774
@Override
6875
public @NotNull List<IWidget> getChildren() {
6976
return Collections.emptyList();
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.cleanroommc.modularui.widgets.textfield;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
import java.text.DecimalFormat;
6+
import java.util.List;
7+
import java.util.stream.Collectors;
8+
9+
class IntegerFieldRenderer extends TextFieldRenderer {
10+
private static final DecimalFormat INTEGER_FIELD_FORMAT = new DecimalFormat("#");
11+
12+
static {
13+
INTEGER_FIELD_FORMAT.setGroupingUsed(true);
14+
INTEGER_FIELD_FORMAT.setGroupingSize(3);
15+
}
16+
17+
public IntegerFieldRenderer(TextFieldHandler handler) {
18+
super(handler);
19+
}
20+
21+
@Override
22+
public void draw(List<String> lines) {
23+
super.draw(lines.stream().map(IntegerFieldRenderer::tryFormatString)
24+
.collect(Collectors.toList()));
25+
}
26+
27+
private static @NotNull String tryFormatString(String str) {
28+
try {
29+
return INTEGER_FIELD_FORMAT.format(Long.parseLong(str));
30+
} catch (NumberFormatException e) {
31+
return str;
32+
}
33+
}
34+
35+
@Override
36+
protected boolean isIgnoredChar(char c) {
37+
return c == INTEGER_FIELD_FORMAT.getDecimalFormatSymbols().getGroupingSeparator();
38+
}
39+
40+
41+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.cleanroommc.modularui.widgets.textfield;
2+
3+
import org.jetbrains.annotations.ApiStatus;
4+
5+
/**
6+
* This widget formats integers with group separators.
7+
*/
8+
@ApiStatus.Experimental
9+
public class IntegerFieldWidget extends TextFieldWidget {
10+
11+
@Override
12+
protected TextFieldRenderer initializeTextFieldRenderer() {
13+
return new IntegerFieldRenderer(this.handler);
14+
}
15+
}

src/main/java/com/cleanroommc/modularui/widgets/textfield/TextFieldRenderer.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
import net.minecraftforge.fml.relauncher.Side;
1111
import net.minecraftforge.fml.relauncher.SideOnly;
1212

13+
import org.jetbrains.annotations.ApiStatus;
14+
import org.jetbrains.annotations.NotNull;
15+
1316
import java.awt.*;
1417
import java.awt.geom.Point2D;
1518
import java.util.Collections;
@@ -107,28 +110,56 @@ public Point getCursorPos(List<String> lines, int x, int y) {
107110
if (line.getWidth() <= 0) return new Point(0, index);
108111
if (line.getWidth() < x) return new Point(line.getText().length(), index);
109112
float currentX = 0;
113+
int ignoredChars = 0;
110114
for (int i = 0; i < line.getText().length(); i++) {
111115
char c = line.getText().charAt(i);
112116
float charWidth = getFontRenderer().getCharWidth(c) * this.scale;
113117
currentX += charWidth;
118+
if (isIgnoredChar(c)) ignoredChars++;
114119
if (currentX >= x) {
115120
// dist with current letter < dist without current letter -> next letter pos
116121
if (Math.abs(currentX - x) < Math.abs(currentX - charWidth - x)) i++;
117-
return new Point(i, index);
122+
return new Point(i - ignoredChars, index);
118123
}
119124
}
120125
return new Point();
121126
}
122127

128+
/**
129+
* Whether the given character should be ignored for cursor positioning purposes
130+
*/
131+
@ApiStatus.Experimental
132+
protected boolean isIgnoredChar(char c) {
133+
return false;
134+
}
135+
123136
public Point2D.Float getPosOf(List<Line> measuredLines, Point cursorPos) {
124137
if (measuredLines.isEmpty()) {
125138
return new Point2D.Float(getStartX(0), getStartYOfLines(1));
126139
}
127140
Line line = measuredLines.get(cursorPos.y);
128-
String sub = line.getText().substring(0, Math.min(line.getText().length(), cursorPos.x));
141+
String sub = getStringBeforeCursor(line, cursorPos);
129142
return new Point2D.Float(getStartX(line.getWidth()) + getFontRenderer().getStringWidth(sub) * this.scale, getStartYOfLines(measuredLines.size()) + cursorPos.y * getFontHeight());
130143
}
131144

145+
private @NotNull String getStringBeforeCursor(Line line, Point cursorPos) {
146+
String text = line.getText();
147+
String sub = text.substring(0, Math.min(text.length(), cursorPos.x));
148+
int i = 0;
149+
int ignoredChars = 0;
150+
while (i < sub.length() && i + ignoredChars < text.length()) {
151+
if (isIgnoredChar(text.charAt(i + ignoredChars))) {
152+
ignoredChars++;
153+
} else {
154+
i++;
155+
}
156+
}
157+
if (ignoredChars > 0) {
158+
sub = sub + text.substring(sub.length(), Math.min(text.length(), cursorPos.x + ignoredChars));
159+
}
160+
return sub;
161+
}
162+
132163
@SideOnly(Side.CLIENT)
133164
public void drawMarked(float y0, float x0, float x1) {
134165
y0 -= 1;

0 commit comments

Comments
 (0)