aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/dev/isxander/yacl
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/dev/isxander/yacl')
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/ColorController.java198
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java22
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/package-info.java1
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/string/IStringController.java18
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/string/StringController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/string/BasicStringController.java)9
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java71
6 files changed, 271 insertions, 48 deletions
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/ColorController.java b/src/main/java/dev/isxander/yacl/gui/controllers/ColorController.java
new file mode 100644
index 0000000..4d1dfc3
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/ColorController.java
@@ -0,0 +1,198 @@
+package dev.isxander.yacl.gui.controllers;
+
+import com.google.common.collect.ImmutableList;
+import dev.isxander.yacl.api.Option;
+import dev.isxander.yacl.api.utils.Dimension;
+import dev.isxander.yacl.gui.AbstractWidget;
+import dev.isxander.yacl.gui.YACLScreen;
+import dev.isxander.yacl.gui.controllers.string.IStringController;
+import dev.isxander.yacl.gui.controllers.string.StringControllerElement;
+import net.minecraft.client.gui.DrawableHelper;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+
+import java.awt.*;
+import java.util.List;
+
+/**
+ * A color controller that uses a hex color field as input.
+ */
+public class ColorController implements IStringController<Color> {
+ private final Option<Color> option;
+ private final boolean allowAlpha;
+
+ /**
+ * Constructs a color controller with {@link ColorController#allowAlpha()} defaulting to false
+ *
+ * @param option bound option
+ */
+ public ColorController(Option<Color> option) {
+ this(option, false);
+ }
+
+ /**
+ * Constructs a color controller
+ *
+ * @param option bound option
+ * @param allowAlpha allows the color input to accept alpha values
+ */
+ public ColorController(Option<Color> option, boolean allowAlpha) {
+ this.option = option;
+ this.allowAlpha = allowAlpha;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Option<Color> option() {
+ return option;
+ }
+
+ public boolean allowAlpha() {
+ return allowAlpha;
+ }
+
+ @Override
+ public String getString() {
+ return formatValue().getString();
+ }
+
+ @Override
+ public Text formatValue() {
+ MutableText text = Text.literal("#");
+ if (allowAlpha()) text.append(toHex(option().pendingValue().getAlpha()));
+ text.append(Text.literal(toHex(option().pendingValue().getRed())).formatted(Formatting.RED));
+ text.append(Text.literal(toHex(option().pendingValue().getGreen())).formatted(Formatting.GREEN));
+ text.append(Text.literal(toHex(option().pendingValue().getBlue())).formatted(Formatting.BLUE));
+ return text;
+ }
+
+ private String toHex(int value) {
+ String hex = Integer.toString(value, 16).toUpperCase();
+ if (hex.length() == 1)
+ hex = "0" + hex;
+ return hex;
+ }
+
+ @Override
+ public void setFromString(String value) {
+ if (value.startsWith("#"))
+ value = value.substring(1);
+
+ int alpha = Integer.parseInt(value.substring(0, 2), 16);
+ int red = Integer.parseInt(allowAlpha() ? value.substring(2, 4) : value.substring(0, 2), 16);
+ int green = Integer.parseInt(allowAlpha() ? value.substring(4, 6) : value.substring(2, 4), 16);
+ int blue = Integer.parseInt(allowAlpha() ? value.substring(6, 8) : value.substring(4, 6), 16);
+
+ option().requestSet(allowAlpha() ? new Color(red, green, blue, alpha) : new Color(red, green, blue));
+ }
+
+ @Override
+ public AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension) {
+ return new ColorControllerElement(this, screen, widgetDimension);
+ }
+
+ public static class ColorControllerElement extends StringControllerElement {
+ private final ColorController colorController;
+
+ protected Dimension<Integer> colorPreviewDim;
+
+ private final List<Character> allowedChars;
+
+ public ColorControllerElement(ColorController control, YACLScreen screen, Dimension<Integer> dim) {
+ super(control, screen, dim);
+ this.colorController = control;
+ this.allowedChars = ImmutableList.of('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
+ }
+
+ @Override
+ protected void drawValueText(MatrixStack matrices, int mouseX, int mouseY, float delta) {
+ if (isHovered()) {
+ colorPreviewDim.move(-inputFieldBounds.width() - 5, 0);
+ super.drawValueText(matrices, mouseX, mouseY, delta);
+ }
+
+ DrawableHelper.fill(matrices, colorPreviewDim.x(), colorPreviewDim.y(), colorPreviewDim.xLimit(), colorPreviewDim.yLimit(), colorController.option().pendingValue().getRGB());
+ drawOutline(matrices, colorPreviewDim.x(), colorPreviewDim.y(), colorPreviewDim.xLimit(), colorPreviewDim.yLimit(), 1, 0xFF000000);
+ }
+
+ @Override
+ public void write(String string) {
+ for (char chr : string.toCharArray()) {
+ if (!allowedChars.contains(Character.toLowerCase(chr))) {
+ return;
+ }
+ }
+
+ if (caretPos == 0)
+ return;
+
+ string = string.substring(0, Math.min(inputField.length() - caretPos, string.length()));
+
+ inputField.replace(caretPos, caretPos + string.length(), string);
+ caretPos += string.length();
+ setSelectionLength();
+
+ updateControl();
+ }
+
+ @Override
+ protected void doBackspace() {
+ if (caretPos > 1) {
+ inputField.setCharAt(caretPos - 1, '0');
+ caretPos--;
+ updateControl();
+ }
+ }
+
+ @Override
+ protected void doDelete() {
+
+ }
+
+ @Override
+ protected boolean canUseShortcuts() {
+ return false;
+ }
+
+ protected void setSelectionLength() {
+ selectionLength = caretPos < inputField.length() && caretPos > 0 ? 1 : 0;
+ }
+
+ @Override
+ protected int getDefaultCarotPos() {
+ return colorController.allowAlpha() ? 3 : 1;
+ }
+
+ @Override
+ public void setDimension(Dimension<Integer> dim) {
+ super.setDimension(dim);
+
+ int previewSize = (dim.height() - getYPadding() * 2) / 2;
+ colorPreviewDim = Dimension.ofInt(dim.xLimit() - getXPadding() - previewSize, dim.centerY() - previewSize / 2, previewSize, previewSize);
+ }
+
+ @Override
+ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
+ if (super.keyPressed(keyCode, scanCode, modifiers)) {
+ caretPos = Math.max(1, caretPos);
+ setSelectionLength();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (super.mouseClicked(mouseX, mouseY, button)) {
+ caretPos = Math.max(1, caretPos);
+ setSelectionLength();
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java b/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java
index 63b1b42..f61aedf 100644
--- a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java
@@ -9,28 +9,18 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
import org.jetbrains.annotations.ApiStatus;
+/**
+ * Simply renders some text as a label.
+ */
public class LabelController implements Controller<Text> {
private final Option<Text> option;
- private final int color;
-
/**
* Constructs a label controller
*
* @param option bound option
*/
public LabelController(Option<Text> option) {
- this(option, -1);
- }
-
- /**
- * Constructs a label controller
- *
- * @param option bound option
- * @param color color of the label
- */
- public LabelController(Option<Text> option, int color) {
this.option = option;
- this.color = color;
}
/**
@@ -41,10 +31,6 @@ public class LabelController implements Controller<Text> {
return option;
}
- public int color() {
- return color;
- }
-
@Override
public Text formatValue() {
return option().pendingValue();
@@ -64,7 +50,7 @@ public class LabelController implements Controller<Text> {
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
- textRenderer.drawWithShadow(matrices, formatValue(), dim.x(), dim.centerY() - textRenderer.fontHeight / 2f, color());
+ textRenderer.drawWithShadow(matrices, formatValue(), dim.x(), dim.centerY() - textRenderer.fontHeight / 2f, -1);
}
}
}
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/package-info.java b/src/main/java/dev/isxander/yacl/gui/controllers/package-info.java
index fcfc8e5..88c74c9 100644
--- a/src/main/java/dev/isxander/yacl/gui/controllers/package-info.java
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/package-info.java
@@ -5,6 +5,7 @@
* <li>For numbers: {@link dev.isxander.yacl.gui.controllers.slider}</li>
* <li>For booleans: {@link dev.isxander.yacl.gui.controllers.TickBoxController}</li>
* <li>For enums: {@link dev.isxander.yacl.gui.controllers.EnumController}</li>
+ * <li>For strings: {@link dev.isxander.yacl.gui.controllers.string.StringController}</li>
* <li>For {@link dev.isxander.yacl.api.ButtonOption}: {@link dev.isxander.yacl.gui.controllers.ActionController}</li>
* </ul>
*/
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/string/IStringController.java b/src/main/java/dev/isxander/yacl/gui/controllers/string/IStringController.java
index ae66433..41843b8 100644
--- a/src/main/java/dev/isxander/yacl/gui/controllers/string/IStringController.java
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/string/IStringController.java
@@ -1,12 +1,30 @@
package dev.isxander.yacl.gui.controllers.string;
import dev.isxander.yacl.api.Controller;
+import dev.isxander.yacl.api.Option;
import net.minecraft.text.Text;
+/**
+ * A controller that can be any type but can input and output a string.
+ */
public interface IStringController<T> extends Controller<T> {
+ /**
+ * Gets the option's pending value as a string.
+ *
+ * @see Option#pendingValue()
+ */
String getString();
+
+ /**
+ * Sets the option's pending value from a string.
+ *
+ * @see Option#requestSet(Object)
+ */
void setFromString(String value);
+ /**
+ * {@inheritDoc}
+ */
@Override
default Text formatValue() {
return Text.of(getString());
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/string/BasicStringController.java b/src/main/java/dev/isxander/yacl/gui/controllers/string/StringController.java
index edda506..0caaa93 100644
--- a/src/main/java/dev/isxander/yacl/gui/controllers/string/BasicStringController.java
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/string/StringController.java
@@ -5,15 +5,18 @@ import dev.isxander.yacl.api.utils.Dimension;
import dev.isxander.yacl.gui.AbstractWidget;
import dev.isxander.yacl.gui.YACLScreen;
-public class BasicStringController implements IStringController<String> {
+/**
+ * A custom text field implementation for strings.
+ */
+public class StringController implements IStringController<String> {
private final Option<String> option;
/**
- * Constructs a tickbox controller
+ * Constructs a string controller
*
* @param option bound option
*/
- public BasicStringController(Option<String> option) {
+ public StringController(Option<String> option) {
this.option = option;
}
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java b/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java
index ed066f2..f8cf802 100644
--- a/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java
@@ -8,7 +8,6 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
-import net.minecraft.util.Pair;
import org.lwjgl.glfw.GLFW;
public class StringControllerElement extends ControllerWidget<IStringController<?>> {
@@ -27,7 +26,6 @@ public class StringControllerElement extends ControllerWidget<IStringController<
super(control, screen, dim);
inputField = new StringBuilder(control.getString());
inputFieldFocused = false;
- caretPos = inputField.length();
selectionLength = 0;
emptyText = Text.literal("Click to type...").formatted(Formatting.GRAY);
}
@@ -40,7 +38,7 @@ public class StringControllerElement extends ControllerWidget<IStringController<
DrawableHelper.fill(matrices, inputFieldBounds.x() + 1, inputFieldBounds.yLimit() + 1, inputFieldBounds.xLimit() + 1, inputFieldBounds.yLimit() + 2, 0xFF404040);
if (inputFieldFocused || focused) {
- int caretX = inputFieldBounds.x() + textRenderer.getWidth(inputField.substring(0, caretPos)) - 1;
+ int caretX = inputFieldBounds.x() + textRenderer.getWidth(control.getString().substring(0, caretPos)) - 1;
if (inputField.isEmpty())
caretX += inputFieldBounds.width() / 2;
@@ -58,18 +56,24 @@ public class StringControllerElement extends ControllerWidget<IStringController<
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (inputFieldBounds.isPointInside((int) mouseX, (int) mouseY)) {
- if (!inputFieldFocused)
+ if (!inputFieldFocused) {
inputFieldFocused = true;
- else {
+ caretPos = getDefaultCarotPos();
+ } else {
int textWidth = (int) mouseX - inputFieldBounds.x();
caretPos = textRenderer.trimToWidth(control.getString(), textWidth).length();
selectionLength = 0;
}
+ return true;
} else {
inputFieldFocused = false;
}
- return super.mouseClicked(mouseX, mouseY, button);
+ return false;
+ }
+
+ protected int getDefaultCarotPos() {
+ return inputField.length();
}
@Override
@@ -115,34 +119,27 @@ public class StringControllerElement extends ControllerWidget<IStringController<
return true;
}
case GLFW.GLFW_KEY_BACKSPACE -> {
- if (selectionLength != 0) {
- write("");
- } else if (caretPos > 0) {
- inputField.deleteCharAt(caretPos - 1);
- updateControl();
- caretPos--;
- }
+ doBackspace();
return true;
}
case GLFW.GLFW_KEY_DELETE -> {
- if (caretPos < inputField.length()) {
- inputField.deleteCharAt(caretPos);
- updateControl();
- }
+ doDelete();
return true;
}
}
- if (Screen.isPaste(keyCode)) {
- this.write(client.keyboard.getClipboard());
- } else if (Screen.isCopy(keyCode) && selectionLength != 0) {
- client.keyboard.setClipboard(getSelection());
- } else if (Screen.isCut(keyCode) && selectionLength != 0) {
- client.keyboard.setClipboard(getSelection());
- this.write("");
- } else if (Screen.isSelectAll(keyCode)) {
- caretPos = inputField.length();
- selectionLength = -caretPos;
+ if (canUseShortcuts()) {
+ if (Screen.isPaste(keyCode)) {
+ this.write(client.keyboard.getClipboard());
+ } else if (Screen.isCopy(keyCode) && selectionLength != 0) {
+ client.keyboard.setClipboard(getSelection());
+ } else if (Screen.isCut(keyCode) && selectionLength != 0) {
+ client.keyboard.setClipboard(getSelection());
+ this.write("");
+ } else if (Screen.isSelectAll(keyCode)) {
+ caretPos = inputField.length();
+ selectionLength = -caretPos;
+ }
}
return false;
@@ -158,6 +155,26 @@ public class StringControllerElement extends ControllerWidget<IStringController<
return true;
}
+ protected boolean canUseShortcuts() {
+ return true;
+ }
+
+ protected void doBackspace() {
+ if (selectionLength != 0) {
+ write("");
+ } else if (caretPos > 0) {
+ inputField.deleteCharAt(caretPos - 1);
+ caretPos--;
+ }
+ }
+
+ protected void doDelete() {
+ if (caretPos < inputField.length()) {
+ inputField.deleteCharAt(caretPos);
+ updateControl();
+ }
+ }
+
public void write(String string) {
if (selectionLength == 0) {
string = textRenderer.trimToWidth(string, getMaxLength() - textRenderer.getWidth(inputField.toString()));