aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com>2022-05-20 20:54:33 +0200
committerDeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com>2022-05-20 20:54:33 +0200
commit13965c418bb9429d2ff92fbcbb29fad73e8a120f (patch)
treeab744b0afa6f43de0a7a04da3bda870099fee589 /src
parent85a8ae69736f93a1a972b696fd9d2fba5d435884 (diff)
downloadOneConfig-13965c418bb9429d2ff92fbcbb29fad73e8a120f.tar.gz
OneConfig-13965c418bb9429d2ff92fbcbb29fad73e8a120f.tar.bz2
OneConfig-13965c418bb9429d2ff92fbcbb29fad73e8a120f.zip
some small stuff and start on multi line textbox
Diffstat (limited to 'src')
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java2
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigDropdown.java38
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigTextBox.java19
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/gui/elements/text/TextInputField.java116
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/lwjgl/RenderManager.java36
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/utils/TextUtils.java32
6 files changed, 161 insertions, 82 deletions
diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java b/src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java
index 22b5455..66bc2cd 100644
--- a/src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java
+++ b/src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java
@@ -28,7 +28,7 @@ public class OneConfigGui extends UScreen {
protected Page currentPage;
protected Page prevPage;
private float pageProgress = -224f;
- private final TextInputField textInputField = new TextInputField(248, 40, "Search...", false, false);
+ private final TextInputField textInputField = new TextInputField(248, 40, "Search...", false, false, SVGs.SEARCH);
private final ArrayList<Page> previousPages = new ArrayList<>();
private final ArrayList<Page> nextPages = new ArrayList<>();
private final BasicElement backArrow = new BasicElement(40, 40, -1, false);
diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigDropdown.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigDropdown.java
index c01228d..f6041c9 100644
--- a/src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigDropdown.java
+++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigDropdown.java
@@ -35,8 +35,8 @@ public class ConfigDropdown extends BasicOption { // TODO: remove dividers and f
else hovered = InputUtils.isAreaHovered(x + 352, y, 640, 32) && isEnabled();
if (hovered && InputUtils.isClicked() || opened && InputUtils.isClicked(true) &&
- (size == 1 && !InputUtils.isAreaHovered(x + 224, y + 40, 256, options.length * 36) ||
- size == 2 && !InputUtils.isAreaHovered(x + 352, y + 40, 640, options.length * 36))) {
+ (size == 1 && !InputUtils.isAreaHovered(x + 224, y + 40, 256, options.length * 32) ||
+ size == 2 && !InputUtils.isAreaHovered(x + 352, y + 40, 640, options.length * 32))) {
opened = !opened;
InputUtils.blockClicks(opened);
}
@@ -88,16 +88,16 @@ public class ConfigDropdown extends BasicOption { // TODO: remove dividers and f
RenderManager.drawSvg(vg, SVGs.DROPDOWN_LIST, x + 452, y + 4, 24, 24);
NanoVG.nvgGlobalAlpha(vg, 1f);
- RenderManager.drawRoundedRect(vg, x + 224, y + 48, 256, options.length * 36, OneConfigConfig.GRAY_700, 12);
- RenderManager.drawHollowRoundRect(vg, x + 223, y + 47, 258, options.length * 36 + 2, new Color(204, 204, 204, 77).getRGB(), 11, 1);
- int optionY = y + 48;
+ RenderManager.drawRoundedRect(vg, x + 224, y + 48, 256, options.length * 32 + 8, OneConfigConfig.GRAY_700, 12);
+ RenderManager.drawHollowRoundRect(vg, x + 223, y + 47, 258, options.length * 32 + 10, new Color(204, 204, 204, 77).getRGB(), 12, 1);
+ int optionY = y + 52;
for (String option : options) {
int color = OneConfigConfig.WHITE_80;
- boolean optionHovered = InputUtils.isAreaHovered(x + 224, optionY, 252, 36);
+ boolean optionHovered = InputUtils.isAreaHovered(x + 224, optionY, 252, 32);
if (optionHovered && Mouse.isButtonDown(0)) {
- RenderManager.drawRoundedRect(vg, x + 228, optionY + 4, 248, 28, OneConfigConfig.BLUE_700_80, 8);
+ RenderManager.drawRoundedRect(vg, x + 228, optionY + 2, 248, 28, OneConfigConfig.BLUE_700_80, 8);
} else if (optionHovered) {
- RenderManager.drawRoundedRect(vg, x + 228, optionY + 4, 248, 28, OneConfigConfig.BLUE_700, 8);
+ RenderManager.drawRoundedRect(vg, x + 228, optionY + 2, 248, 28, OneConfigConfig.BLUE_700, 8);
color = OneConfigConfig.WHITE;
}
if (optionHovered && InputUtils.isClicked(true)) {
@@ -109,10 +109,8 @@ public class ConfigDropdown extends BasicOption { // TODO: remove dividers and f
InputUtils.blockClicks(false);
}
- RenderManager.drawString(vg, option, x + 240, optionY + 20, color, 14, Fonts.MEDIUM);
- if (!options[options.length - 1].equals(option))
- RenderManager.drawLine(vg, x + 232, optionY + 36, x + 472, optionY + 36, 1, new Color(204, 204, 204, 77).getRGB());
- optionY += 36;
+ RenderManager.drawString(vg, option, x + 240, optionY + 18, color, 14, Fonts.MEDIUM);
+ optionY += 32;
}
} else {
RenderManager.drawRoundedRect(vg, x + 352, y, 640, 32, backgroundColor, 12);
@@ -122,22 +120,20 @@ public class ConfigDropdown extends BasicOption { // TODO: remove dividers and f
RenderManager.drawSvg(vg, SVGs.DROPDOWN_LIST, x + 964, y + 4, 24, 24);
NanoVG.nvgGlobalAlpha(vg, 1f);
- RenderManager.drawRoundedRect(vg, x + 352, y + 48, 640, options.length * 36, OneConfigConfig.GRAY_700, 12);
- RenderManager.drawHollowRoundRect(vg, x + 351, y + 47, 642, options.length * 36 + 2, new Color(204, 204, 204, 77).getRGB(), 10, 1);
- int optionY = y + 48;
+ RenderManager.drawRoundedRect(vg, x + 352, y + 48, 640, options.length * 32 + 8, OneConfigConfig.GRAY_700, 12);
+ RenderManager.drawHollowRoundRect(vg, x + 351, y + 47, 642, options.length * 32 + 10, new Color(204, 204, 204, 77).getRGB(), 12, 1);
+ int optionY = y + 52;
for (String option : options) {
int color = OneConfigConfig.WHITE_80;
boolean optionHovered = InputUtils.isAreaHovered(x + 352, optionY, 640, 36);
if (optionHovered && Mouse.isButtonDown(0)) {
- RenderManager.drawRoundedRect(vg, x + 356, optionY + 4, 632, 28, OneConfigConfig.BLUE_700_80, 8);
+ RenderManager.drawRoundedRect(vg, x + 356, optionY + 2, 632, 28, OneConfigConfig.BLUE_700_80, 8);
} else if (optionHovered) {
- RenderManager.drawRoundedRect(vg, x + 356, optionY + 4, 632, 28, OneConfigConfig.BLUE_700, 8);
+ RenderManager.drawRoundedRect(vg, x + 356, optionY + 2, 632, 28, OneConfigConfig.BLUE_700, 8);
color = OneConfigConfig.WHITE;
}
- RenderManager.drawString(vg, option, x + 368, optionY + 20, color, 14, Fonts.MEDIUM);
- if (!options[options.length - 1].equals(option))
- RenderManager.drawLine(vg, x + 360, optionY + 36, x + 984, optionY + 36, 1, new Color(204, 204, 204, 77).getRGB());
+ RenderManager.drawString(vg, option, x + 368, optionY + 18, color, 14, Fonts.MEDIUM);
if (optionHovered && InputUtils.isClicked(true)) {
try {
@@ -147,7 +143,7 @@ public class ConfigDropdown extends BasicOption { // TODO: remove dividers and f
opened = false;
InputUtils.blockClicks(false);
}
- optionY += 36;
+ optionY += 32;
}
}
NanoVG.nvgGlobalAlpha(vg, 1f);
diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigTextBox.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigTextBox.java
index d420f01..dbe0482 100644
--- a/src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigTextBox.java
+++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigTextBox.java
@@ -2,12 +2,12 @@ package cc.polyfrost.oneconfig.gui.elements.config;
import cc.polyfrost.oneconfig.config.OneConfigConfig;
import cc.polyfrost.oneconfig.config.interfaces.BasicOption;
+import cc.polyfrost.oneconfig.gui.elements.text.TextInputField;
import cc.polyfrost.oneconfig.lwjgl.RenderManager;
import cc.polyfrost.oneconfig.lwjgl.font.Fonts;
-import cc.polyfrost.oneconfig.lwjgl.image.Images;
import cc.polyfrost.oneconfig.lwjgl.image.SVGs;
import cc.polyfrost.oneconfig.utils.InputUtils;
-import cc.polyfrost.oneconfig.gui.elements.text.TextInputField;
+import org.lwjgl.input.Mouse;
import org.lwjgl.nanovg.NanoVG;
import java.awt.*;
@@ -37,11 +37,18 @@ public class ConfigTextBox extends BasicOption {
} catch (IllegalAccessException ignored) {
}
+ if (multiLine && textField.getLines() > 2) textField.setHeight(64 + 24 * (textField.getLines() - 2));
+ else if (multiLine) textField.setHeight(64);
textField.draw(vg, x + (size == 1 && hasHalfSize() ? 224 : 352), y);
- if (secure)
- RenderManager.drawSvg(vg, SVGs.EYE, x + 967, y + 7, 18, 18, new Color(196, 196, 196).getRGB());
- if (secure && InputUtils.isAreaClicked(x + 967, y + 7, 18, 18)) textField.setPassword(!textField.getPassword());
+ if (secure) {
+ SVGs icon = textField.getPassword() ? SVGs.EYE_OFF : SVGs.EYE;
+ boolean hovered = InputUtils.isAreaHovered(x + 967, y + 7, 18, 18) && isEnabled();
+ int color = hovered ? OneConfigConfig.WHITE : OneConfigConfig.WHITE_80;
+ if (hovered && InputUtils.isClicked()) textField.setPassword(!textField.getPassword());
+ if (hovered && Mouse.isButtonDown(0)) NanoVG.nvgGlobalAlpha(vg, 0.5f);
+ RenderManager.drawSvg(vg, icon, x + 967, y + 7, 18, 18, color);
+ }
NanoVG.nvgGlobalAlpha(vg, 1f);
}
@@ -57,7 +64,7 @@ public class ConfigTextBox extends BasicOption {
@Override
public int getHeight() {
- return multiLine ? 64 : 32;
+ return multiLine ? textField.getHeight() : 32;
}
@Override
diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/text/TextInputField.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/text/TextInputField.java
index 9d87717..a91d19d 100644
--- a/src/main/java/cc/polyfrost/oneconfig/gui/elements/text/TextInputField.java
+++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/text/TextInputField.java
@@ -4,10 +4,13 @@ import cc.polyfrost.oneconfig.config.OneConfigConfig;
import cc.polyfrost.oneconfig.gui.elements.BasicElement;
import cc.polyfrost.oneconfig.lwjgl.RenderManager;
import cc.polyfrost.oneconfig.lwjgl.font.Fonts;
+import cc.polyfrost.oneconfig.lwjgl.image.SVGs;
import cc.polyfrost.oneconfig.lwjgl.scissor.Scissor;
import cc.polyfrost.oneconfig.lwjgl.scissor.ScissorManager;
import cc.polyfrost.oneconfig.utils.InputUtils;
+import cc.polyfrost.oneconfig.utils.TextUtils;
import gg.essential.universal.UKeyboard;
+import kotlin.Pair;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
@@ -15,6 +18,8 @@ import org.lwjgl.input.Mouse;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
+import java.util.ArrayList;
+import java.util.Map;
public class TextInputField extends BasicElement {
@@ -33,17 +38,25 @@ public class TextInputField extends BasicElement {
protected boolean onlyNums = false;
protected boolean errored = false;
protected boolean centered = false;
+ private int lines = 1;
+ protected SVGs icon;
+ protected ArrayList<String> wrappedText = null;
- public TextInputField(int width, int height, String defaultText, boolean multiLine, boolean password) {
+ public TextInputField(int width, int height, String defaultText, boolean multiLine, boolean password, SVGs icon) {
super(width, height, false);
this.multiLine = multiLine;
this.defaultText = defaultText;
this.password = password;
this.input = "";
+ this.icon = icon;
+ }
+
+ public TextInputField(int width, int height, String defaultText, boolean multiLine, boolean password) {
+ this(width, height, defaultText, multiLine, password, null);
}
public TextInputField(int width, int height, boolean centered, String defaultText) {
- this(width, height, defaultText, false, false);
+ this(width, height, defaultText, false, false, null);
this.centered = centered;
}
@@ -99,9 +112,20 @@ public class TextInputField extends BasicElement {
if (prevCaret > input.length()) prevCaret = input.length();
if (caretPos < 0) caretPos = 0;
if (prevCaret < 0) prevCaret = 0;
+ if (icon != null) {
+ RenderManager.drawSvg(vg, icon, x + 12, y + height / 2f - 12f, 24, 24, color);
+ x += 32;
+ this.x = x;
+ }
float width;
StringBuilder s = new StringBuilder();
- if (!password) {
+ if (multiLine) {
+ wrappedText = TextUtils.wrapText(vg, input, this.width - 24, 14f, Fonts.REGULAR);
+ lines = wrappedText.size();
+ if (!toggled) caretPos = wrappedText.get(wrappedText.size() - 1).length();
+ int caretLine = getCaretLine(caretPos);
+ width = RenderManager.getTextWidth(vg, wrappedText.get(caretLine).substring(0, getLineCaret(caretPos, caretLine)), 14f, Fonts.REGULAR);
+ } else if (!password) {
width = RenderManager.getTextWidth(vg, input.substring(0, caretPos), 14f, Fonts.REGULAR);
} else {
for (int i = 0; i < input.length(); i++) {
@@ -113,7 +137,10 @@ public class TextInputField extends BasicElement {
while (Mouse.next()) {
if (Mouse.getEventButtonState()) {
if (Mouse.getEventButton() == 0) {
- prevCaret = calculatePos(InputUtils.mouseX());
+ if (multiLine) {
+ int caretLine = Math.max(0, Math.min(wrappedText.size() - 1, (int) Math.floor((InputUtils.mouseY() - y - 10) / 24f)));
+ caretPos = calculatePos(InputUtils.mouseX(), wrappedText.get(caretLine));
+ } else prevCaret = calculatePos(InputUtils.mouseX(), input);
if (System.currentTimeMillis() - clickTimeD1 < 300) {
onDoubleClick();
isDoubleClick = true;
@@ -142,7 +169,10 @@ public class TextInputField extends BasicElement {
}
if (hovered) {
if (Mouse.isButtonDown(0) && !isDoubleClick) {
- caretPos = calculatePos(InputUtils.mouseX());
+ if (multiLine) {
+ int caretLine = Math.max(0, Math.min(wrappedText.size() - 1, (int) Math.floor((InputUtils.mouseY() - y - 10) / 24f)));
+ caretPos = calculatePos(InputUtils.mouseX(), wrappedText.get(caretLine));
+ } else caretPos = calculatePos(InputUtils.mouseX(), input);
if (caretPos > prevCaret) {
if (!centered) start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret));
else
@@ -161,7 +191,10 @@ public class TextInputField extends BasicElement {
if (toggled) {
- if (!centered) {
+ if (multiLine) {
+ int lineY = y + 20 + getCaretLine(caretPos) * 24;
+ RenderManager.drawLine(vg, x + width + 12, lineY - 10, x + width + 12, lineY + 10, 1, OneConfigConfig.WHITE);
+ } else if (!centered) {
RenderManager.drawLine(vg, x + width + 12, (float) y + height / 2f - 10, x + width + 12, (float) y + height / 2f + 10, 1, OneConfigConfig.WHITE);
} else {
RenderManager.drawLine(vg, x + this.width / 2f - halfTextWidth + width, (float) y + height / 2f - 10, x + this.width / 2f - halfTextWidth + width, (float) y + height / 2f + 10, 1, OneConfigConfig.WHITE);
@@ -170,7 +203,9 @@ public class TextInputField extends BasicElement {
if (input.equals("")) {
- if (!centered) {
+ if (multiLine) {
+ RenderManager.drawString(vg, defaultText, x + 12, y + 16, color, 14f, Fonts.REGULAR);
+ } else if (!centered) {
RenderManager.drawString(vg, defaultText, x + 12, y + height / 2f + 1, color, 14f, Fonts.REGULAR);
} else {
RenderManager.drawString(vg, defaultText, x + this.width / 2f - halfTextWidth, y + height / 2f + 1, color, 14f, Fonts.REGULAR);
@@ -178,7 +213,13 @@ public class TextInputField extends BasicElement {
}
if (!password) {
- if (!centered) {
+ if (multiLine) {
+ int textY = y + 20;
+ for (String line : wrappedText) {
+ RenderManager.drawString(vg, line, x + 12, textY, color, 14f, Fonts.REGULAR);
+ textY += 24;
+ }
+ } else if (!centered) {
RenderManager.drawString(vg, input, x + 12, y + height / 2f + 1, color, 14f, Fonts.REGULAR);
} else {
RenderManager.drawString(vg, input, x + this.width / 2f - halfTextWidth, y + height / 2f + 1, color, 14f, Fonts.REGULAR);
@@ -190,6 +231,7 @@ public class TextInputField extends BasicElement {
} catch (Exception e) {
e.printStackTrace();
}
+
}
public void keyTyped(char c, int key) {
@@ -345,12 +387,7 @@ public class TextInputField extends BasicElement {
if (UKeyboard.isCtrlKeyDown()) return;
if (isAllowedCharacter(c)) {
if (selectedText != null) {
- if (caretPos > prevCaret) {
- input = input.substring(0, prevCaret) + input.substring(prevCaret, caretPos);
- caretPos = prevCaret;
- } else {
- input = input.substring(0, caretPos) + input.substring(caretPos, prevCaret);
- }
+ if (caretPos > prevCaret) caretPos = prevCaret;
if (selectedText.equals(input)) {
input = "";
}
@@ -390,16 +427,16 @@ public class TextInputField extends BasicElement {
end = this.getTextWidth(vg, input.substring(prevCaret, caretPos));
}
- private int calculatePos(int pos) {
+ private int calculatePos(int pos, String string) {
if (centered) pos -= 12;
String s1 = "";
int i;
- for (char c : input.toCharArray()) {
+ for (char c : string.toCharArray()) {
if (pos - x - 12 < 0) {
return 0;
}
- if (pos - x - 12 > this.getTextWidth(vg, input)) {
- return input.length();
+ if (pos - x - 12 > this.getTextWidth(vg, string)) {
+ return string.length();
}
s1 += c;
i = (int) this.getTextWidth(vg, s1);
@@ -411,7 +448,6 @@ public class TextInputField extends BasicElement {
}
public void onClose() {
-
}
private float getTextWidth(long vg, String s) {
@@ -426,7 +462,49 @@ public class TextInputField extends BasicElement {
}
}
+ private int getCaretLine(int caret) {
+ int pos = 0;
+ for (int i = 0; i < wrappedText.size(); i++) {
+ String text = wrappedText.get(i);
+ float length = RenderManager.getTextWidth(vg, text, 14.0f, Fonts.REGULAR);
+ pos += length;
+ if (pos < caret) continue;
+ return i;
+ }
+ return 0;
+ }
+
+ private float getCaretX(int caret) {
+ int pos = 0;
+ for (String text : wrappedText) {
+ float length = RenderManager.getTextWidth(vg, text, 14.0f, Fonts.REGULAR);
+ if (pos + length < caret) {
+ pos += length;
+ continue;
+ }
+ return RenderManager.getTextWidth(vg, text.substring(0, caret - pos), 14.0f, Fonts.REGULAR);
+ }
+ return 0;
+ }
+
+ private int getLineCaret(int caret, int line) {
+ int pos = 0;
+ for (String text : wrappedText) {
+ float length = RenderManager.getTextWidth(vg, text, 14.0f, Fonts.REGULAR);
+ if (pos + length < caret) {
+ pos += length;
+ continue;
+ }
+ return caret - pos;
+ }
+ return 0;
+ }
+
public static boolean isAllowedCharacter(char character) {
return character != 167 && character >= ' ' && character != 127;
}
+
+ public int getLines() {
+ return lines;
+ }
}
diff --git a/src/main/java/cc/polyfrost/oneconfig/lwjgl/RenderManager.java b/src/main/java/cc/polyfrost/oneconfig/lwjgl/RenderManager.java
index 153fc52..9d6763f 100644
--- a/src/main/java/cc/polyfrost/oneconfig/lwjgl/RenderManager.java
+++ b/src/main/java/cc/polyfrost/oneconfig/lwjgl/RenderManager.java
@@ -379,43 +379,9 @@ public final class RenderManager {
drawSvg(vg, icon, centerX - iconSize / 2f, centerY - iconSize / 2f, iconSize, iconSize);
}
- /*public static void drawSvg(long vg, String filename) {
- if (ImageLoader.INSTANCE.loadSVGImage(filename)) {
- try {
- NSVGImage image = ImageLoader.INSTANCE.getSVG(filename);
- NSVGShape shape = image.shapes();
- NSVGPath path = shape.paths();
- while (shape.address() != 0) {
- while (path.address() != 0) {
- nvgBeginPath(vg);
- nvgFillColor(vg, color(vg, new Color(255, 255, 255).getRGB()));
- nvgStrokeColor(vg, color(vg, new Color(255, 255, 255).getRGB()));
- nvgStrokeWidth(vg, shape.strokeWidth());
- FloatBuffer points = path.pts();
- nvgMoveTo(vg, points.get(), points.get());
- while (points.remaining() >= 6){
- nvgBezierTo(vg, points.get(), points.get(), points.get(), points.get(), points.get(), points.get());
- }
- if (path.closed() == 1) {
- nvgLineTo(vg, points.get(0), points.get(1));
- }
- nvgStroke(vg);
- nvgClosePath(vg);
- path = path.next();
- }
- shape = shape.next();
- }
- path.free();
- shape.free();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }*/
-
// gl
- public static void drawScaledString(String text, float x, float y, int color, boolean shadow, float scale) { //todo replace eventually with either nanovg or UMatrixStack
+ public static void drawScaledString(String text, float x, float y, int color, boolean shadow, float scale) {
UGraphics.GL.pushMatrix();
UGraphics.GL.scale(scale, scale, 1);
UMinecraft.getFontRenderer().drawString(text, x * (1 / scale), y * (1 / scale), color, shadow);
diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/TextUtils.java b/src/main/java/cc/polyfrost/oneconfig/utils/TextUtils.java
new file mode 100644
index 0000000..f574ea1
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/utils/TextUtils.java
@@ -0,0 +1,32 @@
+package cc.polyfrost.oneconfig.utils;
+
+import cc.polyfrost.oneconfig.lwjgl.RenderManager;
+import cc.polyfrost.oneconfig.lwjgl.font.Fonts;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class TextUtils {
+
+ public static ArrayList<String> wrapText(long vg, String text, float maxWidth, float fontSize, Fonts font) {
+ ArrayList<String> wrappedText = new ArrayList<>();
+ List<String> split = Arrays.asList(text.split(" "));
+ for (int i = split.size(); i >= 0; i--) {
+ String textPart = String.join(" ", split.subList(0, i));
+ float textWidth = RenderManager.getTextWidth(vg, textPart, fontSize, font);
+ if (textWidth > maxWidth) continue;
+ wrappedText.add(textPart);
+ if (i != split.size())
+ wrappedText.addAll(wrapText(vg, String.join(" ", split.subList(i, split.size())), maxWidth, fontSize, font));
+ break;
+ }
+ if (text.endsWith(" ")) {
+ String lastLine = wrappedText.get(wrappedText.size() - 1);
+ lastLine += " ";
+ wrappedText.remove(wrappedText.size() - 1);
+ wrappedText.add(lastLine);
+ }
+ return wrappedText;
+ }
+}