diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/virtualkeyboard/clickhandler/DefaultScreenClickHandler.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/virtualkeyboard/clickhandler/DefaultScreenClickHandler.java index 647fbb7..78842e2 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/virtualkeyboard/clickhandler/DefaultScreenClickHandler.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/virtualkeyboard/clickhandler/DefaultScreenClickHandler.java @@ -7,7 +7,6 @@ import net.minecraft.client.gui.ParentElement; import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; -import net.minecraft.client.gui.widget.TextFieldWidget; import org.lwjgl.glfw.GLFW; import java.util.ArrayList; @@ -23,25 +22,25 @@ public class DefaultScreenClickHandler extends AbstractScreenClickHandler {} + default -> { + } } } - private TextFieldWidget findClickedTextField(Screen screen, double mouseX, double mouseY) { - for (Element element : screen.children()) { - if (element instanceof TextFieldWidget textField) { + + private TextFieldWrapper findClickedTextField(List elements, double mouseX, double mouseY) { + for (Element element : elements) { + if (TextFieldWrapper.isValidTextField(element)) { + TextFieldWrapper textField = new TextFieldWrapper(element); if (textField.isMouseOver(mouseX, mouseY) && textField.isFocused()) { return textField; } } + + if (element instanceof ParentElement parentElement) { + TextFieldWrapper found = findClickedTextField(parentElement.children(), mouseX, mouseY); + if (found != null) { + return found; + } + } } - // not hovering over a text field return null; } @@ -78,58 +86,57 @@ public class DefaultScreenClickHandler extends AbstractScreenClickHandler calculatePathToElement(Element parent, Element target) { - if (parent instanceof ParentElement parentElement) { - List children = parentElement.children(); + if (!(parent instanceof ParentElement parentElement)) { + return null; + } - // check direct children first - for (int i = 0; i < children.size(); i++) { - if (children.get(i) == target) { - // found it, return the path to this element - return Collections.singletonList(i); - } + List children = parentElement.children(); + + for (int i = 0; i < children.size(); i++) { + Element child = children.get(i); + + if (child == target) { + return Collections.singletonList(i); } - // check each child's children - for (int i = 0; i < children.size(); i++) { - if (children.get(i) instanceof ParentElement childParent) { - List subPath = calculatePathToElement(childParent, target); - if (subPath != null) { - // found in this subtree, prepend current index - List fullPath = new ArrayList<>(); - fullPath.add(i); - fullPath.addAll(subPath); - return fullPath; - } + if (child instanceof ParentElement) { + List subPath = calculatePathToElement(child, target); + if (subPath != null) { + List fullPath = new ArrayList<>(subPath.size() + 1); + fullPath.add(i); + fullPath.addAll(subPath); + return fullPath; } } } - // Not found return null; } - protected TextFieldWidget findTextFieldByPath(Element parent, List path) { + protected TextFieldWrapper findTextFieldByPath(Element parent, List path) { if (path == null || path.isEmpty()) { return null; } - if (parent instanceof ParentElement parentElement) { - List children = parentElement.children(); - int index = path.getFirst(); + if (!(parent instanceof ParentElement parentElement)) { + return null; + } - if (index >= 0 && index < children.size()) { - Element child = children.get(index); + List children = parentElement.children(); + int index = path.get(0); - if (path.size() == 1) { - // This should be our target - return (child instanceof TextFieldWidget) ? (TextFieldWidget) child : null; - } else { - // Continue traversing - if (child instanceof ParentElement) { - return findTextFieldByPath(child, path.subList(1, path.size())); - } - } - } + if (index < 0 || index >= children.size()) { + return null; + } + + Element child = children.get(index); + + if (path.size() == 1) { + return TextFieldWrapper.isValidTextField(child) ? new TextFieldWrapper(child) : null; + } + + if (child instanceof ParentElement) { + return findTextFieldByPath(child, path.subList(1, path.size())); } return null; diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/virtualkeyboard/clickhandler/TextFieldWrapper.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/virtualkeyboard/clickhandler/TextFieldWrapper.java new file mode 100644 index 0000000..f1190cb --- /dev/null +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/virtualkeyboard/clickhandler/TextFieldWrapper.java @@ -0,0 +1,77 @@ +package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler; + +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.widget.TextFieldWidget; +import org.thinkingstudio.obsidianui.widget.text.SpruceTextFieldWidget; + +public record TextFieldWrapper(Object textField) { + + public TextFieldWrapper { + if (!isValidTextField(textField)) { + throw new IllegalArgumentException("Type " + textField.getClass() + " is not marked as a valid text field"); + } + } + + Element asElement() { + return (Element) textField; + } + + String getText() { + switch (textField) { + case SpruceTextFieldWidget spruceTextField -> { + return spruceTextField.getText(); + } + case TextFieldWidget vanillaTextField -> { + return vanillaTextField.getText(); + } + default -> { + return null; + } + } + } + + void setText(String text) { + switch (textField) { + case SpruceTextFieldWidget spruceTextField -> { + spruceTextField.setText(text); + } + case TextFieldWidget vanillaTextField -> { + vanillaTextField.setText(text); + } + default -> { + } + } + } + + boolean isMouseOver(double mouseX, double mouseY) { + switch (textField) { + case SpruceTextFieldWidget spruceTextField -> { + return spruceTextField.isMouseOver(mouseX, mouseY); + } + case TextFieldWidget vanillaTextField -> { + return vanillaTextField.isMouseOver(mouseX, mouseY); + } + default -> { + return false; + } + } + } + + boolean isFocused() { + switch (textField) { + case SpruceTextFieldWidget spruceTextField -> { + return spruceTextField.isFocused(); + } + case TextFieldWidget vanillaTextField -> { + return vanillaTextField.isFocused(); + } + default -> { + return false; + } + } + } + + static boolean isValidTextField(Object textField) { + return textField instanceof TextFieldWidget || textField instanceof SpruceTextFieldWidget; + } +}