package io.github.moulberry.notenoughupdates.itemeditor; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import org.apache.commons.lang3.StringUtils; import java.awt.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class GuiElementTextField extends GuiElement { public static final int SCALE_TEXT = 0b100000; public static final int NUM_ONLY = 0b10000; public static final int NO_SPACE = 0b01000; public static final int FORCE_CAPS = 0b00100; public static final int COLOUR = 0b00010; public static final int MULTILINE = 0b00001; private int searchBarYSize = 20; private int searchBarXSize = 350; private static final int searchBarPadding = 2; private int options = 0; private boolean focus = false; private int x; private int y; private String prependText = ""; private GuiTextField textField = new GuiTextField(0, Minecraft.getMinecraft().fontRendererObj, 0 , 0, 0, 0); private int customBorderColour = -1; public GuiElementTextField(String initialText, int options) { textField.setFocused(true); textField.setCanLoseFocus(false); textField.setMaxStringLength(9999); textField.setText(initialText); this.options = options; } public void setMaxStringLength(int len) { textField.setMaxStringLength(len); } public void setCustomBorderColour(int colour) { this.customBorderColour = colour; } public String getText() { return textField.getText(); } public void setPrependText(String text) { this.prependText = text; } public void setText(String text) { if(textField.getText() == null || !textField.getText().equals(text)) { textField.setText(text); } } public void setSize(int searchBarXSize, int searchBarYSize) { this.searchBarXSize = searchBarXSize; this.searchBarYSize = searchBarYSize; } @Override public String toString() { return textField.getText(); } public boolean getFocus() { return focus; } @Override public int getHeight() { ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); int numLines = StringUtils.countMatches(textField.getText(), "\n")+1; int extraSize = (searchBarYSize-8)/2+8; int bottomTextBox = searchBarYSize + extraSize*(numLines-1); return bottomTextBox + paddingUnscaled*2; } @Override public int getWidth() { ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); return searchBarXSize + paddingUnscaled*2; } private float getScaleFactor(String str) { return Math.min(1, (searchBarXSize-2)/(float)Minecraft.getMinecraft().fontRendererObj.getStringWidth(str)); } private boolean isScaling() { return (options & SCALE_TEXT) != 0; } private float getStringWidth(String str) { if(isScaling()) { return Minecraft.getMinecraft().fontRendererObj.getStringWidth(str)*getScaleFactor(str); } else { return Minecraft.getMinecraft().fontRendererObj.getStringWidth(str); } } public int getCursorPos(int mouseX, int mouseY) { int xComp = mouseX - x; int yComp = mouseY - y; int extraSize = (searchBarYSize-8)/2+8; String renderText = prependText + textField.getText(); int lineNum = Math.round(((yComp - (searchBarYSize-8)/2))/extraSize); Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6])(?!\\u00B6)"); String text = renderText; String textNoColour = renderText; if((options & COLOUR) != 0) { while(true) { Matcher matcher = patternControlCode.matcher(text); if(!matcher.find() || matcher.groupCount() < 1) break; String code = matcher.group(1); text = matcher.replaceFirst("\u00A7"+code+"\u00B6"+code); } } while(true) { Matcher matcher = patternControlCode.matcher(textNoColour); if(!matcher.find() || matcher.groupCount() < 1) break; String code = matcher.group(1); textNoColour = matcher.replaceFirst("\u00B6"+code); } int currentLine = 0; int cursorIndex = 0; for(; cursorIndex 0) { textBeforeCursorWidth = 0; lineBefore = split[split.length-1]; thisLineBeforeCursor = ""; } else if(split.length > 1) { thisLineBeforeCursor = split[split.length-1]; lineBefore = split[split.length-2]; textBeforeCursorWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(thisLineBeforeCursor); } else { return; } String trimmed = Minecraft.getMinecraft().fontRendererObj .trimStringToWidth(lineBefore, textBeforeCursorWidth); int linePos = strLenNoColor(trimmed); if(linePos != strLenNoColor(lineBefore)) { char after = lineBefore.charAt(linePos); int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); if(trimmedWidth + charWidth/2 < textBeforeCursorWidth) { linePos++; } } int newPos = textField.getSelectionEnd()-strLenNoColor(thisLineBeforeCursor) -strLenNoColor(lineBefore)-1+linePos; if(GuiScreen.isShiftKeyDown()) { textField.setSelectionPos(newPos); } else { textField.setCursorPosition(newPos); } } else if(keyCode == 208) { //Down String textNCBeforeCursor = textNoColour.substring(0, textField.getSelectionEnd()); int colorCodes = StringUtils.countMatches(textNCBeforeCursor, "\u00B6"); String textBeforeCursor = text.substring(0, textField.getSelectionEnd()+colorCodes*2); int numLinesBeforeCursor = StringUtils.countMatches(textBeforeCursor, "\n"); String[] split = textBeforeCursor.split("\n"); String thisLineBeforeCursor; int textBeforeCursorWidth; if(split.length == numLinesBeforeCursor) { thisLineBeforeCursor = ""; textBeforeCursorWidth = 0; } else if(split.length > 0) { thisLineBeforeCursor = split[split.length-1]; textBeforeCursorWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(thisLineBeforeCursor); } else { return; } String[] split2 = textNoColour.split("\n"); if(split2.length > numLinesBeforeCursor+1) { String lineAfter = split2[numLinesBeforeCursor+1]; String trimmed = Minecraft.getMinecraft().fontRendererObj .trimStringToWidth(lineAfter, textBeforeCursorWidth); int linePos = strLenNoColor(trimmed); if(linePos != strLenNoColor(lineAfter)) { char after = lineAfter.charAt(linePos); int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed); int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after); if(trimmedWidth + charWidth/2 < textBeforeCursorWidth) { linePos++; } } int newPos = textField.getSelectionEnd()-strLenNoColor(thisLineBeforeCursor) +strLenNoColor(split2[numLinesBeforeCursor])+1+linePos; if(GuiScreen.isShiftKeyDown()) { textField.setSelectionPos(newPos); } else { textField.setCursorPosition(newPos); } } } } String old = textField.getText(); if((options & FORCE_CAPS) != 0) typedChar = Character.toUpperCase(typedChar); if((options & NO_SPACE) != 0 && typedChar == ' ') return; textField.setFocused(true); textField.textboxKeyTyped(typedChar, keyCode); if((options & COLOUR) != 0) { if(typedChar == '&') { int pos = textField.getCursorPosition()-2; if(pos >= 0 && pos < textField.getText().length()) { if(textField.getText().charAt(pos) == '&') { String before = textField.getText().substring(0, pos); String after = ""; if(pos+2 < textField.getText().length()) { after = textField.getText().substring(pos+2); } textField.setText(before + "\u00A7" + after); textField.setCursorPosition(pos+1); } } } } if((options & NUM_ONLY) != 0 && textField.getText().matches("[^0-9.]")) textField.setText(old); } } public void render(int x, int y) { this.x = x; this.y = y; drawTextbox(x, y, searchBarXSize, searchBarYSize, searchBarPadding, textField, focus); } private void drawTextbox(int x, int y, int searchBarXSize, int searchBarYSize, int searchBarPadding, GuiTextField textField, boolean focus) { ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); String renderText = prependText + textField.getText(); GlStateManager.disableLighting(); /** * Search bar */ int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor(); if(paddingUnscaled < 1) paddingUnscaled = 1; int numLines = StringUtils.countMatches(renderText, "\n")+1; int extraSize = (searchBarYSize-8)/2+8; int bottomTextBox = y + searchBarYSize + extraSize*(numLines-1); int borderColour = focus ? Color.GREEN.getRGB() : Color.WHITE.getRGB(); if(customBorderColour != -1) { borderColour = customBorderColour; } //bar background drawRect(x - paddingUnscaled, y - paddingUnscaled, x + searchBarXSize + paddingUnscaled, bottomTextBox + paddingUnscaled, borderColour); drawRect(x, y, x + searchBarXSize, bottomTextBox, Color.BLACK.getRGB()); //bar text Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6\n])(?!\\u00B6)"); String text = renderText; String textNoColor = renderText; if((options & COLOUR) != 0) { while(true) { Matcher matcher = patternControlCode.matcher(text); if(!matcher.find() || matcher.groupCount() < 1) break; String code = matcher.group(1); text = matcher.replaceFirst("\u00A7"+code+"\u00B6"+code); } } while(true) { Matcher matcher = patternControlCode.matcher(textNoColor); if(!matcher.find() || matcher.groupCount() < 1) break; String code = matcher.group(1); textNoColor = matcher.replaceFirst("\u00B6"+code); } int xStartOffset = 5; float scale = 1; String[] texts = text.split("\n"); for(int yOffI = 0; yOffI < texts.length; yOffI++) { int yOff = yOffI*extraSize; if(isScaling() && Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI])>searchBarXSize-10) { scale = (searchBarXSize-2)/(float)Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI]); if(scale > 1) scale=1; float newLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI])*scale; xStartOffset = (int)((searchBarXSize-newLen)/2f); Utils.drawStringCenteredScaledMaxWidth(texts[yOffI], Minecraft.getMinecraft().fontRendererObj, x+searchBarXSize/2f, y+searchBarYSize/2f+yOff, false, searchBarXSize-2, Color.WHITE.getRGB()); } else { Minecraft.getMinecraft().fontRendererObj.drawString(Utils.trimToWidth(texts[yOffI], searchBarXSize-10), x + 5, y+(searchBarYSize-8)/2+yOff, Color.WHITE.getRGB()); } } if(focus && System.currentTimeMillis()%1000>500) { String textNCBeforeCursor = textNoColor.substring(0, textField.getCursorPosition()+prependText.length()); int colorCodes = StringUtils.countMatches(textNCBeforeCursor, "\u00B6"); String textBeforeCursor = text.substring(0, textField.getCursorPosition()+prependText.length()+(((options & COLOUR) != 0) ? colorCodes*2 : 0)); int numLinesBeforeCursor = StringUtils.countMatches(textBeforeCursor, "\n"); int yOff = numLinesBeforeCursor*extraSize; String[] split = textBeforeCursor.split("\n"); int textBeforeCursorWidth; if(split.length <= numLinesBeforeCursor || split.length == 0) { textBeforeCursorWidth = 0; } else { textBeforeCursorWidth = (int)(Minecraft.getMinecraft().fontRendererObj.getStringWidth(split[split.length-1])*scale); } drawRect(x + xStartOffset + textBeforeCursorWidth, y+(searchBarYSize-8)/2-1 + yOff, x + xStartOffset + textBeforeCursorWidth+1, y+(searchBarYSize-8)/2+9 + yOff, Color.WHITE.getRGB()); } String selectedText = textField.getSelectedText(); if(!selectedText.isEmpty()) { int leftIndex = Math.min(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length()); int rightIndex = Math.max(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length()); float texX = 0; int texY = 0; boolean sectionSignPrev = false; boolean bold = false; for(int i=0; i= leftIndex && i < rightIndex) { drawRect(x + xStartOffset + (int)texX, y+(searchBarYSize-8)/2-1 + texY, x + xStartOffset + (int)texX + 3, y+(searchBarYSize-8)/2+9 + texY, Color.LIGHT_GRAY.getRGB()); } texX = 0; texY += extraSize; continue; } //String c2 = bold ? EnumChatFormatting.BOLD.toString() : "" + c; int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(String.valueOf(c)); if(bold) len++; if(i >= leftIndex && i < rightIndex) { drawRect(x + xStartOffset + (int)texX, y+(searchBarYSize-8)/2-1 + texY, x + xStartOffset + (int)(texX + len*scale), y+(searchBarYSize-8)/2+9 + texY, Color.LIGHT_GRAY.getRGB()); Utils.drawStringScaled(String.valueOf(c), Minecraft.getMinecraft().fontRendererObj, x + xStartOffset + texX, y+searchBarYSize/2f-scale*8/2f + texY, false, Color.BLACK.getRGB(), scale); if(bold) { Utils.drawStringScaled(String.valueOf(c), Minecraft.getMinecraft().fontRendererObj, x + xStartOffset + texX + 1, y+searchBarYSize/2f-scale*8/2f + texY, false, Color.BLACK.getRGB(), scale); } } texX += len*scale; } } } }