From 36151e3a460608e4977356c3f1ee0f947c16d78c Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 28 Dec 2022 11:30:12 +0100 Subject: [PATCH] Add selection and copy, paste and cut --- .../lexer/TokenTypeColors.java | 1 + .../screen/ScriptEditScreen.java | 271 ++++++++++++++---- 2 files changed, 224 insertions(+), 48 deletions(-) diff --git a/src/main/java/de/zonlykroks/advancedscripts/lexer/TokenTypeColors.java b/src/main/java/de/zonlykroks/advancedscripts/lexer/TokenTypeColors.java index e01fc89..71a5643 100644 --- a/src/main/java/de/zonlykroks/advancedscripts/lexer/TokenTypeColors.java +++ b/src/main/java/de/zonlykroks/advancedscripts/lexer/TokenTypeColors.java @@ -7,6 +7,7 @@ public class TokenTypeColors { } public static final int BACKGROUND = 0xFF1E1F22; + public static final int SELECTION = 0xFF23437F; public static final int OTHER = 0xFFFFFFFF; public static final int ERROR = 0xFFAA0000; diff --git a/src/main/java/de/zonlykroks/advancedscripts/screen/ScriptEditScreen.java b/src/main/java/de/zonlykroks/advancedscripts/screen/ScriptEditScreen.java index e4211d6..581bde6 100644 --- a/src/main/java/de/zonlykroks/advancedscripts/screen/ScriptEditScreen.java +++ b/src/main/java/de/zonlykroks/advancedscripts/screen/ScriptEditScreen.java @@ -13,6 +13,7 @@ import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.widget.PressableWidget; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.util.NarratorManager; +import net.minecraft.client.util.SelectionManager; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; @@ -25,10 +26,7 @@ import net.minecraft.text.Text; import net.minecraft.util.Hand; import org.apache.commons.lang3.mutable.MutableInt; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; public class ScriptEditScreen extends Screen { @@ -42,6 +40,9 @@ public class ScriptEditScreen extends Screen { private int cursorY = 0; private int cursorX = 0; + private int savedCursorY = -1; + private int savedCursorX = -1; + private int tickCounter; private int keyCode = -1; @@ -114,6 +115,17 @@ public class ScriptEditScreen extends Screen { } } + private void setClipboard(String clipboard) { + if (this.client != null) { + SelectionManager.setClipboard(this.client, clipboard); + } + + } + + private String getClipboard() { + return this.client != null ? SelectionManager.getClipboard(this.client) : ""; + } + @Override public void tick() { super.tick(); @@ -132,6 +144,12 @@ public class ScriptEditScreen extends Screen { int lineNumberLength = textRenderer.getWidth(lines.size() + ""); + boolean hasSelection = savedCursorY != -1 && savedCursorX != -1; + int minSelectionY = Math.min(cursorY, savedCursorY); + int maxSelectionY = Math.max(cursorY, savedCursorY); + int minSelectionX = minSelectionY == cursorY ? cursorX : savedCursorX; + int maxSelectionX = maxSelectionY == cursorY ? cursorX : savedCursorX; + int lineNumberText = scroll + 1; MutableInt lineNumber = new MutableInt(); TextHandler textHandler = this.textRenderer.getTextHandler(); @@ -147,8 +165,8 @@ public class ScriptEditScreen extends Screen { } // Line number + int height = this.textRenderer.getWrappedLinesHeight(s, this.width - 50 - lineNumberLength - 5); if (lineTooLong(s)) { - int height = this.textRenderer.getWrappedLinesHeight(s, this.width - 50 - lineNumberLength - 5); fill(matrices, 25 + lineNumberLength + 2, 25 + lineNumber.getValue() * 9, 25 + lineNumberLength + 3, 25 + lineNumber.getValue() * 9 + height, TokenTypeColors.ERROR); } this.textRenderer.draw(matrices, lineNumberText + "", 25 + lineNumberLength - textRenderer.getWidth(lineNumberText + ""), 25 + lineNumber.getValue() * 9, 0xFFFFFF); @@ -169,9 +187,37 @@ public class ScriptEditScreen extends Screen { String line = token.text.substring(start, end); int previousXIndex = currentXIndex.get(); currentXIndex.addAndGet(line.length()); + + if (hasSelection) { + int x1 = x.get(); + int x2 = x.get() + textRenderer.getWidth(line); + + if (finalI == minSelectionY) { + if (minSelectionX > currentXIndex.get()) { + x2 = 0; + } else if (minSelectionX <= currentXIndex.get() && minSelectionX >= previousXIndex) { + int startInLine = minSelectionX - previousXIndex; + x1 += textRenderer.getWidth(line.substring(0, startInLine)); + } + } + if (finalI == maxSelectionY) { + if (maxSelectionX < previousXIndex) { + x2 = 0; + } else if (maxSelectionX <= currentXIndex.get()) { + int endInLine = maxSelectionX - previousXIndex; + x2 = x.get() + textRenderer.getWidth(line.substring(0, endInLine)); + } + } + + if (finalI >= minSelectionY && finalI <= maxSelectionY && x2 > x1) { + fill(matrices, x1, y + 25, x2, y + 25 + 9, TokenTypeColors.SELECTION); + } + } + if (finalI == cursorY && currentXIndex.get() >= cursorX && previousXIndex <= cursorX) { drawCursor(matrices, x.get() + textRenderer.getWidth(line.substring(0, cursorX - previousXIndex)) - 1, 25 + y, isAtEndOfLine()); } + this.textRenderer.draw(matrices, line, x.get(), 25 + y, token.color); x.addAndGet(textRenderer.getWidth(line)); if (x.get() > this.width - 50 - lineNumberLength - 5) { @@ -206,35 +252,85 @@ public class ScriptEditScreen extends Screen { } private void key(int keyCode) { + if (Screen.isSelectAll(keyCode)) { + this.cursorX = 0; + this.cursorY = 0; + this.savedCursorX = lines.get(lines.size() - 1).length(); + this.savedCursorY = lines.size() - 1; + return; + } else if (Screen.isCopy(keyCode)) { + String copied = selection(false); + if (copied != null) { + setClipboard(copied); + } + return; + } else if (Screen.isPaste(keyCode)) { + String copied = getClipboard(); + if (copied != null) { + insert(copied); + } + return; + } else if (Screen.isCut(keyCode)) { + String copied = selection(true); + if (copied != null) { + setClipboard(copied); + } + return; + } + SelectionManager.SelectionType selectionType = Screen.hasControlDown() ? SelectionManager.SelectionType.WORD : SelectionManager.SelectionType.CHARACTER; + boolean valid = true; + int previousCursorX = cursorX; + int previousCursorY = cursorY; switch (keyCode) { case 257: case 335: + selection(true); newLine(); + valid = false; break; case 259: - backspace(); + if (selection(true) == null) backspace(selectionType); + valid = false; break; case 261: - delete(); + if (selection(true) == null) delete(selectionType); + valid = false; break; case 262: - moveCursor(1); + moveCursor(1, selectionType); + valid = Screen.hasShiftDown(); break; case 263: - moveCursor(-1); + moveCursor(-1, selectionType); + valid = Screen.hasShiftDown(); break; case 264: moveDown(); + valid = Screen.hasShiftDown(); break; case 265: moveUp(); + valid = Screen.hasShiftDown(); break; case 268: cursorX = 0; + valid = Screen.hasShiftDown(); break; case 269: cursorX = lines.get(cursorY).length(); + valid = Screen.hasShiftDown(); break; + default: + break; + } + if (valid) { + if (Screen.hasShiftDown() && savedCursorX == -1 && savedCursorY == -1) { + savedCursorX = previousCursorX; + savedCursorY = previousCursorY; + } + } else { + savedCursorY = -1; + savedCursorX = -1; } } @@ -260,21 +356,78 @@ public class ScriptEditScreen extends Screen { if (super.charTyped(chr, modifiers)) { return true; } - if (insert(chr, modifiers)) { - return true; - } - return true; + selection(true); + boolean valid = insert(chr + ""); + savedCursorY = -1; + savedCursorX = -1; + return valid; } - private boolean insert(char chr, int modifiers) { - String line = lines.get(cursorY); - if (cursorX == line.length()) { - line += chr; - } else { - line = line.substring(0, cursorX) + chr + line.substring(cursorX); + private String selection(boolean remove) { + if (savedCursorX == -1 || savedCursorY == -1) { + return null; + } + int minSelectionY = Math.min(savedCursorY, cursorY); + int maxSelectionY = Math.max(savedCursorY, cursorY); + int minSelectionX = minSelectionY == cursorY ? cursorX : savedCursorX; + int maxSelectionX = maxSelectionY == cursorY ? cursorX : savedCursorX; + + StringBuilder builder = new StringBuilder(); + for (int i = minSelectionY; i <= maxSelectionY; i++) { + String line = lines.get(i); + if (i == minSelectionY && i == maxSelectionY) { + builder.append(line, minSelectionX, maxSelectionX); + } else if (i == minSelectionY) { + builder.append(line, minSelectionX, line.length()); + } else if (i == maxSelectionY) { + builder.append(line, 0, Math.min(maxSelectionX, line.length())); + } else { + builder.append(line); + } + if (i != maxSelectionY) { + builder.append("\n"); + } + } + if (remove) { + for (int i = maxSelectionY; i >= minSelectionY; i--) { + String line = lines.get(i); + if (i == minSelectionY && i == maxSelectionY) { + lines.set(i, line.substring(0, minSelectionX) + line.substring(maxSelectionX)); + } else if (i == minSelectionY) { + lines.set(i, line.substring(0, minSelectionX)); + } else if (i == maxSelectionY) { + lines.set(i, line.substring(Math.min(maxSelectionX, line.length()))); + } else { + lines.remove(i); + } + } + if (minSelectionY != maxSelectionY) { + lines.set(minSelectionY, lines.get(minSelectionY) + lines.get(minSelectionY + 1)); + lines.remove(minSelectionY + 1); + } + cursorX = minSelectionX; + cursorY = minSelectionY; + savedCursorX = -1; + savedCursorY = -1; + } + return builder.toString(); + } + + private boolean insert(String s) { + String[] split = s.split("\n"); + for (int i = 0; i < split.length; i++) { + String line = lines.get(cursorY); + if (cursorX == line.length()) { + line += split[i]; + } else { + line = line.substring(0, cursorX) + split[i] + line.substring(cursorX); + } + lines.set(cursorY, line); + cursorX += split[i].length(); + if (i != split.length - 1) { + newLine(); + } } - lines.set(cursorY, line); - cursorX++; return true; } @@ -289,58 +442,80 @@ public class ScriptEditScreen extends Screen { return true; } - private boolean backspace() { + private boolean backspace(SelectionManager.SelectionType selectionType) { if (cursorX == 0) { if (cursorY == 0) { return true; } - String line = lines.get(cursorY); - String prevLine = lines.get(cursorY - 1); - lines.set(cursorY - 1, prevLine + line); - lines.remove(cursorY); + String previousLine = lines.get(cursorY - 1); + lines.set(cursorY - 1, lines.get(cursorY - 1) + lines.remove(cursorY)); cursorY--; - cursorX = prevLine.length(); + cursorX = previousLine.length(); } else { String line = lines.get(cursorY); - line = line.substring(0, cursorX - 1) + line.substring(cursorX); + int remove = selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, -1); + line = line.substring(0, cursorX - remove) + line.substring(cursorX); lines.set(cursorY, line); - cursorX--; + cursorX -= remove; } return true; } - private boolean delete() { - String line = lines.get(cursorY); - if (cursorX == line.length()) { + private boolean delete(SelectionManager.SelectionType selectionType) { + if (cursorX == lines.get(cursorY).length()) { if (cursorY == lines.size() - 1) { return true; } String nextLine = lines.get(cursorY + 1); - lines.set(cursorY, line + nextLine); - lines.remove(cursorY + 1); + lines.remove(cursorY); + lines.set(cursorY, lines.get(cursorY) + nextLine); } else { - line = line.substring(0, cursorX) + line.substring(cursorX + 1); + String line = lines.get(cursorY); + int remove = selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, 1); + line = line.substring(0, cursorX) + line.substring(cursorX + remove); lines.set(cursorY, line); } return true; } - private boolean moveCursor(int offset) { + private int getWordLength(String line, int cursorX, int direction) { + int i = cursorX; + while (i >= 0 && i < line.length()) { + char c = line.charAt(i); + if (Character.isLetterOrDigit(c)) { + i += direction; + } else { + break; + } + } + return Math.abs(i - cursorX); + } + + private boolean moveCursor(int offset, SelectionManager.SelectionType selectionType) { + if (offset == 0) { + return true; + } String line = lines.get(cursorY); - if (cursorX + offset < 0) { - if (cursorY == 0) { - return true; + if (offset > 0) { + if (cursorX == line.length()) { + if (cursorY == lines.size() - 1) { + return true; + } + cursorY++; + cursorX = 0; + } else { + cursorX += selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, 1); } - cursorY--; - cursorX = lines.get(cursorY).length(); - } else if (cursorX + offset > line.length()) { - if (cursorY == lines.size() - 1) { - return true; - } - cursorY++; - cursorX = 0; } else { - cursorX += offset; + if (cursorX == 0) { + if (cursorY == 0) { + return true; + } + cursorY--; + cursorX = lines.get(cursorY).length(); + } else { + cursorX -= selectionType == SelectionManager.SelectionType.CHARACTER ? 1 : getWordLength(line, cursorX, -1); + } } return true; }