aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/dev/isxander/yacl/gui/controllers/cycling
diff options
context:
space:
mode:
authorisXander <isxander@users.noreply.github.com>2022-09-28 22:01:25 +0100
committerisXander <isxander@users.noreply.github.com>2022-09-28 22:01:25 +0100
commit575faeaf25256e02cbca39501c3ec97655959cea (patch)
tree47387038bbad42541d657c69ca68459f58bf0205 /src/main/java/dev/isxander/yacl/gui/controllers/cycling
parent6dec651e3d8b36cdb81d9db937df417e60dc2f71 (diff)
downloadYetAnotherConfigLib-575faeaf25256e02cbca39501c3ec97655959cea.tar.gz
YetAnotherConfigLib-575faeaf25256e02cbca39501c3ec97655959cea.tar.bz2
YetAnotherConfigLib-575faeaf25256e02cbca39501c3ec97655959cea.zip
generified cycling controller
Diffstat (limited to 'src/main/java/dev/isxander/yacl/gui/controllers/cycling')
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java60
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java48
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java60
-rw-r--r--src/main/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java19
4 files changed, 187 insertions, 0 deletions
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java b/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java
new file mode 100644
index 0000000..ab0a9c3
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java
@@ -0,0 +1,60 @@
+package dev.isxander.yacl.gui.controllers.cycling;
+
+import dev.isxander.yacl.api.utils.Dimension;
+import dev.isxander.yacl.gui.YACLScreen;
+import dev.isxander.yacl.gui.controllers.ControllerWidget;
+import net.minecraft.client.gui.screen.Screen;
+import org.lwjgl.glfw.GLFW;
+
+public class CyclingControllerElement extends ControllerWidget<ICyclingController<?>> {
+
+ public CyclingControllerElement(ICyclingController<?> control, YACLScreen screen, Dimension<Integer> dim) {
+ super(control, screen, dim);
+ }
+
+ public void cycleValue(int increment) {
+ int targetIdx = control.getPendingValue() + increment;
+ if (targetIdx >= control.getCycleLength()) {
+ targetIdx -= control.getCycleLength();
+ } else if (targetIdx < 0) {
+ targetIdx += control.getCycleLength();
+ }
+ control.setPendingValue(targetIdx);
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (!isMouseOver(mouseX, mouseY) || (button != 0 && button != 1) || !isAvailable())
+ return false;
+
+ playDownSound();
+ cycleValue(button == 1 || Screen.hasShiftDown() || Screen.hasControlDown() ? -1 : 1);
+
+ return true;
+ }
+
+ @Override
+ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
+ if (!focused)
+ return false;
+
+ switch (keyCode) {
+ case GLFW.GLFW_KEY_LEFT, GLFW.GLFW_KEY_DOWN ->
+ cycleValue(-1);
+ case GLFW.GLFW_KEY_RIGHT, GLFW.GLFW_KEY_UP ->
+ cycleValue(1);
+ case GLFW.GLFW_KEY_ENTER, GLFW.GLFW_KEY_SPACE, GLFW.GLFW_KEY_KP_ENTER ->
+ cycleValue(Screen.hasControlDown() || Screen.hasShiftDown() ? -1 : 1);
+ default -> {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ protected int getHoveredControlWidth() {
+ return getUnhoveredControlWidth();
+ }
+}
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java b/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java
new file mode 100644
index 0000000..a894eff
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java
@@ -0,0 +1,48 @@
+package dev.isxander.yacl.gui.controllers.cycling;
+
+import com.google.common.collect.ImmutableList;
+import dev.isxander.yacl.api.Option;
+import net.minecraft.text.Text;
+
+import java.util.function.Function;
+
+public class CyclingListController<T> implements ICyclingController<T> {
+ private final Option<T> option;
+ private final Function<T, Text> valueFormatter;
+ private final ImmutableList<T> values;
+
+ public CyclingListController(Option<T> option, Iterable<T> values) {
+ this(option, values, value -> Text.of(value.toString()));
+ }
+
+ public CyclingListController(Option<T> option, Iterable<T> values, Function<T, Text> valueFormatter) {
+ this.option = option;
+ this.valueFormatter = valueFormatter;
+ this.values = ImmutableList.copyOf(values);
+ }
+
+ @Override
+ public Option<T> option() {
+ return option;
+ }
+
+ @Override
+ public Text formatValue() {
+ return valueFormatter.apply(option().pendingValue());
+ }
+
+ @Override
+ public void setPendingValue(int ordinal) {
+ option().requestSet(values.get(ordinal));
+ }
+
+ @Override
+ public int getPendingValue() {
+ return values.indexOf(option().pendingValue());
+ }
+
+ @Override
+ public int getCycleLength() {
+ return values.size();
+ }
+}
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java b/src/main/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java
new file mode 100644
index 0000000..291863c
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java
@@ -0,0 +1,60 @@
+package dev.isxander.yacl.gui.controllers.cycling;
+
+import dev.isxander.yacl.api.NameableEnum;
+import dev.isxander.yacl.api.Option;
+import net.minecraft.text.Text;
+import net.minecraft.util.TranslatableOption;
+
+import java.util.Arrays;
+import java.util.function.Function;
+
+/**
+ * Simple controller type that displays the enum on the right.
+ * <p>
+ * Cycles forward with left click, cycles backward with right click or when shift is held
+ *
+ * @param <T> enum type
+ */
+public class EnumController<T extends Enum<T>> extends CyclingListController<T> {
+ public static <T extends Enum<T>> Function<T, Text> getDefaultFormatter() {
+ return value -> {
+ if (value instanceof NameableEnum nameableEnum)
+ return nameableEnum.getDisplayName();
+ if (value instanceof TranslatableOption translatableOption)
+ return translatableOption.getText();
+ return Text.of(value.toString());
+ };
+ }
+
+ /**
+ * Constructs a cycling enum controller with a default value formatter and all values being available.
+ * The default value formatter first searches if the
+ * enum is a {@link NameableEnum} else, just uses {@link Enum#toString()}
+ *
+ * @param option bound option
+ */
+ public EnumController(Option<T> option) {
+ this(option, getDefaultFormatter());
+ }
+
+ /**
+ * Constructs a cycling enum controller with all values being available.
+ *
+ * @param option bound option
+ * @param valueFormatter format the enum into any {@link Text}
+ */
+ public EnumController(Option<T> option, Function<T, Text> valueFormatter) {
+ this(option, valueFormatter, option.typeClass().getEnumConstants());
+ }
+
+ /**
+ * Constructs a cycling enum controller.
+ *
+ * @param option bound option
+ * @param valueFormatter format the enum into any {@link Text}
+ * @param availableValues all enum constants that can be cycled through
+ */
+ public EnumController(Option<T> option, Function<T, Text> valueFormatter, T[] availableValues) {
+ super(option, Arrays.asList(availableValues), valueFormatter);
+ }
+}
diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java b/src/main/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java
new file mode 100644
index 0000000..39f0b35
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java
@@ -0,0 +1,19 @@
+package dev.isxander.yacl.gui.controllers.cycling;
+
+import dev.isxander.yacl.api.Controller;
+import dev.isxander.yacl.api.utils.Dimension;
+import dev.isxander.yacl.gui.AbstractWidget;
+import dev.isxander.yacl.gui.YACLScreen;
+
+public interface ICyclingController<T> extends Controller<T> {
+ void setPendingValue(int ordinal);
+
+ int getPendingValue();
+
+ int getCycleLength();
+
+ @Override
+ default AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension) {
+ return new CyclingControllerElement(this, screen, widgetDimension);
+ }
+}