diff --git a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/BlocksComponent.java b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/BlocksComponent.java index 7f54010..14ec047 100644 --- a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/BlocksComponent.java +++ b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/BlocksComponent.java @@ -162,8 +162,8 @@ public final class BlocksComponent extends HudComponent { public void mouseClick(int mouseX, int mouseY, int button) { super.mouseClick(mouseX, mouseY, button); - if (this.searchBox.displayValue.equals("...")) - this.searchBox.displayValue = ""; + if (this.searchBox.getText().equals("...")) + this.searchBox.setText(""); this.searchBox.mouseClick(mouseX, mouseY, button); } @@ -212,7 +212,7 @@ public final class BlocksComponent extends HudComponent { super.keyTyped(typedChar, keyCode); this.searchBox.keyTyped(typedChar, keyCode); - if (this.searchBox.displayValue.equals("") && this.displayedBlocks.size() != 0) { + if (this.searchBox.getText().equals("") && this.displayedBlocks.size() != 0) { this.displayedBlocks.clear(); this.displayedBlocks.addAll(this.blocks); } else { @@ -220,9 +220,9 @@ public final class BlocksComponent extends HudComponent { } for (Block block : this.blocks) { - if (CharUtils.isAsciiNumeric(typedChar) && NumberUtils.isDigits(this.searchBox.displayValue)) { + if (CharUtils.isAsciiNumeric(typedChar) && NumberUtils.isDigits(this.searchBox.getText())) { final int blockID = Block.getIdFromBlock(block); - if (blockID == Integer.parseInt(this.searchBox.displayValue)) { + if (blockID == Integer.parseInt(this.searchBox.getText())) { if (!this.displayedBlocks.contains(block)) { this.displayedBlocks.add(block); } @@ -230,7 +230,7 @@ public final class BlocksComponent extends HudComponent { } else { final ResourceLocation registryName = block.getRegistryName(); if (registryName != null) { - if (registryName.toString().contains(this.searchBox.displayValue)) { + if (registryName.toString().contains(this.searchBox.getText())) { if (!this.displayedBlocks.contains(block)) { this.displayedBlocks.add(block); } diff --git a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/ColorComponent.java b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/ColorComponent.java index 2cd3718..ab64718 100644 --- a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/ColorComponent.java +++ b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/ColorComponent.java @@ -12,9 +12,9 @@ public class ColorComponent extends TextComponent { private Color currentColor; - private static final int BORDER = 1; - private static final int TEXT_BLOCK_PADDING = 1; + // space occupied from left to right: border, color box, spacing, text, spacing, check, spacing, gear, border private static final int COLOR_SIZE = 7; + private static final int GEAR_WIDTH = 8; private String customDisplayValue; @@ -24,7 +24,7 @@ public class ColorComponent extends TextComponent { public ColorComponent(String name, int defaultColor) { super(name, String.valueOf(defaultColor), false); this.currentColor = new Color(defaultColor); - this.displayValue = "#" + Integer.toHexString(this.currentColor.getRGB()).toLowerCase().substring(2); + this.setText("#" + Integer.toHexString(this.currentColor.getRGB()).toLowerCase().substring(2)); this.gearTexture = new Texture("gear_wheel.png"); this.gearTextureEnabled = new Texture("gear_wheel-enabled.png"); @@ -38,63 +38,33 @@ public class ColorComponent extends TextComponent { @Override public void render(int mouseX, int mouseY, float partialTicks) { - //super.render(mouseX, mouseY, partialTicks); - /*if (this.focused) { - this.setH(50); - } else { - this.setH(9); - }*/ - - if (isMouseInside(mouseX, mouseY)) - RenderUtil.drawGradientRect(this.getX(), this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0x30909090, 0x00101010); - - // draw bg rect - RenderUtil.drawRect(this.getX(), this.getY(), this.getX() + this.getW() - (this.focused ? 20 : 10), this.getY() + this.getH(), 0x45303030); - - // draw color rect - RenderUtil.drawRect(this.getX() + BORDER, this.getY() + BORDER, this.getX() + BORDER + COLOR_SIZE, this.getY() + BORDER + COLOR_SIZE, ColorUtil.changeAlpha(this.currentColor.getRGB(), 0xFF)); - - // draw name / display value - String displayedName = this.getName(); + // draw text component, reserving space for gear and color rectangle + // only show color hex value if focused, else, show value's name + String displayedName = null; if (this.focused) { - displayedName = this.displayValue; + displayedName = ""; } else if (customDisplayValue != null) { displayedName = customDisplayValue; } else if (this.getDisplayName() != null) { displayedName = this.getDisplayName(); - } - Minecraft.getMinecraft().fontRenderer.drawString(displayedName, (int) this.getX() + BORDER + COLOR_SIZE + BORDER, (int) this.getY() + BORDER, this.focused ? 0xFFFFFFFF : 0xFFAAAAAA); - - // draw bg rect behind right button - RenderUtil.drawRect(this.getX() + this.getW() - (this.focused ? 20 : 10), this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0x45202020); - - if (this.focused) { - if (!this.selectedText.equals("")) { - RenderUtil.drawRect(this.getX() + BORDER + COLOR_SIZE + BORDER, this.getY(), this.getX() + BORDER + COLOR_SIZE + BORDER + Minecraft.getMinecraft().fontRenderer.getStringWidth(this.displayValue), this.getY() + this.getH(), 0x45FFFFFF); - } - - float blockX = this.getX() + BORDER + Minecraft.getMinecraft().fontRenderer.getStringWidth(this.displayValue) + COLOR_SIZE + BORDER + TEXT_BLOCK_PADDING; - float blockY = this.getY() + TEXT_BLOCK_PADDING; - int blockWidth = 2; - int blockHeight = Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT - 2; - RenderUtil.drawRect(blockX, blockY, blockX + blockWidth, blockY + blockHeight, 0xFFFFFFFF); - - // draw gear - RenderUtil.drawRect(this.getX() + this.getW() - 10, this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0xFF101010); - this.gearTextureEnabled.bind(); - this.gearTextureEnabled.render(this.getX() + this.getW() - 9, this.getY() + 0.5f, 8, 8); - - // check - RenderUtil.drawRect(this.getX() + this.getW() - 20, this.getY(), this.getX() + this.getW() - 10, this.getY() + this.getH(), 0xFF101010); - this.checkTexture.bind(); - this.checkTexture.render(this.getX() + this.getW() - 19, this.getY() + 0.5f, 8, 8); - - // handle holding backspace - this.handleBackspacing(); } else { - // draw gear + displayedName = this.getName(); + } + + this.renderReserved(mouseX, mouseY, partialTicks, displayedName, this.focused, SPACING + COLOR_SIZE, SPACING + GEAR_WIDTH + SPACING); + + // draw color rect + RenderUtil.drawRect(this.getX() + BORDER, this.getY() + BORDER, this.getX() + BORDER + COLOR_SIZE, this.getY() + BORDER + COLOR_SIZE, ColorUtil.changeAlpha(this.currentColor.getRGB(), 0xFF)); + + // draw gear + final float gearOffset = this.getX() + this.getW() - BORDER - GEAR_WIDTH; + if (this.focused) { + RenderUtil.drawRect(gearOffset - SPACING, this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0xFF101010); + this.gearTextureEnabled.bind(); + this.gearTextureEnabled.render(gearOffset, this.getY() + ICON_V_OFFSET, GEAR_WIDTH, GEAR_WIDTH); + } else { this.gearTexture.bind(); - this.gearTexture.render(this.getX() + this.getW() - 9, this.getY() + 0.5f, 8, 8); + this.gearTexture.render(gearOffset, this.getY() + ICON_V_OFFSET, GEAR_WIDTH, GEAR_WIDTH); } } @@ -106,8 +76,9 @@ public class ColorComponent extends TextComponent { return; if (button == 0) { - // check for clicking check - if (mouseX >= this.getX() + this.getW() - 20 && mouseX <= this.getX() + this.getW() - 10 && mouseY >= this.getY() && mouseY <= this.getY() + this.getH()) { + // check for clicking check check, spacing, gear, border + final float right = this.getX() + this.getW() - BORDER - GEAR_WIDTH - SPACING; + if (mouseX >= right - CHECK_WIDTH && mouseX <= right && mouseY >= this.getY() && mouseY <= this.getY() + this.getH()) { this.enterPressed(); } } @@ -116,7 +87,7 @@ public class ColorComponent extends TextComponent { @Override protected void enterPressed() { try { - int newColor = (int) Long.parseLong(this.displayValue.replaceAll("#", ""), 16); + int newColor = (int) Long.parseLong(this.getText().replaceAll("#", ""), 16); this.currentColor = new Color(newColor); } catch (NumberFormatException e) { Seppuku.INSTANCE.logChat(this.getName() + ": Invalid color format. Correct format example: \"ff0000\" for red."); diff --git a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/ItemsComponent.java b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/ItemsComponent.java index 6623fb5..8f0043d 100644 --- a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/ItemsComponent.java +++ b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/ItemsComponent.java @@ -122,8 +122,8 @@ public final class ItemsComponent extends HudComponent { public void mouseClick(int mouseX, int mouseY, int button) { super.mouseClick(mouseX, mouseY, button); - if (this.searchBox.displayValue.equals("...")) - this.searchBox.displayValue = ""; + if (this.searchBox.getText().equals("...")) + this.searchBox.setText(""); this.searchBox.mouseClick(mouseX, mouseY, button); } @@ -172,7 +172,7 @@ public final class ItemsComponent extends HudComponent { super.keyTyped(typedChar, keyCode); this.searchBox.keyTyped(typedChar, keyCode); - if (this.searchBox.displayValue.equals("") && this.displayedItems.size() != 0) { + if (this.searchBox.getText().equals("") && this.displayedItems.size() != 0) { this.displayedItems.clear(); this.displayedItems.addAll(this.items); } else { @@ -180,9 +180,9 @@ public final class ItemsComponent extends HudComponent { } for (Item item : this.items) { - if (CharUtils.isAsciiNumeric(typedChar) && NumberUtils.isDigits(this.searchBox.displayValue)) { + if (CharUtils.isAsciiNumeric(typedChar) && NumberUtils.isDigits(this.searchBox.getText())) { final int itemID = Item.getIdFromItem(item); - if (itemID == Integer.parseInt(this.searchBox.displayValue)) { + if (itemID == Integer.parseInt(this.searchBox.getText())) { if (!this.displayedItems.contains(item)) { this.displayedItems.add(item); } @@ -190,7 +190,7 @@ public final class ItemsComponent extends HudComponent { } else { final ResourceLocation registryName = item.getRegistryName(); if (registryName != null) { - if (registryName.toString().contains(this.searchBox.displayValue)) { + if (registryName.toString().contains(this.searchBox.getText())) { if (!this.displayedItems.contains(item)) { this.displayedItems.add(item); } diff --git a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/SliderComponent.java b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/SliderComponent.java index 89828e7..d13f18c 100644 --- a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/SliderComponent.java +++ b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/SliderComponent.java @@ -219,15 +219,15 @@ public final class SliderComponent extends HudComponent { public void onComponentEvent() { try { if (value.getValue() instanceof Integer) { - value.setValue(Integer.parseInt(valueNumberText.displayValue)); + value.setValue(Integer.parseInt(valueNumberText.getText())); } else if (value.getValue() instanceof Double) { - value.setValue(Double.parseDouble(valueNumberText.displayValue)); + value.setValue(Double.parseDouble(valueNumberText.getText())); } else if (value.getValue() instanceof Float) { - value.setValue(Float.parseFloat(valueNumberText.displayValue)); + value.setValue(Float.parseFloat(valueNumberText.getText())); } else if (value.getValue() instanceof Long) { - value.setValue(Long.parseLong(valueNumberText.displayValue)); + value.setValue(Long.parseLong(valueNumberText.getText())); } else if (value.getValue() instanceof Byte) { - value.setValue(Byte.parseByte(valueNumberText.displayValue)); + value.setValue(Byte.parseByte(valueNumberText.getText())); } Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); // save module configs } catch (NumberFormatException e) { diff --git a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/TextComponent.java b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/TextComponent.java index f8a9cfc..9f3526e 100644 --- a/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/TextComponent.java +++ b/src/main/java/me/rigamortis/seppuku/api/gui/hud/component/TextComponent.java @@ -3,13 +3,14 @@ package me.rigamortis.seppuku.api.gui.hud.component; import me.rigamortis.seppuku.Seppuku; import me.rigamortis.seppuku.api.texture.Texture; import me.rigamortis.seppuku.api.util.RenderUtil; -import me.rigamortis.seppuku.api.util.Timer; +import me.rigamortis.seppuku.api.util.StringUtil; import me.rigamortis.seppuku.impl.gui.hud.component.ColorsComponent; import me.rigamortis.seppuku.impl.gui.hud.component.module.ModuleListComponent; import net.minecraft.client.Minecraft; import org.lwjgl.input.Keyboard; import java.awt.*; +import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.DataFlavor; import java.util.logging.Level; @@ -18,7 +19,7 @@ import java.util.logging.Level; */ public class TextComponent extends HudComponent { - public String displayValue, selectedText; + private String displayValue; public boolean focused; public boolean digitOnly; public ComponentListener returnListener; @@ -26,66 +27,110 @@ public class TextComponent extends HudComponent { protected Texture checkTexture; - protected Timer backspaceTimer = new Timer(), backspaceWaitTimer = new Timer(); - protected boolean doBackspacing = false; - + private int textCursor = 0; + private int textCursorOffset = 0; + private int selectCursor = 0; + private int selectCursorOffset = 0; private int shiftLength = 0; + private boolean dirty = false; - private static final int CHECK_WIDTH = 10; - private static final int BLOCK_WIDTH = 2; + // space occupied from left to right: border, text, spacing, check, border + protected static final int BORDER = 1; + protected static final int SPACING = 1; + protected static final int SHIFT_GAP = 8; + protected static final int CHECK_WIDTH = 8; + protected static final int BLOCK_WIDTH = 2; + protected static final float ICON_V_OFFSET = 0.5f; public TextComponent(String name, String displayValue, boolean digitOnly) { super(name); this.displayValue = displayValue; - this.selectedText = ""; this.focused = false; this.digitOnly = digitOnly; this.checkTexture = new Texture("check.png"); } + protected void renderReserved(int mouseX, int mouseY, float partialTicks, String renderName, boolean renderValue, float reservedLeft, float reservedRight) { + // calculate dimensions that can be used given reserved left/right + final float left = this.getX() + reservedLeft; + final float right = this.getX() + this.getW() - reservedRight; + + // draw gradient if component has mouse hovering + if (this.isMouseInside(mouseX, mouseY)) + RenderUtil.drawGradientRect(this.getX(), this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0x30909090, 0x00101010); + + // draw background + RenderUtil.drawRect(this.getX(), this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0x45303030); + + // update text shift and cursor offsets if needed + String displayValueText = renderName; + if (renderValue) { + displayValueText += this.displayValue; + } + + if (this.focused && renderValue) { + if (this.dirty) { + this.dirty = false; + final String beforeTextCursor = displayValueText.substring(0, renderName.length() + this.textCursor); + this.textCursorOffset = Minecraft.getMinecraft().fontRenderer.getStringWidth(beforeTextCursor); + + if (this.selectCursor == this.textCursor) { + this.selectCursorOffset = this.textCursorOffset; + } else { + final String beforeSelectCursor = displayValueText.substring(0, renderName.length() + this.selectCursor); + this.selectCursorOffset = Minecraft.getMinecraft().fontRenderer.getStringWidth(beforeSelectCursor); + } + + // shift gap is the minimum amount of space to leave after the + // text cursor (block) so the user can see that there is more + // text to the right + final int shiftStart = Math.round(right - left) - CHECK_WIDTH - SPACING - BLOCK_WIDTH - BORDER * 2 - SHIFT_GAP; + if (this.textCursorOffset > shiftStart) { + this.shiftLength = this.textCursorOffset - shiftStart; + } else { + this.shiftLength = 0; + } + } + } else { + this.shiftLength = 0; + } + + // draw text + Minecraft.getMinecraft().fontRenderer.drawString(displayValueText, (int) left + BORDER - this.shiftLength, (int) this.getY() + BORDER, this.focused ? 0xFFFFFFFF : 0xFFAAAAAA); + + if (this.focused && renderValue) { + // draw text selection background + if (this.textCursor != this.selectCursor) { + final int start = Math.min(this.textCursorOffset, this.selectCursorOffset); + final int end = Math.max(this.textCursorOffset, this.selectCursorOffset); + RenderUtil.drawRect(left + start - this.shiftLength, this.getY(), left + end - this.shiftLength, this.getY() + this.getH(), 0x45FFFFFF); + } + + // draw text cursor (block) + float blockX = left + BORDER + this.textCursorOffset - this.shiftLength; + float blockY = this.getY() + BORDER; + final int blockHeight = Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT - BORDER * 2; + RenderUtil.drawRect(blockX, blockY, blockX + BLOCK_WIDTH, blockY + blockHeight, 0xFFFFFFFF); + + // draw checkbox + RenderUtil.drawRect(right - CHECK_WIDTH - BORDER - SPACING, this.getY(), right, this.getY() + this.getH(), 0xFF101010); + this.checkTexture.bind(); + this.checkTexture.render(right - CHECK_WIDTH - BORDER, this.getY() + ICON_V_OFFSET, CHECK_WIDTH, CHECK_WIDTH); + } + } + @Override public void render(int mouseX, int mouseY, float partialTicks) { super.render(mouseX, mouseY, partialTicks); - if (isMouseInside(mouseX, mouseY)) - RenderUtil.drawGradientRect(this.getX(), this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0x30909090, 0x00101010); - - RenderUtil.drawRect(this.getX(), this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0x45303030); - String renderName = this.getName(); if (this.getDisplayName() != null) { renderName = this.getDisplayName(); } - final String displayValueText = renderName + ": " + this.displayValue; - this.shiftLength = 0; - if (this.focused) { - if (Minecraft.getMinecraft().fontRenderer.getStringWidth(displayValueText) > (this.getW() - CHECK_WIDTH - BLOCK_WIDTH - 2)) - this.shiftLength += Math.abs(Minecraft.getMinecraft().fontRenderer.getStringWidth(displayValueText) - (this.getW() - CHECK_WIDTH - BLOCK_WIDTH - 2)); - } - - Minecraft.getMinecraft().fontRenderer.drawString(displayValueText, (int) this.getX() + 1 - this.shiftLength, (int) this.getY() + 1, this.focused ? 0xFFFFFFFF : 0xFFAAAAAA); - - if (this.focused) { - if (!this.selectedText.equals("")) { - RenderUtil.drawRect(this.getX() + Minecraft.getMinecraft().fontRenderer.getStringWidth(renderName + ": ") - this.shiftLength, this.getY(), this.getX() + Minecraft.getMinecraft().fontRenderer.getStringWidth(displayValueText), this.getY() + this.getH(), 0x45FFFFFF); - } - - float blockX = this.getX() + 1 - this.shiftLength + Minecraft.getMinecraft().fontRenderer.getStringWidth(renderName + ": " + this.displayValue); - float blockY = this.getY() + 1; - final int blockHeight = Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT - 2; - RenderUtil.drawRect(blockX, blockY, blockX + BLOCK_WIDTH, blockY + blockHeight, 0xFFFFFFFF); - - // check - RenderUtil.drawRect(this.getX() + this.getW() - CHECK_WIDTH, this.getY(), this.getX() + this.getW(), this.getY() + this.getH(), 0xFF101010); - this.checkTexture.bind(); - this.checkTexture.render(this.getX() + this.getW() - 9, this.getY() + 0.5f, 8, 8); - - // handle holding backspace - this.handleBackspacing(); - } + this.renderReserved(mouseX, mouseY, partialTicks, renderName + ": ", true, 0, 0); } @Override @@ -140,24 +185,29 @@ public class TextComponent extends HudComponent { textListener.onKeyTyped(keyCode); } - if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { + final boolean ctrlDown = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); + if (ctrlDown) { switch (keyCode) { case Keyboard.KEY_A: - this.selectedText = this.displayValue; + this.selectAll(); return; case Keyboard.KEY_V: - if (!this.digitOnly) { - this.displayValue += this.getClipBoard(); - } else if (this.getClipBoard().matches("[0-9]+") /* is a number */) { - this.displayValue += this.getClipBoard(); - } + this.insertText(this.getClipBoard()); return; case Keyboard.KEY_X: + if (this.setClipBoard(this.getSelection())) { + this.onRemoveSelectedText(); + } + return; case Keyboard.KEY_C: + this.setClipBoard(this.getSelection()); return; } + + return; // dont do anything else or you will get special characters typed } + final boolean shiftDown = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); switch (keyCode) { case Keyboard.KEY_ESCAPE: this.focused = false; @@ -165,30 +215,28 @@ public class TextComponent extends HudComponent { case Keyboard.KEY_RETURN: this.enterPressed(); return; - //case Keyboard.KEY_SPACE: - // if (!this.digitOnly) { - // this.displayValue += ' '; - // } - // break; case Keyboard.KEY_BACK: case Keyboard.KEY_DELETE: - this.backspaceWaitTimer.reset(); - this.doBackspacing = true; - if (this.displayValue.length() > 0) { - if (!this.onRemoveSelectedText()) { - this.displayValue = this.displayValue.substring(0, this.displayValue.length() - 1); - } - } + final int delta = (keyCode == Keyboard.KEY_DELETE) ? 1 : -1; + this.deleteText(delta); return; case Keyboard.KEY_CLEAR: - if (this.displayValue.length() > 0) { - this.displayValue = ""; - } + this.setText(""); return; case Keyboard.KEY_LEFT: + this.setTextCursor(this.textCursor - 1, shiftDown); + return; case Keyboard.KEY_RIGHT: + this.setTextCursor(this.textCursor + 1, shiftDown); + return; case Keyboard.KEY_UP: + case Keyboard.KEY_HOME: + this.setTextCursor(0, shiftDown); + return; case Keyboard.KEY_DOWN: + case Keyboard.KEY_END: + this.setTextCursor(this.displayValue.length(), shiftDown); + return; case Keyboard.KEY_LSHIFT: case Keyboard.KEY_RSHIFT: case Keyboard.KEY_LCONTROL: @@ -200,24 +248,11 @@ public class TextComponent extends HudComponent { case Keyboard.KEY_RMENU: case Keyboard.KEY_LMETA: return; - case Keyboard.KEY_PERIOD: - if (this.digitOnly) { - this.displayValue += typedChar; - } - break; default: break; } - if (digitOnly && !Character.isDigit(typedChar)) - return; - - this.onRemoveSelectedText(); - - //if (!digitOnly && !Character.isLetterOrDigit(typedChar)) - // return; - - this.displayValue += typedChar; + this.insertText(typedChar); } } @@ -226,7 +261,6 @@ public class TextComponent extends HudComponent { if (returnListener != null) returnListener.onComponentEvent(); - this.shiftLength = 0; this.focused = false; } @@ -239,27 +273,20 @@ public class TextComponent extends HudComponent { } protected boolean onRemoveSelectedText() { - if (!this.selectedText.equals("")) { - this.displayValue = ""; - this.selectedText = ""; - return true; + if (this.textCursor == this.selectCursor) { + return false; } - return false; + + this.deleteText(this.textCursor, this.selectCursor); + return true; } - protected void handleBackspacing() { - if (Keyboard.isKeyDown(Keyboard.KEY_BACK) || Keyboard.isKeyDown(Keyboard.KEY_DELETE)) { - if (this.doBackspacing && this.backspaceWaitTimer.passed(600)) { - if (this.backspaceTimer.passed(75)) { - if (this.displayValue.length() > 0) { - this.displayValue = this.displayValue.substring(0, this.displayValue.length() - 1); - } - this.backspaceTimer.reset(); - } - } - } else { - this.doBackspacing = false; + @Override + public void setW(float w) { + if (this.getW() != w) { + this.dirty = true; } + super.setW(w); } public String getClipBoard() { @@ -271,8 +298,109 @@ public class TextComponent extends HudComponent { return ""; } + public boolean setClipBoard(String s) { + try { + final StringSelection sel = new StringSelection(s); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, sel); + } catch (Exception e) { + Seppuku.INSTANCE.getLogger().log(Level.WARNING, "Error setting clipboard while using " + this.getName()); + return false; + } + + return true; + } + + public String getSelection() { + if (!this.focused || this.textCursor == this.selectCursor) { + // textCursor or selectCursor may be invalid if not focused + return ""; + } + + if(this.textCursor > this.selectCursor) { + return this.displayValue.substring(this.selectCursor, this.textCursor); + } else { + return this.displayValue.substring(this.textCursor, this.selectCursor); + } + } + public void focus() { + this.textCursor = this.selectCursor = this.displayValue.length(); this.focused = true; + this.dirty = true; + } + + public void setTextCursor(int pos, boolean shiftDown) { + if (pos <= 0) { + pos = 0; + } else if(pos > this.displayValue.length()) { + pos = this.displayValue.length(); + } + + final int selectPos = shiftDown ? this.selectCursor : pos; + if (this.textCursor != pos || this.selectCursor != selectPos) { + this.textCursor = pos; + this.selectCursor = selectPos; + this.dirty = true; + } + } + + public void insertText(char character) { + this.insertText(String.valueOf(character)); + } + + public void insertText(String str) { + if (this.digitOnly && !str.matches("[0-9.]+") /* is a number */) { + return; + } + + this.onRemoveSelectedText(); + + this.displayValue = StringUtil.insertAt(this.displayValue, str, this.textCursor); + this.setTextCursor(this.textCursor + str.length(), false); + } + + public void deleteText(int start, int end) { + // sanitise range + start = Math.min(Math.max(start, 0), this.displayValue.length()); + end = Math.min(Math.max(end, 0), this.displayValue.length()); + if (start == end) { + return; + } else if(start > end) { + final int temp = start; + start = end; + end = temp; + } + + this.displayValue = StringUtil.removeRange(this.displayValue, start, end); + this.setTextCursor(start, false); + } + + public void deleteText(int delta) { + if (delta == 0) { + return; + } + + if (!this.onRemoveSelectedText()) { + this.deleteText(this.textCursor, this.textCursor + delta); + } + } + + public void selectAll() { + this.textCursor = this.displayValue.length(); + this.selectCursor = 0; + this.dirty = true; + } + + public String getText() { + return this.displayValue; + } + + public void setText(String text) { + this.displayValue = text; + this.selectCursor = this.textCursor = text.length(); + if (this.focused) { + this.dirty = true; + } } public interface TextComponentListener { diff --git a/src/main/java/me/rigamortis/seppuku/api/util/RenderUtil.java b/src/main/java/me/rigamortis/seppuku/api/util/RenderUtil.java index bd87c0c..0e59445 100644 --- a/src/main/java/me/rigamortis/seppuku/api/util/RenderUtil.java +++ b/src/main/java/me/rigamortis/seppuku/api/util/RenderUtil.java @@ -36,7 +36,7 @@ public final class RenderUtil { GLUProjection.getInstance().updateMatrices(VIEWPORT, MODELVIEW, PROJECTION, (float) res.getScaledWidth() / (float) Minecraft.getMinecraft().displayWidth, (float) res.getScaledHeight() / (float) Minecraft.getMinecraft().displayHeight); } - public static void drawRect(float x, float y, float w, float h, int color) { + public static void drawRect(float left, float top, float right, float bottom, int color) { float alpha = (float) (color >> 24 & 255) / 255.0F; float red = (float) (color >> 16 & 255) / 255.0F; float green = (float) (color >> 8 & 255) / 255.0F; @@ -47,10 +47,10 @@ public final class RenderUtil { GlStateManager.disableTexture2D(); GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0); bufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR); - bufferbuilder.pos(x, h, 0.0D).color(red, green, blue, alpha).endVertex(); - bufferbuilder.pos(w, h, 0.0D).color(red, green, blue, alpha).endVertex(); - bufferbuilder.pos(w, y, 0.0D).color(red, green, blue, alpha).endVertex(); - bufferbuilder.pos(x, y, 0.0D).color(red, green, blue, alpha).endVertex(); + bufferbuilder.pos(left, bottom, 0.0D).color(red, green, blue, alpha).endVertex(); + bufferbuilder.pos(right, bottom, 0.0D).color(red, green, blue, alpha).endVertex(); + bufferbuilder.pos(right, top, 0.0D).color(red, green, blue, alpha).endVertex(); + bufferbuilder.pos(left, top, 0.0D).color(red, green, blue, alpha).endVertex(); tessellator.draw(); GlStateManager.enableTexture2D(); GlStateManager.disableBlend(); diff --git a/src/main/java/me/rigamortis/seppuku/api/util/StringUtil.java b/src/main/java/me/rigamortis/seppuku/api/util/StringUtil.java index 0da0528..3f0d20a 100644 --- a/src/main/java/me/rigamortis/seppuku/api/util/StringUtil.java +++ b/src/main/java/me/rigamortis/seppuku/api/util/StringUtil.java @@ -141,4 +141,51 @@ public final class StringUtil { } return sb.toString(); } + + /** + * Insert a string inside another string at a given position. Does not check + * for bounds and therefore may throw. + * @param original The original string, where the insertion string will be put + * @param insertion The string to insert + * @param position Where to insert the string at + * @returns the final string + */ + public static String insertAt(String original, String insertion, int position) { + return new StringBuilder(original.length() + insertion.length()) + .append(original, 0, position) + .append(insertion) + .append(original,position, original.length()) + .toString(); + } + + /** + * Insert a character inside another string at a given position. Does not + * check for bounds and therefore may throw. + * @param original The original string, where the insertion string will be put + * @param insertion The character to insert + * @param position Where to insert the character at + * @returns the final string + */ + public static String insertAt(String original, char insertion, int position) { + return new StringBuilder(original.length() + 1) + .append(original, 0, position) + .append(insertion) + .append(original,position, original.length()) + .toString(); + } + + /** + * Delete a range of characters in a string. Does not check for bounds and + * therefore may throw. + * @param s The string to manipulate + * @param start The start of the range + * @param end The end of the range (exclusive; character at this position not removed) + * @returns the final string + */ + public static String removeRange(String s, int start, int end) { + return new StringBuilder(s.length() + start - end) + .append(s, 0, start) + .append(s, end, s.length()) + .toString(); + } } diff --git a/src/main/java/me/rigamortis/seppuku/impl/gui/hud/GuiHudEditor.java b/src/main/java/me/rigamortis/seppuku/impl/gui/hud/GuiHudEditor.java index 6222c1f..2cc2823 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/gui/hud/GuiHudEditor.java +++ b/src/main/java/me/rigamortis/seppuku/impl/gui/hud/GuiHudEditor.java @@ -29,6 +29,8 @@ public final class GuiHudEditor extends GuiScreen { public void initGui() { super.initGui(); + Keyboard.enableRepeatEvents(true); + this.particlesComponent = (ParticlesComponent) Seppuku.INSTANCE.getHudManager().findComponent(ParticlesComponent.class); if (particlesComponent != null) { if (particlesComponent.isVisible()) { @@ -185,6 +187,7 @@ public final class GuiHudEditor extends GuiScreen { @Override public void onGuiClosed() { //Seppuku.INSTANCE.getConfigManager().saveAll(); + Keyboard.enableRepeatEvents(false); final HudEditorModule hudEditorModule = (HudEditorModule) Seppuku.INSTANCE.getModuleManager().find(HudEditorModule.class); if (hudEditorModule != null) { diff --git a/src/main/java/me/rigamortis/seppuku/impl/gui/hud/component/ColorsComponent.java b/src/main/java/me/rigamortis/seppuku/impl/gui/hud/component/ColorsComponent.java index 38edb7d..cb55b2c 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/gui/hud/component/ColorsComponent.java +++ b/src/main/java/me/rigamortis/seppuku/impl/gui/hud/component/ColorsComponent.java @@ -374,7 +374,7 @@ public final class ColorsComponent extends ResizableHudComponent { this.selectedColor = colorAtMouseClick.getRGB(); this.currentColorComponent.setCurrentColor(colorAtMouseClick); this.currentColorComponent.returnListener.onComponentEvent(); - this.currentColorComponent.displayValue = "#" + Integer.toHexString(this.selectedColor).toLowerCase().substring(2); + this.currentColorComponent.setText("#" + Integer.toHexString(this.selectedColor).toLowerCase().substring(2)); this.lastSpectrumMouseX = mouseX; this.lastSpectrumMouseY = mouseY; } else { diff --git a/src/main/java/me/rigamortis/seppuku/impl/gui/hud/component/module/ModuleListComponent.java b/src/main/java/me/rigamortis/seppuku/impl/gui/hud/component/module/ModuleListComponent.java index f546128..3681840 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/gui/hud/component/module/ModuleListComponent.java +++ b/src/main/java/me/rigamortis/seppuku/impl/gui/hud/component/module/ModuleListComponent.java @@ -464,7 +464,7 @@ public final class ModuleListComponent extends ResizableHudComponent { public void onKeyTyped(int keyCode) { if (keyCode == Keyboard.KEY_ESCAPE) { module.setKey("NONE"); - keybindText.displayValue = "none"; + keybindText.setText("none"); keybindText.focused = false; // re-open the hud editor final HudEditorModule hudEditorModule = (HudEditorModule) Seppuku.INSTANCE.getModuleManager().find(HudEditorModule.class); @@ -474,7 +474,7 @@ public final class ModuleListComponent extends ResizableHudComponent { } else { String newKey = Keyboard.getKeyName(keyCode); module.setKey(newKey); - keybindText.displayValue = newKey.length() == 1 /* is letter */ ? newKey.substring(1) : newKey.toLowerCase(); + keybindText.setText(newKey.length() == 1 /* is letter */ ? newKey.substring(1) : newKey.toLowerCase()); keybindText.focused = false; } } @@ -574,8 +574,8 @@ public final class ModuleListComponent extends ResizableHudComponent { valueText.returnListener = new ComponentListener() { @Override public void onComponentEvent() { - if (value.getEnum(valueText.displayValue) != -1) { - value.setEnumValue(valueText.displayValue); + if (value.getEnum(valueText.getText()) != -1) { + value.setEnumValue(valueText.getText()); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); // save configs Seppuku.INSTANCE.getEventManager().dispatchEvent(new EventUIValueChanged(value)); } else { @@ -596,8 +596,8 @@ public final class ModuleListComponent extends ResizableHudComponent { valueText.returnListener = new ComponentListener() { @Override public void onComponentEvent() { - if (valueText.displayValue.length() > 0) { - value.setValue(valueText.displayValue); + if (valueText.getText().length() > 0) { + value.setValue(valueText.getText()); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); // save configs Seppuku.INSTANCE.getEventManager().dispatchEvent(new EventUIValueChanged(value)); } else { @@ -640,7 +640,7 @@ public final class ModuleListComponent extends ResizableHudComponent { @Override public void onComponentEvent() { final Regex regex = (Regex) value.getValue(); - regex.setPatternString(valueText.displayValue); + regex.setPatternString(valueText.getText()); if(regex.getPattern() == null) Seppuku.INSTANCE.logfChat("%s - %s: Invalid or empty regular expression; no input will match with pattern.", module.getDisplayName(), value.getName()); Seppuku.INSTANCE.getConfigManager().save(ModuleConfig.class); // save configs diff --git a/src/main/java/me/rigamortis/seppuku/impl/module/render/StorageESPModule.java b/src/main/java/me/rigamortis/seppuku/impl/module/render/StorageESPModule.java index 7ea2cd0..922b333 100644 --- a/src/main/java/me/rigamortis/seppuku/impl/module/render/StorageESPModule.java +++ b/src/main/java/me/rigamortis/seppuku/impl/module/render/StorageESPModule.java @@ -251,8 +251,7 @@ public final class StorageESPModule extends Module { int baseColor; if (this.tracerStorageColor.getValue()) { baseColor = this.getBaseColor(te); - } - else { + } else { baseColor = this.tracerColor.getValue().getRGB(); }