291 lines
8.1 KiB
Java
291 lines
8.1 KiB
Java
package net.minecraft.client.gui.font;
|
|
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Predicate;
|
|
import java.util.function.Supplier;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.ChatFormatting;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.StringSplitter;
|
|
import net.minecraft.client.gui.screens.Screen;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.StringUtil;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class TextFieldHelper {
|
|
private final Supplier<String> getMessageFn;
|
|
private final Consumer<String> setMessageFn;
|
|
private final Supplier<String> getClipboardFn;
|
|
private final Consumer<String> setClipboardFn;
|
|
private final Predicate<String> stringValidator;
|
|
private int cursorPos;
|
|
private int selectionPos;
|
|
|
|
public TextFieldHelper(
|
|
Supplier<String> getMessage, Consumer<String> setMessage, Supplier<String> getClipboard, Consumer<String> setClipboard, Predicate<String> stringValidator
|
|
) {
|
|
this.getMessageFn = getMessage;
|
|
this.setMessageFn = setMessage;
|
|
this.getClipboardFn = getClipboard;
|
|
this.setClipboardFn = setClipboard;
|
|
this.stringValidator = stringValidator;
|
|
this.setCursorToEnd();
|
|
}
|
|
|
|
public static Supplier<String> createClipboardGetter(Minecraft minecraft) {
|
|
return () -> getClipboardContents(minecraft);
|
|
}
|
|
|
|
public static String getClipboardContents(Minecraft minecraft) {
|
|
return ChatFormatting.stripFormatting(minecraft.keyboardHandler.getClipboard().replaceAll("\\r", ""));
|
|
}
|
|
|
|
public static Consumer<String> createClipboardSetter(Minecraft minecraft) {
|
|
return string -> setClipboardContents(minecraft, string);
|
|
}
|
|
|
|
public static void setClipboardContents(Minecraft minecraft, String text) {
|
|
minecraft.keyboardHandler.setClipboard(text);
|
|
}
|
|
|
|
public boolean charTyped(char character) {
|
|
if (StringUtil.isAllowedChatCharacter(character)) {
|
|
this.insertText((String)this.getMessageFn.get(), Character.toString(character));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public boolean keyPressed(int key) {
|
|
if (Screen.isSelectAll(key)) {
|
|
this.selectAll();
|
|
return true;
|
|
} else if (Screen.isCopy(key)) {
|
|
this.copy();
|
|
return true;
|
|
} else if (Screen.isPaste(key)) {
|
|
this.paste();
|
|
return true;
|
|
} else if (Screen.isCut(key)) {
|
|
this.cut();
|
|
return true;
|
|
} else {
|
|
TextFieldHelper.CursorStep cursorStep = Screen.hasControlDown() ? TextFieldHelper.CursorStep.WORD : TextFieldHelper.CursorStep.CHARACTER;
|
|
if (key == 259) {
|
|
this.removeFromCursor(-1, cursorStep);
|
|
return true;
|
|
} else {
|
|
if (key == 261) {
|
|
this.removeFromCursor(1, cursorStep);
|
|
} else {
|
|
if (key == 263) {
|
|
this.moveBy(-1, Screen.hasShiftDown(), cursorStep);
|
|
return true;
|
|
}
|
|
|
|
if (key == 262) {
|
|
this.moveBy(1, Screen.hasShiftDown(), cursorStep);
|
|
return true;
|
|
}
|
|
|
|
if (key == 268) {
|
|
this.setCursorToStart(Screen.hasShiftDown());
|
|
return true;
|
|
}
|
|
|
|
if (key == 269) {
|
|
this.setCursorToEnd(Screen.hasShiftDown());
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private int clampToMsgLength(int textIndex) {
|
|
return Mth.clamp(textIndex, 0, ((String)this.getMessageFn.get()).length());
|
|
}
|
|
|
|
private void insertText(String text, String clipboardText) {
|
|
if (this.selectionPos != this.cursorPos) {
|
|
text = this.deleteSelection(text);
|
|
}
|
|
|
|
this.cursorPos = Mth.clamp(this.cursorPos, 0, text.length());
|
|
String string = new StringBuilder(text).insert(this.cursorPos, clipboardText).toString();
|
|
if (this.stringValidator.test(string)) {
|
|
this.setMessageFn.accept(string);
|
|
this.selectionPos = this.cursorPos = Math.min(string.length(), this.cursorPos + clipboardText.length());
|
|
}
|
|
}
|
|
|
|
public void insertText(String text) {
|
|
this.insertText((String)this.getMessageFn.get(), text);
|
|
}
|
|
|
|
private void resetSelectionIfNeeded(boolean keepSelection) {
|
|
if (!keepSelection) {
|
|
this.selectionPos = this.cursorPos;
|
|
}
|
|
}
|
|
|
|
public void moveBy(int direction, boolean keepSelection, TextFieldHelper.CursorStep cursorStep) {
|
|
switch (cursorStep) {
|
|
case CHARACTER:
|
|
this.moveByChars(direction, keepSelection);
|
|
break;
|
|
case WORD:
|
|
this.moveByWords(direction, keepSelection);
|
|
}
|
|
}
|
|
|
|
public void moveByChars(int direction) {
|
|
this.moveByChars(direction, false);
|
|
}
|
|
|
|
public void moveByChars(int direction, boolean keepSelection) {
|
|
this.cursorPos = Util.offsetByCodepoints((String)this.getMessageFn.get(), this.cursorPos, direction);
|
|
this.resetSelectionIfNeeded(keepSelection);
|
|
}
|
|
|
|
public void moveByWords(int direction) {
|
|
this.moveByWords(direction, false);
|
|
}
|
|
|
|
public void moveByWords(int direction, boolean keepSelection) {
|
|
this.cursorPos = StringSplitter.getWordPosition((String)this.getMessageFn.get(), direction, this.cursorPos, true);
|
|
this.resetSelectionIfNeeded(keepSelection);
|
|
}
|
|
|
|
public void removeFromCursor(int direction, TextFieldHelper.CursorStep step) {
|
|
switch (step) {
|
|
case CHARACTER:
|
|
this.removeCharsFromCursor(direction);
|
|
break;
|
|
case WORD:
|
|
this.removeWordsFromCursor(direction);
|
|
}
|
|
}
|
|
|
|
public void removeWordsFromCursor(int direction) {
|
|
int i = StringSplitter.getWordPosition((String)this.getMessageFn.get(), direction, this.cursorPos, true);
|
|
this.removeCharsFromCursor(i - this.cursorPos);
|
|
}
|
|
|
|
public void removeCharsFromCursor(int direction) {
|
|
String string = (String)this.getMessageFn.get();
|
|
if (!string.isEmpty()) {
|
|
String string2;
|
|
if (this.selectionPos != this.cursorPos) {
|
|
string2 = this.deleteSelection(string);
|
|
} else {
|
|
int i = Util.offsetByCodepoints(string, this.cursorPos, direction);
|
|
int j = Math.min(i, this.cursorPos);
|
|
int k = Math.max(i, this.cursorPos);
|
|
string2 = new StringBuilder(string).delete(j, k).toString();
|
|
if (direction < 0) {
|
|
this.selectionPos = this.cursorPos = j;
|
|
}
|
|
}
|
|
|
|
this.setMessageFn.accept(string2);
|
|
}
|
|
}
|
|
|
|
public void cut() {
|
|
String string = (String)this.getMessageFn.get();
|
|
this.setClipboardFn.accept(this.getSelected(string));
|
|
this.setMessageFn.accept(this.deleteSelection(string));
|
|
}
|
|
|
|
public void paste() {
|
|
this.insertText((String)this.getMessageFn.get(), (String)this.getClipboardFn.get());
|
|
this.selectionPos = this.cursorPos;
|
|
}
|
|
|
|
public void copy() {
|
|
this.setClipboardFn.accept(this.getSelected((String)this.getMessageFn.get()));
|
|
}
|
|
|
|
public void selectAll() {
|
|
this.selectionPos = 0;
|
|
this.cursorPos = ((String)this.getMessageFn.get()).length();
|
|
}
|
|
|
|
private String getSelected(String text) {
|
|
int i = Math.min(this.cursorPos, this.selectionPos);
|
|
int j = Math.max(this.cursorPos, this.selectionPos);
|
|
return text.substring(i, j);
|
|
}
|
|
|
|
private String deleteSelection(String text) {
|
|
if (this.selectionPos == this.cursorPos) {
|
|
return text;
|
|
} else {
|
|
int i = Math.min(this.cursorPos, this.selectionPos);
|
|
int j = Math.max(this.cursorPos, this.selectionPos);
|
|
String string = text.substring(0, i) + text.substring(j);
|
|
this.selectionPos = this.cursorPos = i;
|
|
return string;
|
|
}
|
|
}
|
|
|
|
public void setCursorToStart() {
|
|
this.setCursorToStart(false);
|
|
}
|
|
|
|
public void setCursorToStart(boolean keepSelection) {
|
|
this.cursorPos = 0;
|
|
this.resetSelectionIfNeeded(keepSelection);
|
|
}
|
|
|
|
public void setCursorToEnd() {
|
|
this.setCursorToEnd(false);
|
|
}
|
|
|
|
public void setCursorToEnd(boolean keepSelection) {
|
|
this.cursorPos = ((String)this.getMessageFn.get()).length();
|
|
this.resetSelectionIfNeeded(keepSelection);
|
|
}
|
|
|
|
public int getCursorPos() {
|
|
return this.cursorPos;
|
|
}
|
|
|
|
public void setCursorPos(int textIndex) {
|
|
this.setCursorPos(textIndex, true);
|
|
}
|
|
|
|
public void setCursorPos(int textIndex, boolean keepSelection) {
|
|
this.cursorPos = this.clampToMsgLength(textIndex);
|
|
this.resetSelectionIfNeeded(keepSelection);
|
|
}
|
|
|
|
public int getSelectionPos() {
|
|
return this.selectionPos;
|
|
}
|
|
|
|
public void setSelectionPos(int textIndex) {
|
|
this.selectionPos = this.clampToMsgLength(textIndex);
|
|
}
|
|
|
|
public void setSelectionRange(int selectionStart, int selectionEnd) {
|
|
int i = ((String)this.getMessageFn.get()).length();
|
|
this.cursorPos = Mth.clamp(selectionStart, 0, i);
|
|
this.selectionPos = Mth.clamp(selectionEnd, 0, i);
|
|
}
|
|
|
|
public boolean isSelecting() {
|
|
return this.cursorPos != this.selectionPos;
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static enum CursorStep {
|
|
CHARACTER,
|
|
WORD;
|
|
}
|
|
}
|