Skip to content

Commit 8d67eee

Browse files
committed
Add TextFieldWidget::setFormatAsInteger
1 parent 61c62a2 commit 8d67eee

File tree

3 files changed

+101
-7
lines changed

3 files changed

+101
-7
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
@@ -53,6 +53,7 @@ public class TestTile extends TileEntity implements IGuiHolder<PosGuiData>, ITic
5353
private long time = 0;
5454
private int val, val2 = 0;
5555
private String value = "";
56+
private int intValue = 1234567;
5657
private double doubleValue = 1;
5758
private final int duration = 80;
5859
private int progress = 0;
@@ -221,8 +222,17 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager,
221222
.child(new FluidSlot()
222223
.margin(2)
223224
.width(30)
224-
.syncHandler(SyncHandlers.fluidSlot(this.fluidTankPhantom).phantom(true)))
225-
)))
225+
.syncHandler(SyncHandlers.fluidSlot(this.fluidTankPhantom).phantom(true))))
226+
.child(new Column()
227+
.debugName("button and slots test 3")
228+
.coverChildren()
229+
.alignY(Alignment.START)
230+
.child(new TextFieldWidget()
231+
.size(60, 20)
232+
.value(SyncHandlers.intNumber(() -> this.intValue, val -> this.intValue = val))
233+
.setNumbers(0, 9999999)
234+
.setFormatAsInteger(true)
235+
.hintText("integer")))))
226236
.addPage(new Column()
227237
.debugName("Slots test page")
228238
.coverChildren()

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

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,30 @@
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;
18+
import java.text.DecimalFormat;
1519
import java.util.Collections;
1620
import java.util.List;
21+
import java.util.stream.Collectors;
1722

1823
public class TextFieldRenderer extends TextRenderer {
24+
private static final DecimalFormat INTEGER_FIELD_FORMAT = new DecimalFormat("#");
25+
private static final char groupingSeparator = INTEGER_FIELD_FORMAT.getDecimalFormatSymbols().getGroupingSeparator();
26+
27+
static {
28+
INTEGER_FIELD_FORMAT.setGroupingUsed(true);
29+
INTEGER_FIELD_FORMAT.setGroupingSize(3);
30+
}
1931

2032
protected final TextFieldHandler handler;
2133
protected int markedColor = 0x2F72A8;
2234
protected int cursorColor = 0xFFFFFFFF;
2335
protected boolean renderCursor = false;
36+
private boolean formatAsInteger = false;
2437

2538
public TextFieldRenderer(TextFieldHandler handler) {
2639
this.handler = handler;
@@ -42,6 +55,30 @@ public void setCursorColor(int cursorColor) {
4255
this.cursorColor = cursorColor;
4356
}
4457

58+
@ApiStatus.Experimental
59+
public void setFormatAsInteger(boolean formatAsInteger) {
60+
this.formatAsInteger = formatAsInteger;
61+
}
62+
63+
@Override
64+
public void draw(List<String> lines) {
65+
if (formatAsInteger) lines = decorateLines(lines);
66+
super.draw(lines);
67+
}
68+
69+
private static @NotNull List<String> decorateLines(List<String> lines) {
70+
return lines.stream().map(TextFieldRenderer::tryFormatString)
71+
.collect(Collectors.toList());
72+
}
73+
74+
private static @NotNull String tryFormatString(String str) {
75+
try {
76+
return INTEGER_FIELD_FORMAT.format(Long.parseLong(str));
77+
} catch (NumberFormatException e) {
78+
return str;
79+
}
80+
}
81+
4582
@Override
4683
protected void drawMeasuredLines(List<Line> measuredLines) {
4784
drawMarked(measuredLines);
@@ -96,39 +133,79 @@ public Point getCursorPos(List<String> lines, int x, int y) {
96133
if (lines.isEmpty()) {
97134
return new Point();
98135
}
136+
if (formatAsInteger) lines = decorateLines(lines);
99137
List<Line> measuredLines = measureLines(lines);
100138
y -= getStartY(measuredLines.size());
101139
int index = (int) (y / (getFontHeight()));
102140
if (index < 0) return new Point();
103-
if (index >= measuredLines.size())
104-
return new Point(measuredLines.get(measuredLines.size() - 1).getText().length(), measuredLines.size() - 1);
141+
if (index >= measuredLines.size()) {
142+
return new Point(getRealLength(measuredLines.get(measuredLines.size() - 1).getText()), measuredLines.size() - 1);
143+
}
105144
Line line = measuredLines.get(index);
106145
x -= getStartX(line.getWidth());
107146
if (line.getWidth() <= 0) return new Point(0, index);
108-
if (line.getWidth() < x) return new Point(line.getText().length(), index);
147+
if (line.getWidth() < x) {
148+
return new Point(getRealLength(line.getText()), index);
149+
}
109150
float currentX = 0;
151+
int ignoredChars = 0;
110152
for (int i = 0; i < line.getText().length(); i++) {
111153
char c = line.getText().charAt(i);
112154
float charWidth = getFontRenderer().getCharWidth(c) * this.scale;
113155
currentX += charWidth;
156+
if (isIgnoredChar(c)) ignoredChars++;
114157
if (currentX >= x) {
115158
// dist with current letter < dist without current letter -> next letter pos
116159
if (Math.abs(currentX - x) < Math.abs(currentX - charWidth - x)) i++;
117-
return new Point(i, index);
160+
return new Point(i - ignoredChars, index);
118161
}
119162
}
120163
return new Point();
121164
}
122165

166+
/**
167+
* Whether the given character should be ignored for cursor positioning purposes
168+
*/
169+
@ApiStatus.Experimental
170+
protected boolean isIgnoredChar(int c) {
171+
return formatAsInteger && c == groupingSeparator;
172+
}
173+
174+
private int getRealLength(String text) {
175+
int length = text.length();
176+
if (formatAsInteger) length -= (int) text.chars().filter(this::isIgnoredChar).count();
177+
return length;
178+
}
179+
123180
public Point2D.Float getPosOf(List<Line> measuredLines, Point cursorPos) {
124181
if (measuredLines.isEmpty()) {
125182
return new Point2D.Float(getStartX(0), getStartYOfLines(1));
126183
}
127184
Line line = measuredLines.get(cursorPos.y);
128-
String sub = line.getText().substring(0, Math.min(line.getText().length(), cursorPos.x));
185+
String sub = getStringBeforeCursor(line, cursorPos);
129186
return new Point2D.Float(getStartX(line.getWidth()) + getFontRenderer().getStringWidth(sub) * this.scale, getStartYOfLines(measuredLines.size()) + cursorPos.y * getFontHeight());
130187
}
131188

189+
private @NotNull String getStringBeforeCursor(Line line, Point cursorPos) {
190+
String text = line.getText();
191+
String sub = text.substring(0, Math.min(text.length(), cursorPos.x));
192+
if (formatAsInteger) {
193+
int i = 0;
194+
int ignoredChars = 0;
195+
while (i < sub.length() && i + ignoredChars < text.length()) {
196+
if (isIgnoredChar(text.charAt(i + ignoredChars))) {
197+
ignoredChars++;
198+
} else {
199+
i++;
200+
}
201+
}
202+
if (ignoredChars > 0) {
203+
sub = sub + text.substring(sub.length(), Math.min(text.length(), cursorPos.x + ignoredChars));
204+
}
205+
}
206+
return sub;
207+
}
208+
132209
@SideOnly(Side.CLIENT)
133210
public void drawMarked(float y0, float x0, float x1) {
134211
y0 -= 1;

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.cleanroommc.modularui.value.sync.SyncHandler;
1414
import com.cleanroommc.modularui.value.sync.ValueSyncHandler;
1515

16+
import org.jetbrains.annotations.ApiStatus;
1617
import org.jetbrains.annotations.NotNull;
1718

1819
import java.awt.*;
@@ -232,6 +233,12 @@ public TextFieldWidget setDefaultNumber(double defaultNumber) {
232233
return this;
233234
}
234235

236+
@ApiStatus.Experimental
237+
public TextFieldWidget setFormatAsInteger(boolean formatAsInteger) {
238+
this.renderer.setFormatAsInteger(formatAsInteger);
239+
return getThis();
240+
}
241+
235242
public TextFieldWidget value(IStringValue<?> stringValue) {
236243
this.stringValue = stringValue;
237244
setValue(stringValue);

0 commit comments

Comments
 (0)