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;
 | |
| 	}
 | |
| }
 |