|
| 1 | +package net.modificationstation.stationapi.api.config; |
| 2 | + |
| 3 | +import com.google.common.base.CharMatcher; |
| 4 | +import net.modificationstation.stationapi.impl.config.DrawContextAccessor; |
| 5 | +import net.minecraft.client.font.TextRenderer; |
| 6 | +import net.minecraft.client.gui.screen.Screen; |
| 7 | +import org.lwjgl.opengl.GL11; |
| 8 | +import org.lwjgl.opengl.GL12; |
| 9 | + |
| 10 | +import java.awt.*; |
| 11 | +import java.awt.datatransfer.*; |
| 12 | +import java.util.List; |
| 13 | + |
| 14 | +/** |
| 15 | + * Some utility methods copied over from r1.2.5 for use in ExtensibleTextFieldWidget. |
| 16 | + * This should be useful for other things. |
| 17 | + */ |
| 18 | +public class CharacterUtils { |
| 19 | + // Custom methods |
| 20 | + |
| 21 | + /** |
| 22 | + * Renders a tooltip on screen at the provided place, handling flipping of the tooltip where required. |
| 23 | + * @param textRenderer the text renderer to use. You can use <code>((Minecraft) FabricLoader.getInstance().getGameInstance()).textRenderer</code> for this. |
| 24 | + * @param tooltip the tooltip to render. Can be multiline using multiple elements on the list. |
| 25 | + * @param x the X position where the tooltip should be. Typically mouseX. |
| 26 | + * @param y the Y position where the tooltip should be. Typically mouseY. |
| 27 | + * @param screen the screen where the tooltip is being rendered. |
| 28 | + */ |
| 29 | + public static void renderTooltip(TextRenderer textRenderer, List<String> tooltip, int x, int y, Screen screen) { |
| 30 | + if (!tooltip.isEmpty()) { |
| 31 | + |
| 32 | + GL11.glDisable(GL12.GL_RESCALE_NORMAL); |
| 33 | + GL11.glDisable(GL11.GL_DEPTH_TEST); |
| 34 | + int k = 0; |
| 35 | + |
| 36 | + for (String string : tooltip) { |
| 37 | + int l = textRenderer.getWidth(string); |
| 38 | + if (l > k) { |
| 39 | + k = l; |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + int m = x + 12; |
| 44 | + int n = y - 12; |
| 45 | + int p = 8; |
| 46 | + if (tooltip.size() > 1) { |
| 47 | + p += 2 + (tooltip.size() - 1) * 10; |
| 48 | + } |
| 49 | + |
| 50 | + if (m + k > screen.width) { |
| 51 | + m -= 28 + k; |
| 52 | + } |
| 53 | + |
| 54 | + if (n + p + 6 > screen.height) { |
| 55 | + n = screen.height - p - 6; |
| 56 | + } |
| 57 | + |
| 58 | + int transparentGrey = -1073741824; |
| 59 | + int margin = 3; |
| 60 | + ((DrawContextAccessor) screen).invokeFill(m - margin, n - margin, m + k + margin, |
| 61 | + n + p + margin, transparentGrey); |
| 62 | + GL11.glPushMatrix(); |
| 63 | + GL11.glTranslatef(0, 0, 300); |
| 64 | + |
| 65 | + for(int t = 0; t < tooltip.size(); ++t) { |
| 66 | + String string2 = tooltip.get(t); |
| 67 | + if (string2 != null) { |
| 68 | + textRenderer.draw(string2, m, n, 0xffffff); |
| 69 | + } |
| 70 | + |
| 71 | + if (t == 0) { |
| 72 | + n += 2; |
| 73 | + } |
| 74 | + |
| 75 | + n += 10; |
| 76 | + } |
| 77 | + |
| 78 | + GL11.glPopMatrix(); |
| 79 | + GL11.glEnable(GL11.GL_DEPTH_TEST); |
| 80 | + GL11.glEnable(GL12.GL_RESCALE_NORMAL); |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * Custom function for converting an JWJGL colour into minecraft's weird ARGB system. |
| 86 | + * Uses AWT's Colour class because LWJGL's one doesn't exist on server, so it saves me a headache. |
| 87 | + */ |
| 88 | + public static int getIntFromColour(Color colour) { |
| 89 | + return ((colour.getAlpha() & 255) << 24) | ((colour.getRed() & 255) << 16) | ((colour.getGreen() & 255) << 8) | (colour.getBlue() & 255); |
| 90 | + } |
| 91 | + |
| 92 | + /** |
| 93 | + * Susceptible to overflows, but honestly, I am not too concerned. |
| 94 | + * <a href="https://stackoverflow.com/a/237204">StackOverflow Source</a> |
| 95 | + */ |
| 96 | + public static boolean isInteger(String str) { |
| 97 | + if (str == null) { |
| 98 | + return false; |
| 99 | + } |
| 100 | + int length = str.length(); |
| 101 | + if (length == 0) { |
| 102 | + return false; |
| 103 | + } |
| 104 | + int i = 0; |
| 105 | + if (str.charAt(0) == '-') { |
| 106 | + if (length == 1) { |
| 107 | + return false; |
| 108 | + } |
| 109 | + i = 1; |
| 110 | + } |
| 111 | + for (; i < length; i++) { |
| 112 | + char c = str.charAt(i); |
| 113 | + if (c < '0' || c > '9') { |
| 114 | + return false; |
| 115 | + } |
| 116 | + } |
| 117 | + return true; |
| 118 | + } |
| 119 | + |
| 120 | + /** |
| 121 | + * Susceptible to overflows, but honestly, I am not too concerned. Modified to look for floats instead. |
| 122 | + * <a href="https://stackoverflow.com/a/237204">StackOverflow Source</a> |
| 123 | + */ |
| 124 | + public static boolean isFloat(String str) { |
| 125 | + if (str == null) { |
| 126 | + return false; |
| 127 | + } |
| 128 | + int length = str.length(); |
| 129 | + if (length == 0 || str.charAt(0) == '.' || str.charAt(str.length()-1) == '.' || CharMatcher.is('.').countIn(str) > 1) { |
| 130 | + return false; |
| 131 | + } |
| 132 | + int i = 0; |
| 133 | + if (str.charAt(0) == '-') { |
| 134 | + if (length == 1) { |
| 135 | + return false; |
| 136 | + } |
| 137 | + i = 1; |
| 138 | + } |
| 139 | + for (; i < length; i++) { |
| 140 | + char c = str.charAt(i); |
| 141 | + if ((c < '0' || c > '9') && c != '.') { |
| 142 | + return false; |
| 143 | + } |
| 144 | + } |
| 145 | + return true; |
| 146 | + } |
| 147 | + |
| 148 | + // 1.2.5 methods. Most of these I have no real explanation for. |
| 149 | + |
| 150 | + public static boolean isCharacterValid(char c) { |
| 151 | + return c != 167 && (net.minecraft.util.CharacterUtils.VALID_CHARACTERS.indexOf(c) >= 0 || c > ' '); |
| 152 | + } |
| 153 | + |
| 154 | + public static String stripInvalidChars(String string) { |
| 155 | + StringBuilder var1 = new StringBuilder(); |
| 156 | + char[] var2 = string.toCharArray(); |
| 157 | + |
| 158 | + for (char var5 : var2) { |
| 159 | + if (isCharacterValid(var5)) { |
| 160 | + var1.append(var5); |
| 161 | + } |
| 162 | + } |
| 163 | + |
| 164 | + return var1.toString(); |
| 165 | + } |
| 166 | + |
| 167 | + /** |
| 168 | + * Tries to set the given string as clipboard text. Silently fails. |
| 169 | + * @param string the text to set. |
| 170 | + */ |
| 171 | + public static void setClipboardText(String string) { |
| 172 | + try { |
| 173 | + StringSelection var1 = new StringSelection(string); |
| 174 | + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(var1, null); |
| 175 | + } catch (Exception ignored) { |
| 176 | + } |
| 177 | + |
| 178 | + } |
| 179 | + |
| 180 | + /** |
| 181 | + * Gets the current text on clipboard. Strips formatting. |
| 182 | + * @return the current text of the clipboard. Can be empty, but never null. Fails silently. |
| 183 | + */ |
| 184 | + public static String getClipboardText() { |
| 185 | + try { |
| 186 | + Transferable var0 = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); |
| 187 | + if (var0 != null && var0.isDataFlavorSupported(DataFlavor.stringFlavor)) { |
| 188 | + return (String)var0.getTransferData(DataFlavor.stringFlavor); |
| 189 | + } |
| 190 | + } catch (Exception ignored) { |
| 191 | + } |
| 192 | + |
| 193 | + return ""; |
| 194 | + } |
| 195 | + |
| 196 | + /** |
| 197 | + * Processes string colours. I think. I have no idea, honestly. |
| 198 | + */ |
| 199 | + public static String getRenderableString(String string, int maxPixelWidth, boolean flag, TextRenderer textRenderer) { |
| 200 | + StringBuilder var4 = new StringBuilder(); |
| 201 | + int currentPixelWidth = 0; |
| 202 | + int var6 = flag ? string.length() - 1 : 0; |
| 203 | + int var7 = flag ? -1 : 1; |
| 204 | + boolean var8 = false; |
| 205 | + boolean var9 = false; |
| 206 | + |
| 207 | + for(int var10 = var6; var10 >= 0 && var10 < string.length() && currentPixelWidth < maxPixelWidth; var10 += var7) { |
| 208 | + char var11 = string.charAt(var10); |
| 209 | + int var12 = textRenderer.getWidth(Character.toString(var11)); |
| 210 | + if (var8) { |
| 211 | + var8 = false; |
| 212 | + if (var11 != 'l' && var11 != 'L') { |
| 213 | + if (var11 == 'r' || var11 == 'R') { |
| 214 | + var9 = false; |
| 215 | + } |
| 216 | + } else { |
| 217 | + var9 = true; |
| 218 | + } |
| 219 | + } else if (var12 < 0) { |
| 220 | + var8 = true; |
| 221 | + } else { |
| 222 | + currentPixelWidth += var12; |
| 223 | + if (var9) { |
| 224 | + ++currentPixelWidth; |
| 225 | + } |
| 226 | + } |
| 227 | + |
| 228 | + if (currentPixelWidth > maxPixelWidth) { |
| 229 | + break; |
| 230 | + } |
| 231 | + |
| 232 | + if (flag) { |
| 233 | + var4.insert(0, var11); |
| 234 | + } else { |
| 235 | + var4.append(var11); |
| 236 | + } |
| 237 | + } |
| 238 | + |
| 239 | + return var4.toString(); |
| 240 | + } |
| 241 | +} |
0 commit comments