From bfa560966e6f01a1a8b8493cfb3151f0cdb6a782 Mon Sep 17 00:00:00 2001 From: Falkreon Date: Sun, 18 Aug 2019 02:46:25 -0500 Subject: initial text control impl --- .../cotton/gui/CottonScreenController.java | 57 +++ .../github/cottonmc/cotton/gui/GuiDescription.java | 20 + .../cotton/gui/client/ClientCottonScreen.java | 42 ++ .../cottonmc/cotton/gui/client/CottonScreen.java | 23 +- .../gui/client/LightweightGuiDescription.java | 29 ++ .../cotton/gui/client/modmenu/ConfigGui.java | 5 + .../cottonmc/cotton/gui/widget/WItemSlot.java | 1 + .../github/cottonmc/cotton/gui/widget/WPanel.java | 3 +- .../cottonmc/cotton/gui/widget/WTextField.java | 504 +++++++++++++++++++++ .../github/cottonmc/cotton/gui/widget/WWidget.java | 106 +++-- 10 files changed, 739 insertions(+), 51 deletions(-) create mode 100644 src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java (limited to 'src') diff --git a/src/main/java/io/github/cottonmc/cotton/gui/CottonScreenController.java b/src/main/java/io/github/cottonmc/cotton/gui/CottonScreenController.java index 3393cdd..a063424 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/CottonScreenController.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/CottonScreenController.java @@ -41,6 +41,8 @@ public class CottonScreenController extends CraftingContainer impleme protected int titleColor = WLabel.DEFAULT_TEXT_COLOR; protected int darkTitleColor = WLabel.DEFAULT_DARKMODE_TEXT_COLOR; + protected WWidget focus; + public CottonScreenController(RecipeType recipeType, int syncId, PlayerInventory playerInventory) { super(null, syncId); this.blockInventory = null; @@ -290,9 +292,36 @@ public class CottonScreenController extends CraftingContainer impleme } public void doClick(int x, int y, int button) { + System.out.println("Doing click"); + if (focus!=null) { + int wx = focus.getAbsoluteX(); + int wy = focus.getAbsoluteY(); + + if (x>=wx && x=wy && y impleme } //} //} + + @Override + public boolean isFocused(WWidget widget) { + return focus == widget; + } + + @Override + public WWidget getFocus() { + return focus; + } + + @Override + public void requestFocus(WWidget widget) { + //TODO: Are there circumstances where focus can't be stolen? + if (focus==widget) return; //Nothing happens if we're already focused + if (!widget.canFocus()) return; //This is kind of a gotcha but needs to happen + if (focus!=null) focus.onFocusLost(); + focus = widget; + focus.onFocusGained(); + } + + @Override + public void releaseFocus(WWidget widget) { + if (focus==widget) { + focus = null; + widget.onFocusLost(); + } + } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java b/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java index 2b2e0d9..c494016 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/GuiDescription.java @@ -3,6 +3,7 @@ package io.github.cottonmc.cotton.gui; import javax.annotation.Nullable; import io.github.cottonmc.cotton.gui.widget.WPanel; +import io.github.cottonmc.cotton.gui.widget.WWidget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.container.PropertyDelegate; @@ -13,13 +14,32 @@ public interface GuiDescription { public GuiDescription setRootPanel(WPanel panel); public GuiDescription setTitleColor(int color); + + /** Sets the object which manages the integer properties used by WBars */ public GuiDescription setPropertyDelegate(PropertyDelegate delegate); + + /** Typical users won't call this. This adds a Slot to Container/Controller-based guis, and does nothing on lightweight guis. */ public void addSlotPeer(ValidatedSlot slot); + /** Guis should use this method to add clientside styles and BackgroundPainters to their controls */ @Environment(EnvType.CLIENT) public void addPainters(); + /** Gets the object which manages the integer properties used by WBars and such. */ @Nullable public PropertyDelegate getPropertyDelegate(); + /** Tests whether the widget is the currently-focused one. */ + public boolean isFocused(WWidget widget); + + /** Gets the currently-focused WWidget. May be null. */ + @Nullable + public WWidget getFocus(); + + /** Notifies this gui that the widget waants to acquire focus. */ + public void requestFocus(WWidget widget); + + /** Notifies this gui that the widget wants to give up its hold over focus. */ + public void releaseFocus(WWidget widget); + } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/ClientCottonScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/ClientCottonScreen.java index deecbee..90b6273 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/ClientCottonScreen.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/ClientCottonScreen.java @@ -4,6 +4,7 @@ import io.github.cottonmc.cotton.gui.GuiDescription; import io.github.cottonmc.cotton.gui.widget.WPanel; import io.github.cottonmc.cotton.gui.widget.WWidget; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; @@ -92,6 +93,20 @@ public class ClientCottonScreen extends Screen { @Override public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { + WWidget focus = description.getFocus(); + if (focus!=null) { + + int wx = focus.getAbsoluteX(); + int wy = focus.getAbsoluteY(); + + if (mouseX>=wx && mouseX=wy && mouseY=width || containerY>=height) return result; lastResponder = description.getRootPanel().onMouseDown(containerX, containerY, mouseButton); + return result; } @@ -128,4 +144,30 @@ public class ClientCottonScreen extends Screen { description.getRootPanel().onMouseDrag(containerX, containerY, mouseButton); return result; } + + @Override + public boolean charTyped(char ch, int keyCode) { + if (description.getFocus()==null) return false; + description.getFocus().onCharTyped(ch); + return true; + } + + @Override + public boolean keyPressed(int ch, int keyCode, int modifiers) { + if (description.getFocus()==null) return false; + description.getFocus().onKeyPressed(keyCode, modifiers); + return true; + } + + @Override + public boolean keyReleased(int ch, int keyCode, int modifiers) { + if (description.getFocus()==null) return false; + description.getFocus().onKeyReleased(keyCode, modifiers); + return true; + } + + @Override + public Element getFocused() { + return this; + } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java index 4caa477..445d612 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonScreen.java @@ -14,6 +14,7 @@ public class CottonScreen extends AbstractCont protected CottonScreenController container; public static final int PADDING = 8; protected WWidget lastResponder = null; + protected WWidget focus = null; public CottonScreen(T container, PlayerEntity player) { super(container, player.inventory, new LiteralText("")); @@ -72,10 +73,24 @@ public class CottonScreen extends AbstractCont } @Override - public boolean charTyped(char typedChar, int keyCode) { - if (MinecraftClient.getInstance().options.keyInventory.matchesKey(keyCode, keyCode)); - - return super.charTyped(typedChar, keyCode); + public boolean charTyped(char ch, int keyCode) { + if (container.getFocus()==null) return false; + container.getFocus().onCharTyped(ch); + return true; + } + + @Override + public boolean keyPressed(int ch, int keyCode, int modifiers) { + if (container.getFocus()==null) return false; + container.getFocus().onKeyPressed(keyCode, modifiers); + return true; + } + + @Override + public boolean keyReleased(int ch, int keyCode, int modifiers) { + if (container.getFocus()==null) return false; + container.getFocus().onKeyReleased(keyCode, modifiers); + return true; } @Override diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java b/src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java index 9658fb5..6284c2f 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/LightweightGuiDescription.java @@ -7,6 +7,7 @@ import io.github.cottonmc.cotton.gui.ValidatedSlot; import io.github.cottonmc.cotton.gui.widget.WGridPanel; import io.github.cottonmc.cotton.gui.widget.WLabel; import io.github.cottonmc.cotton.gui.widget.WPanel; +import io.github.cottonmc.cotton.gui.widget.WWidget; import net.minecraft.container.PropertyDelegate; /** @@ -17,6 +18,7 @@ public class LightweightGuiDescription implements GuiDescription { protected int titleColor = WLabel.DEFAULT_TEXT_COLOR; protected int darkmodeTitleColor = WLabel.DEFAULT_DARKMODE_TEXT_COLOR; protected PropertyDelegate propertyDelegate; + protected WWidget focus; @Override public WPanel getRootPanel() { @@ -64,4 +66,31 @@ public class LightweightGuiDescription implements GuiDescription { return this; } + @Override + public boolean isFocused(WWidget widget) { + return widget == focus; + } + + @Override + public WWidget getFocus() { + return focus; + } + + @Override + public void requestFocus(WWidget widget) { + //TODO: Are there circumstances where focus can't be stolen? + if (focus==widget) return; //Nothing happens if we're already focused + if (!widget.canFocus()) return; //This is kind of a gotcha but needs to happen + if (focus!=null) focus.onFocusLost(); + focus = widget; + focus.onFocusGained(); + } + + @Override + public void releaseFocus(WWidget widget) { + if (focus==widget) { + focus = null; + widget.onFocusLost(); + } + } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java b/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java index 8b3c3ee..15c39dd 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java @@ -5,6 +5,7 @@ import io.github.cottonmc.cotton.gui.client.LibGuiClient; import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription; import io.github.cottonmc.cotton.gui.widget.WButton; import io.github.cottonmc.cotton.gui.widget.WGridPanel; +import io.github.cottonmc.cotton.gui.widget.WTextField; import io.github.cottonmc.cotton.gui.widget.WToggleButton; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; @@ -28,6 +29,8 @@ public class ConfigGui extends LightweightGuiDescription { root.add(new WKirbSprite(), 5, 4); + root.add(new WTextField(), 0, 3, 5, 1); + WButton doneButton = new WButton(new TranslatableText("gui.done")); doneButton.setOnClick(()->{ MinecraftClient.getInstance().openScreen(previous); @@ -36,5 +39,7 @@ public class ConfigGui extends LightweightGuiDescription { root.setBackgroundPainter(BackgroundPainter.VANILLA); root.setSize(7*18, 6*18); + + root.validate(this); } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java index 4287941..64d4171 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java @@ -87,6 +87,7 @@ public class WItemSlot extends WWidget { @Override public void createPeers(GuiDescription c) { + super.createPeers(c); peers.clear(); int index = startIndex; diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java index a79f3be..630494f 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java @@ -16,6 +16,7 @@ public class WPanel extends WWidget { @Override public void createPeers(GuiDescription c) { + super.createPeers(c); for(WWidget child : children) { child.createPeers(c); } @@ -116,7 +117,7 @@ public class WPanel extends WWidget { @Override public void validate(GuiDescription c) { layout(); - createPeers(c); + if (c!=null) createPeers(c); } @Environment(EnvType.CLIENT) diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java new file mode 100644 index 0000000..d1aa437 --- /dev/null +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java @@ -0,0 +1,504 @@ +package io.github.cottonmc.cotton.gui.widget; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +import javax.annotation.Nullable; + +import org.lwjgl.glfw.GLFW; + +import io.github.cottonmc.cotton.gui.client.BackgroundPainter; +import io.github.cottonmc.cotton.gui.client.ScreenDrawing; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; + +public class WTextField extends WWidget { + + protected String text = ""; + protected int maxLength = 16; + protected int focusedTicks = 0; + protected boolean focused = false; + protected boolean editable = true; + + protected int enabledColor = 0xE0E0E0; + protected int uneditableColor = 0x707070; + + @Nullable + protected String suggestion = null; + + protected int cursor = 0; + + protected Consumer onChanged; + + protected Predicate textPredicate; + + @Environment(EnvType.CLIENT) + @Nullable + protected BackgroundPainter backgroundPainter; + + public WTextField() { + } + + public WTextField(Text suggestion) { + this.suggestion = suggestion.asString(); + } + + public void setText(String s) { + if (this.textPredicate.test(s)) { + this.text = (s.length()>maxLength) ? s.substring(0,maxLength) : s; + if (onChanged!=null) onChanged.accept(this.text); + } + } + + public String getText() { + return this.text; + } + + @Override + public boolean canResize() { + return true; + } + + /* + public String getSelectedText() { + int start = this.cursorMax < this.cursorMin ? this.cursorMax : this.cursorMin; + int end = this.cursorMax < this.cursorMin ? this.cursorMin : this.cursorMax; + return this.text.substring(start, end); + }*/ + + /* + //This would seem to insert or paste text in the vanilla control + public void addText(String string_1) { + String string_2 = ""; + String string_3 = SharedConstants.stripInvalidChars(string_1); + int int_1 = this.cursorMax < this.cursorMin ? this.cursorMax : this.cursorMin; + int int_2 = this.cursorMax < this.cursorMin ? this.cursorMin : this.cursorMax; + int int_3 = this.maxLength - this.text.length() - (int_1 - int_2); + if (!this.text.isEmpty()) { + string_2 = string_2 + this.text.substring(0, int_1); + } + + int int_5; + if (int_3 < string_3.length()) { + string_2 = string_2 + string_3.substring(0, int_3); + int_5 = int_3; + } else { + string_2 = string_2 + string_3; + int_5 = string_3.length(); + } + + if (!this.text.isEmpty() && int_2 < this.text.length()) { + string_2 = string_2 + this.text.substring(int_2); + } + + if (this.textPredicate.test(string_2)) { + this.text = string_2; + this.setCursor(int_1 + int_5); + this.method_1884(this.cursorMax); + this.onChanged(this.text); + } + }*/ + + /* + + //this would seem to delete text. if int_1 is negative, deletes from the end? + public void method_1878(int int_1) { + if (!this.text.isEmpty()) { + if (this.cursorMin != this.cursorMax) { + this.addText(""); + } else { + boolean boolean_1 = int_1 < 0; + int int_2 = boolean_1 ? this.cursorMax + int_1 : this.cursorMax; + int int_3 = boolean_1 ? this.cursorMax : this.cursorMax + int_1; + String string_1 = ""; + if (int_2 >= 0) { + string_1 = this.text.substring(0, int_2); + } + + if (int_3 < this.text.length()) { + string_1 = string_1 + this.text.substring(int_3); + } + + if (this.textPredicate.test(string_1)) { + this.text = string_1; + if (boolean_1) { + this.moveCursor(int_1); + } + + this.onChanged(this.text); + } + } + } + }*/ + + public void setCursorPos(int location) { + this.cursor = MathHelper.clamp(location, 0, this.text.length()); + } + + public int getMaxLength() { + return this.maxLength; + } + + public int getCursor() { + return this.cursor; + } + + public boolean isEditable() { + return this.editable; + } + + /* + public boolean keyPressed(int int_1, int int_2, int int_3) { + if (!this.method_20315()) { + return false; + } else { + this.field_17037 = Screen.hasShiftDown(); + if (Screen.isSelectAll(int_1)) { + this.method_1872(); + this.method_1884(0); + return true; + } else if (Screen.isCopy(int_1)) { + MinecraftClient.getInstance().keyboard.setClipboard(this.getSelectedText()); + return true; + } else if (Screen.isPaste(int_1)) { + if (this.editable) { + this.addText(MinecraftClient.getInstance().keyboard.getClipboard()); + } + + return true; + } else if (Screen.isCut(int_1)) { + MinecraftClient.getInstance().keyboard.setClipboard(this.getSelectedText()); + if (this.editable) { + this.addText(""); + } + + return true; + } else { + switch(int_1) { + case 259: + if (this.editable) { + this.method_16873(-1); + } + + return true; + case 260: + case 264: + case 265: + case 266: + case 267: + default: + return false; + case 261: + if (this.editable) { + this.method_16873(1); + } + + return true; + case 262: + if (Screen.hasControlDown()) { + this.method_1883(this.method_1853(1)); + } else { + this.moveCursor(1); + } + + return true; + case 263: + if (Screen.hasControlDown()) { + this.method_1883(this.method_1853(-1)); + } else { + this.moveCursor(-1); + } + + return true; + case 268: + this.method_1870(); + return true; + case 269: + this.method_1872(); + return true; + } + } + } + }*/ + + /* + public boolean charTyped(char char_1, int int_1) { + if (!this.method_20315()) { + return false; + } else if (SharedConstants.isValidChar(char_1)) { + if (this.editable) { + this.addText(Character.toString(char_1)); + } + + return true; + } else { + return false; + } + }*/ + /* + @Override + public void onClick(int x, int y, int button) { + + } + + public boolean mouseClicked(double double_1, double double_2, int int_1) { + if (!this.isVisible()) { + return false; + } else { + boolean boolean_1 = double_1 >= (double)this.x && double_1 < (double)(this.x + this.width) && double_2 >= (double)this.y && double_2 < (double)(this.y + this.height); + if (this.field_2096) { + this.method_1876(boolean_1); + } + + if (this.isFocused() && boolean_1 && int_1 == 0) { + int int_2 = MathHelper.floor(double_1) - this.x; + if (this.focused) { + int_2 -= 4; + } + + String string_1 = this.textRenderer.trimToWidth(this.text.substring(this.field_2103), this.method_1859()); + this.method_1883(this.textRenderer.trimToWidth(string_1, int_2).length() + this.field_2103); + return true; + } else { + return false; + } + } + }*/ + + /* + public void renderButton(int int_1, int int_2, float float_1) { + if (this.isVisible()) { + if (this.hasBorder()) { + fill(this.x - 1, this.y - 1, this.x + this.width + 1, this.y + this.height + 1, -6250336); + fill(this.x, this.y, this.x + this.width, this.y + this.height, -16777216); + } + + int int_3 = this.editable ? this.editableColor : this.uneditableColor; + int int_4 = this.cursorMax - this.field_2103; + int int_5 = this.cursorMin - this.field_2103; + String string_1 = this.textRenderer.trimToWidth(this.text.substring(this.field_2103), this.method_1859()); + boolean boolean_1 = int_4 >= 0 && int_4 <= string_1.length(); + boolean boolean_2 = this.isFocused() && this.focusedTicks / 6 % 2 == 0 && boolean_1; + int int_6 = this.focused ? this.x + 4 : this.x; + int int_7 = this.focused ? this.y + (this.height - 8) / 2 : this.y; + int int_8 = int_6; + if (int_5 > string_1.length()) { + int_5 = string_1.length(); + } + + if (!string_1.isEmpty()) { + String string_2 = boolean_1 ? string_1.substring(0, int_4) : string_1; + int_8 = this.textRenderer.drawWithShadow((String)this.renderTextProvider.apply(string_2, this.field_2103), (float)int_6, (float)int_7, int_3); + } + + boolean boolean_3 = this.cursorMax < this.text.length() || this.text.length() >= this.getMaxLength(); + int int_9 = int_8; + if (!boolean_1) { + int_9 = int_4 > 0 ? int_6 + this.width : int_6; + } else if (boolean_3) { + int_9 = int_8 - 1; + --int_8; + } + + if (!string_1.isEmpty() && boolean_1 && int_4 < string_1.length()) { + this.textRenderer.drawWithShadow((String)this.renderTextProvider.apply(string_1.substring(int_4), this.cursorMax), (float)int_8, (float)int_7, int_3); + } + + if (!boolean_3 && this.suggestion != null) { + this.textRenderer.drawWithShadow(this.suggestion, (float)(int_9 - 1), (float)int_7, -8355712); + } + + int var10002; + int var10003; + if (boolean_2) { + if (boolean_3) { + int var10001 = int_7 - 1; + var10002 = int_9 + 1; + var10003 = int_7 + 1; + this.textRenderer.getClass(); + DrawableHelper.fill(int_9, var10001, var10002, var10003 + 9, -3092272); + } else { + this.textRenderer.drawWithShadow("_", (float)int_9, (float)int_7, int_3); + } + } + + if (int_5 != int_4) { + int int_10 = int_6 + this.textRenderer.getStringWidth(string_1.substring(0, int_5)); + var10002 = int_7 - 1; + var10003 = int_10 - 1; + int var10004 = int_7 + 1; + this.textRenderer.getClass(); + this.method_1886(int_9, var10002, var10003, var10004 + 9); + } + + } + }*/ + + /* + private void method_1886(int int_1, int int_2, int int_3, int int_4) { + int int_6; + if (int_1 < int_3) { + int_6 = int_1; + int_1 = int_3; + int_3 = int_6; + } + + if (int_2 < int_4) { + int_6 = int_2; + int_2 = int_4; + int_4 = int_6; + } + + if (int_3 > this.x + this.width) { + int_3 = this.x + this.width; + } + + if (int_1 > this.x + this.width) { + int_1 = this.x + this.width; + } + + Tessellator tessellator_1 = Tessellator.getInstance(); + BufferBuilder bufferBuilder_1 = tessellator_1.getBufferBuilder(); + GlStateManager.color4f(0.0F, 0.0F, 255.0F, 255.0F); + GlStateManager.disableTexture(); + GlStateManager.enableColorLogicOp(); + GlStateManager.logicOp(GlStateManager.LogicOp.OR_REVERSE); + bufferBuilder_1.begin(7, VertexFormats.POSITION); + bufferBuilder_1.vertex((double)int_1, (double)int_4, 0.0D).next(); + bufferBuilder_1.vertex((double)int_3, (double)int_4, 0.0D).next(); + bufferBuilder_1.vertex((double)int_3, (double)int_2, 0.0D).next(); + bufferBuilder_1.vertex((double)int_1, (double)int_2, 0.0D).next(); + tessellator_1.draw(); + GlStateManager.disableColorLogicOp(); + GlStateManager.enableTexture(); + }*/ + + public WTextField setTextPredicate(Predicate predicate_1) { + this.textPredicate = predicate_1; + return this; + } + + public WTextField setChangedListener(Consumer listener) { + this.onChanged = listener; + return this; + } + + public WTextField setMaxLength(int max) { + this.maxLength = max; + if (this.text.length() > max) { + this.text = this.text.substring(0, max); + this.onChanged.accept(this.text); + } + return this; + } + + public WTextField setEnabledColor(int col) { + this.enabledColor = col; + return this; + } + + public WTextField setDisabledColor(int col) { + this.uneditableColor = col; + return this; + } + + public WTextField setEditable(boolean editable) { + this.editable = editable; + return this; + } + + public WTextField setSuggestion(@Nullable String suggestion) { + this.suggestion = suggestion; + return this; + } + + public WTextField setSuggestion(@Nullable Text suggestion) { + this.suggestion = suggestion.asString(); + return this; + } + + @Environment(EnvType.CLIENT) + public WTextField setBackgroundPainter(BackgroundPainter painter) { + this.backgroundPainter = painter; + return this; + } + /* + public void method_1884(int int_1) { + int int_2 = this.text.length(); + this.cursorMin = MathHelper.clamp(int_1, 0, int_2); + if (this.textRenderer != null) { + if (this.field_2103 > int_2) { + this.field_2103 = int_2; + } + + int int_3 = this.method_1859(); + String string_1 = this.textRenderer.trimToWidth(this.text.substring(this.field_2103), int_3); + int int_4 = string_1.length() + this.field_2103; + if (this.cursorMin == this.field_2103) { + this.field_2103 -= this.textRenderer.trimToWidth(this.text, int_3, true).length(); + } + + if (this.cursorMin > int_4) { + this.field_2103 += this.cursorMin - int_4; + } else if (this.cursorMin <= this.field_2103) { + this.field_2103 -= this.field_2103 - this.cursorMin; + } + + this.field_2103 = MathHelper.clamp(this.field_2103, 0, int_2); + } + + }*/ + + + + /* + @Environment(EnvType.CLIENT) + public int getCharacterX(int int_1) { + return int_1 > this.text.length() ? this.x : this.x + this.textRenderer.getStringWidth(this.text.substring(0, int_1)); + }*/ + + public boolean canFocus() { + return true; + } + + @Override + public void onFocusGained() { + } + + @Override + public void paintBackground(int x, int y) { + if (isFocused()) { + ScreenDrawing.rect(x-1, y-1, this.getWidth()+2, this.getHeight()+2, 0xFFFFFFFF); + } + + if (backgroundPainter!=null) { + backgroundPainter.paintBackground(x, y, this); + } else { + ScreenDrawing.drawBeveledPanel(x, y, this.getWidth(), this.getHeight()); + } + + ScreenDrawing.drawString(this.text, x+2, y+6, 0xFFFFFFFF); + int ofs = MinecraftClient.getInstance().textRenderer.getStringWidth(this.text); + ScreenDrawing.rect(x+2+ofs, y+4, 1, 12, 0xFFE0E0E0); + } + + @Override + public void onClick(int x, int y, int button) { + requestFocus(); + } + + @Override + public void onCharTyped(char ch) { + if (this.text.length()0) text = text.substring(0, text.length()-1); + } + } +} diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java index 14bb979..630f681 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java @@ -11,11 +11,11 @@ import net.minecraft.client.gui.screen.Screen; public class WWidget { protected WPanel parent; - private int x = 0; - private int y = 0; - private int width = 18; - private int height = 18; - //private boolean renderTooltip; + protected int x = 0; + protected int y = 0; + protected int width = 18; + protected int height = 18; + protected GuiDescription host; public void setLocation(int x, int y) { this.x = x; @@ -66,14 +66,6 @@ public class WWidget { public void setParent(WPanel parent) { this.parent = parent; } - - //public boolean getRenderTooltip() { - // return renderTooltip; - //} - - //public void setRenderTooltip(boolean renderTooltip) { - // this.renderTooltip = renderTooltip; - //} /** * Draw this Widget at the specified coordinates. The coordinates provided are the top-level device coordinates of @@ -125,24 +117,76 @@ public class WWidget { public void onClick(int x, int y, int button) { } + /** + * Notifies this widget that a character has been typed. This method is subject to key repeat, + * and may be called for characters that do not directly have a corresponding keyboard key. + * @param ch the character typed + */ + public void onCharTyped(char ch) { + } + + /** + * Notifies this widget that a key has been pressed. + * @param key the GLFW scancode of the key + */ + public void onKeyPressed(int key, int modifiers) { + } + + /** + * Notifies this widget that a key has been released + * @param key the GLFW scancode of the key + */ + public void onKeyReleased(int key, int modifiers) { + } + + /** Notifies this widget that it has gained focus */ + public void onFocusGained() { + } + + /** Notifies this widget that it has lost focus */ + public void onFocusLost() { + } + + public boolean isFocused() { + if (host==null) return false; + return host.isFocused(this); + } + + public void requestFocus() { + if (host!=null) { + host.requestFocus(this); + } else { + System.out.println("host is null"); + } + } + + public void releaseFocus() { + if (host!=null) host.releaseFocus(this); + } + + public boolean canFocus() { + return false; + } + /** * Creates "heavyweight" component peers * @param c the top-level Container that will hold the peers */ public void createPeers(GuiDescription c) { + host=c; } - + @Environment(EnvType.CLIENT) public void paintBackground(int x, int y) { } - + @Environment(EnvType.CLIENT) public void paintForeground(int x, int y, int mouseX, int mouseY) { if (mouseX >= x && mouseX < x+getWidth() && mouseY >= y && mouseY < y+getHeight()) { renderTooltip(mouseX, mouseY); } } - + /** * Internal method to conditionally render tooltip data. This requires an overriden {@link #addInformation(List) * addInformation} method to insert data into the tooltip - without this, the method returns early, because no work @@ -160,30 +204,8 @@ public class WWidget { Screen screen = MinecraftClient.getInstance().currentScreen; screen.renderTooltip(info, tX, tY); - /* - MinecraftClient mc = MinecraftClient.getInstance(); - int width = mc.window.getScaledWidth(); - int height = mc.window.getScaledHeight(); - //TODO: Hook into or copy Screen::drawStackTooltip or Screen::drawTooltip - TextRenderer renderer = mc.getFontManager().getTextRenderer(MinecraftClient.DEFAULT_TEXT_RENDERER_ID); - //Get width of the panel - int maxWidth = 0; - for(String s : info) { - maxWidth = Math.max(maxWidth, renderer.getStringWidth(s)); - } - //TODO: Draw background panel - - //Draw strings - for(int i=0; i