aboutsummaryrefslogtreecommitdiff
path: root/src/client/java/dev
diff options
context:
space:
mode:
authorisXander <xandersmith2008@gmail.com>2022-11-27 18:17:36 +0000
committerisXander <xandersmith2008@gmail.com>2022-11-27 18:17:36 +0000
commitd163b9128d760e53e34fd6c08dbf782fa3d50c51 (patch)
treeb9ea79bb99bf52ea7de9d059cc05900270ff88d4 /src/client/java/dev
parentc26d3a89caae20f1a91898202d91de8dc90da5ad (diff)
downloadYetAnotherConfigLib-d163b9128d760e53e34fd6c08dbf782fa3d50c51.tar.gz
YetAnotherConfigLib-d163b9128d760e53e34fd6c08dbf782fa3d50c51.tar.bz2
YetAnotherConfigLib-d163b9128d760e53e34fd6c08dbf782fa3d50c51.zip
split sourcesets
Diffstat (limited to 'src/client/java/dev')
-rw-r--r--src/client/java/dev/isxander/yacl/api/Binding.java64
-rw-r--r--src/client/java/dev/isxander/yacl/api/ButtonOption.java123
-rw-r--r--src/client/java/dev/isxander/yacl/api/ConfigCategory.java157
-rw-r--r--src/client/java/dev/isxander/yacl/api/Controller.java28
-rw-r--r--src/client/java/dev/isxander/yacl/api/NameableEnum.java10
-rw-r--r--src/client/java/dev/isxander/yacl/api/Option.java336
-rw-r--r--src/client/java/dev/isxander/yacl/api/OptionFlag.java27
-rw-r--r--src/client/java/dev/isxander/yacl/api/OptionGroup.java141
-rw-r--r--src/client/java/dev/isxander/yacl/api/PlaceholderCategory.java94
-rw-r--r--src/client/java/dev/isxander/yacl/api/YetAnotherConfigLib.java136
-rw-r--r--src/client/java/dev/isxander/yacl/api/utils/Dimension.java33
-rw-r--r--src/client/java/dev/isxander/yacl/api/utils/MutableDimension.java11
-rw-r--r--src/client/java/dev/isxander/yacl/api/utils/OptionUtils.java37
-rw-r--r--src/client/java/dev/isxander/yacl/gui/AbstractWidget.java108
-rw-r--r--src/client/java/dev/isxander/yacl/gui/CategoryListWidget.java96
-rw-r--r--src/client/java/dev/isxander/yacl/gui/CategoryWidget.java31
-rw-r--r--src/client/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java29
-rw-r--r--src/client/java/dev/isxander/yacl/gui/OptionListWidget.java470
-rw-r--r--src/client/java/dev/isxander/yacl/gui/RequireRestartScreen.java16
-rw-r--r--src/client/java/dev/isxander/yacl/gui/SearchFieldWidget.java62
-rw-r--r--src/client/java/dev/isxander/yacl/gui/TextScaledButtonWidget.java44
-rw-r--r--src/client/java/dev/isxander/yacl/gui/TooltipButtonWidget.java30
-rw-r--r--src/client/java/dev/isxander/yacl/gui/YACLScreen.java269
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/ActionController.java120
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/BooleanController.java156
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/ColorController.java203
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java165
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/LabelController.java144
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/TickBoxController.java120
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java60
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java79
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java60
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java38
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/package-info.java12
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/slider/DoubleSliderController.java114
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/slider/FloatSliderController.java114
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/slider/ISliderController.java54
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/slider/IntegerSliderController.java111
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/slider/LongSliderController.java111
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java160
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/slider/package-info.java10
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/string/IStringController.java32
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/string/StringController.java45
-rw-r--r--src/client/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java283
-rw-r--r--src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java142
-rw-r--r--src/client/java/dev/isxander/yacl/impl/ConfigCategoryImpl.java10
-rw-r--r--src/client/java/dev/isxander/yacl/impl/GenericBindingImpl.java35
-rw-r--r--src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java10
-rw-r--r--src/client/java/dev/isxander/yacl/impl/OptionImpl.java144
-rw-r--r--src/client/java/dev/isxander/yacl/impl/PlaceholderCategoryImpl.java19
-rw-r--r--src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java19
-rw-r--r--src/client/java/dev/isxander/yacl/impl/utils/DimensionIntegerImpl.java115
-rw-r--r--src/client/java/dev/isxander/yacl/impl/utils/YACLConstants.java8
-rw-r--r--src/client/java/dev/isxander/yacl/mixin/client/SimpleOptionAccessor.java11
54 files changed, 5056 insertions, 0 deletions
diff --git a/src/client/java/dev/isxander/yacl/api/Binding.java b/src/client/java/dev/isxander/yacl/api/Binding.java
new file mode 100644
index 0000000..91158d3
--- /dev/null
+++ b/src/client/java/dev/isxander/yacl/api/Binding.java
@@ -0,0 +1,64 @@
+package dev.isxander.yacl.api;
+
+import dev.isxander.yacl.impl.GenericBindingImpl;
+import dev.isxander.yacl.mixin.client.SimpleOptionAccessor;
+import net.minecraft.client.option.SimpleOption;
+import org.apache.commons.lang3.Validate;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * Controls modifying the bound option.
+ * Provides the default value, a setter and a getter.
+ */
+public interface Binding<T> {
+ void setValue(T value);
+
+ T getValue();
+
+ T defaultValue();
+
+ /**
+ * Creates a generic binding.
+ *
+ * @param def default value of the option, used to reset
+ * @param getter should return the current value of the option
+ * @param setter should set the option to the supplied value
+ */
+ static <T> Binding<T> generic(T def, Supplier<T> getter, Consumer<T> setter) {
+ Validate.notNull(def, "`def` must not be null");
+ Validate.notNull(getter, "`getter` must not be null");
+ Validate.notNull(setter, "`setter` must not be null");
+
+ return new GenericBindingImpl<>(def, getter, setter);
+ }
+
+ /**
+ * Creates a {@link Binding} for Minecraft's {@link SimpleOption}
+ */
+ static <T> Binding<T> minecraft(SimpleOption<T> minecraftOption) {
+ Validate.notNull(minecraftOption, "`minecraftOption` must not be null");
+
+ return new GenericBindingImpl<>(
+ ((SimpleOptionAccessor<T>) (Object) minecraftOption).getDefaultValue(),
+ minecraftOption::getValue,
+ minecraftOption::setValue
+ );
+ }
+
+ /**
+ * Creates an immutable binding that has no default and cannot be modified.
+ *
+ * @param value the value for the binding
+ */
+ static <T> Binding<T> immutable(T value) {
+ Validate.notNull(value, "`value` must not be null");
+
+ return new GenericBindingImpl<>(
+ value,
+ () -> value,
+ changed -> {}
+ );
+ }
+}
diff --git a/src/client/java/dev/isxander/yacl/api/ButtonOption.java b/src/client/java/dev/isxander/yacl/api/ButtonOption.java
new file mode 100644
index 0000000..1124a9a
--- /dev/null
+++ b/src/client/java/dev/isxander/yacl/api/ButtonOption.java
@@ -0,0 +1,123 @@
+package dev.isxander.yacl.api;
+
+import dev.isxander.yacl.gui.YACLScreen;
+import dev.isxander.yacl.impl.ButtonOptionImpl;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import org.apache.commons.lang3.Validate;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+public interface ButtonOption extends Option<BiConsumer<YACLScreen, ButtonOption>> {
+ /**
+ * Action to be executed upon button press
+ */
+ BiConsumer<YACLScreen, ButtonOption> action();
+
+ static Builder createBuilder() {
+ return new Builder();
+ }
+
+ class Builder {
+ private Text name;
+ private final List<Text> tooltipLines = new ArrayList<>();
+ private boolean available = true;
+ private Function<ButtonOption, Controller<BiConsumer<YACLScreen, ButtonOption>>> controlGetter;
+ private BiConsumer<YACLScreen, ButtonOption> action;
+
+ private Builder() {
+
+ }
+
+ /**
+ * Sets the name to be used by the option.
+ *
+ * @see Option#name()
+ */
+ public Builder name(@NotNull Text name) {
+ Validate.notNull(name, "`name` cannot be null");
+
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Sets the tooltip to be used by the option.
+ * Can be invoked twice to append more lines.
+ * No need to wrap the text yourself, the gui does this itself.
+ *
+ * @param tooltips text lines - merged with a new-line on {@link Option.Builder#build()}.
+ */
+ public Builder tooltip(@NotNull Text... tooltips) {
+ Validate.notNull(tooltips, "`tooltips` cannot be empty");
+
+ tooltipLines.addAll(List.of(tooltips));
+ return this;
+ }
+
+ public Builder action(@NotNull BiConsumer<YACLScreen, ButtonOption> action) {
+ Validate.notNull(action, "`action` cannot be null");
+
+ this.action = action;
+ return this;
+ }
+
+ /**
+ * Action to be executed upon button press
+ *
+ * @see ButtonOption#action()
+ */
+ @Deprecated
+ public Builder action(@NotNull Consumer<YACLScreen> action) {
+ Validate.notNull(action, "`action` cannot be null");
+
+ this.action = (screen, button) -> action.accept(screen);
+ return this;
+ }
+
+ /**
+ * Sets if the option can be configured
+ *
+ * @see Option#available()
+ */
+ public Builder available(boolean available) {
+ this.available = available;
+ return this;
+ }
+
+ /**
+ * Sets the controller for the option.
+ * This is how you interact and change the options.
+ *
+ * @see dev.isxander.yacl.gui.controllers
+ */
+ public Builder controller(@NotNull Function<ButtonOption, Controller<BiConsumer<YACLScreen, ButtonOption>>> control) {
+ Validate.notNull(control, "`control` cannot be null");
+
+ this.controlGetter = control;
+ return this;
+ }
+
+ public ButtonOption build() {
+ Validate.notNull(name, "`name` must not be null when building `Option`");
+ Validate.notNull(controlGetter, "`control` must not be null when building `Option`");
+ Validate.notNull(action, "`action` must not be null when building `Option`");
+
+ MutableText concatenatedTooltip = Text.empty();
+ boolean first = true;
+ for (Text line : tooltipLines) {
+ if (!first) concatenatedTooltip.append("\n");
+ first = false;
+
+ concatenatedTooltip.append(line);
+ }
+
+ return new ButtonOptionImpl(name, concatenatedTooltip, action, available, controlGetter);
+ }
+ }
+}
diff --git a/src/client/java/dev/isxander/yacl/api/ConfigCategory.java b/src/client/java/dev/isxander/yacl/api/ConfigCategory.java
new file mode 100644
index 0000000..e9755dd
--- /dev/null
+++ b/src/client/java/dev/isxander/yacl/api/ConfigCategory.java
@@ -0,0 +1,157 @@
+package dev.isxander.yacl.api;
+
+import com.google.common.collect.ImmutableList;
+import dev.isxander.yacl.impl.ConfigCategoryImpl;
+import dev.isxander.yacl.impl.OptionGroupImpl;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import org.apache.commons.lang3.Validate;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Separates {@link Option}s or {@link OptionGroup}s into multiple distinct sections.
+ * Served to a user as a button in the left column,
+ * upon pressing, the options list is filled with options contained within this category.
+ */
+public interface ConfigCategory {
+ /**
+ * Name of category, displayed as a button on the left column.
+ */
+ @NotNull Text name();
+
+ /**
+ * Gets every {@link OptionGroup} in this category.
+ */
+ @NotNull ImmutableList<OptionGroup> groups();
+
+ /**
+ * Tooltip (or description) of the category.
+ * Rendered on hover.
+ */
+ @NotNull Text tooltip();
+
+ /**
+ * Creates a builder to construct a {@link ConfigCategory}
+ */
+ static Builder createBuilder() {
+ return new Builder();
+ }
+
+ class Builder {
+ private Text name;
+
+ private final List<Option<?>> rootOptions = new ArrayList<>();
+ private final List<OptionGroup> groups = new ArrayList<>();
+
+ private final List<Text> tooltipLines = new ArrayList<>();
+
+ private Builder() {
+
+ }
+
+ /**
+ * Sets name of the category
+ *
+ * @see ConfigCategory#name()
+ */
+ public Builder name(@NotNull Text name) {
+ Validate.notNull(name, "`name` cannot be null");
+
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Adds an option to the root group of the category.
+ * To add to another group, use {@link Builder#group(OptionGroup)}.
+ * To construct an option, use {@link Option#createBuilder(Class)}
+ *
+ * @see ConfigCategory#groups()
+ * @see OptionGroup#isRoot()
+ */
+ public Builder option(@NotNull Option<?> option) {
+ Validate.notNull(option, "`option` must not be null");
+
+ this.rootOptions.add(option);
+ return this;
+ }
+
+ /**
+ * Adds multiple options to the root group of the category.
+ * To add to another group, use {@link Builder#groups(Collection)}.
+ * To construct an option, use {@link Option#createBuilder(Class)}
+ *
+ * @see ConfigCategory#groups()
+ * @see OptionGroup#isRoot()
+ */
+ public Builder options(@NotNull Collection<Option<?>> options) {
+ Validate.notNull(options, "`options` must not be null");
+
+ this.rootOptions.addAll(options);
+ return this;
+ }
+
+ /**
+ * Adds an option group.
+ * To add an option to the root group, use {@link Builder#option(Option)}
+ * To construct a group, use {@link OptionGroup#createBuilder()}
+ */
+ public Builder group(@NotNull OptionGroup group) {
+ Validate.notNull(group, "`group` must not be null");
+
+ this.groups.add(group);
+ return this;
+ }
+
+ /**
+ * Adds multiple option groups.
+ * To add multiple options to the root group, use {@link Builder#options(Collection)}
+ * To construct a group, use {@link OptionGroup#createBuilder()}
+ */
+ public Builder groups(@NotNull Collection<OptionGroup> groups) {
+ Validate.notEmpty(groups, "`groups` must not be empty");
+
+ this.groups.addAll(groups);
+ return this;
+ }
+
+ /**
+ * Sets the tooltip to be used by the category.
+ * Can be invoked twice to append more lines.
+ * No need to wrap the text yourself, the gui does this itself.
+ *
+ * @param tooltips text lines - merged with a new-line on {@link Builder#build()}.
+ */
+ public Builder tooltip(@NotNull Text... tooltips) {
+ Validate.notEmpty(tooltips, "`tooltips` cannot be empty");
+
+ tooltipLines.addAll(List.of(tooltips));
+ return this;
+ }
+
+ public ConfigCategory build() {
+ Validate.notNull(name, "`name` must not be null to build `ConfigCategory`");
+
+ List<OptionGroup> combinedGroups = new ArrayList<>();
+ combinedGroups.add(new OptionGroupImpl(Text.empty(), Text.empty(), ImmutableList.copyOf(rootOptions), false, true));
+ combinedGroups.addAll(groups);
+
+ Validate.notEmpty(combinedGroups, "at least one option must be added to build `ConfigCategory`");
+
+ MutableText concatenatedTooltip = Text.empty();
+ boolean first = true;
+ for (Text line : tooltipLines) {
+ if (!first) concatenatedTooltip.append("\n");
+ first = false;
+
+ concatenatedTooltip.append(line);
+ }
+
+ return new ConfigCategoryImpl(name, ImmutableList.copyOf(combinedGroups), concatenatedTooltip);
+ }
+ }
+}
diff --git a/src/client/java/dev/isxander/yacl/api/Controller.java b/src/client/java/dev/isxander/yacl/api/Controller.java
new file mode 100644
index 0000000..7bf7e7f
--- /dev/null
+++ b/src/client/java/dev/isxander/yacl/api/Controller.java
@@ -0,0 +1,28 @@
+package dev.isxander.yacl.api;
+
+import dev.isxander.yacl.api.utils.Dimension;
+import dev.isxander.yacl.gui.AbstractWidget;
+import dev.isxander.yacl.gui.YACLScreen;
+import net.minecraft.text.Text;
+
+/**
+ * Provides a widget to control the option.
+ */
+public interface Controller<T> {
+ /**
+ * Gets the dedicated {@link Option} for this controller
+ */
+ Option<T> option();
+
+ /**
+ * Gets the formatted value based on {@link Option#pendingValue()}
+ */
+ Text formatValue();
+
+ /**
+ * Provides a widget to display
+ *
+ * @param screen parent screen
+ */
+ AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension);
+}
diff --git a/src/client/java/dev/isxander/yacl/api/NameableEnum.java b/src/client/java/dev/isxander/yacl/api/NameableEnum.java
new file mode 100644
index 0000000..793b230
--- /dev/null
+++ b/src/client/java/dev/isxander/yacl/api/NameableEnum.java
@@ -0,0 +1,10 @@
+package dev.isxander.yacl.api;
+
+import net.minecraft.text.Text;
+
+/**
+ * Used for the default value formatter of {@link dev.isxander.yacl.gui.controllers.cycling.EnumController}
+ */
+public interface NameableEnum {
+ Text getDisplayName();
+}
diff --git a/src/client/java/dev/isxander/yacl/api/Option.java b/src/client/java/dev/isxander/yacl/api/Option.java
new file mode 100644
index 0000000..772c816
--- /dev/null
+++ b/src/client/java/dev/isxander/yacl/api/Option.java
@@ -0,0 +1,336 @@
+package dev.isxander.yacl.api;
+
+import com.google.common.collect.ImmutableSet;
+import dev.isxander.yacl.impl.OptionImpl;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+import org.apache.commons.lang3.Validate;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+public interface Option<T> {
+ /**
+ * Name of the option
+ */
+ @NotNull Text name();
+
+ /**
+ * Tooltip (or description) of the option.
+ * Rendered on hover.
+ */
+ @NotNull Text tooltip();
+
+ /**
+ * Widget provider for a type of option.
+ *
+ * @see dev.isxander.yacl.gui.controllers
+ */
+ @NotNull Controller<T> controller();
+
+ /**
+ * Binding for the option.
+ * Controls setting, getting and default value.
+ *
+ * @see Binding
+ */
+ @NotNull Binding<T> binding();
+
+ /**
+ * If the option can be configured
+ */
+ boolean available();
+
+ /**
+ * Sets if the option can be configured after being built
+ *
+ * @see Option#available()
+ */
+ void setAvailable(boolean available);
+
+ /**
+ * Class of the option type.
+ * Used by some controllers.
+ */
+ @NotNull Class<T> typeClass();
+
+ /**
+ * Tasks that needs to be executed upon applying changes.
+ */
+ @NotNull ImmutableSet<OptionFlag> flags();
+
+ /**
+ * Checks if the pending value is not equal to the current set value
+ */
+ boolean changed();
+
+ /**
+ * If true, modifying this option recommends a restart.
+ */
+ @Deprecated
+ boolean requiresRestart();
+
+ /**
+ * Value in the GUI, ready to set the actual bound value or be undone.
+ */
+ @NotNull T pendingValue();
+
+ /**
+ * Sets the pending value
+ */
+ void requestSet(T value);
+
+ /**
+ * Applies the pending value to the bound value.
+ * Cannot be undone.
+ *
+ * @return if there were changes to apply {@link Option#changed()}
+ */
+ boolean applyValue();
+
+ /**
+ * Sets the pending value to the bound value.
+ */
+ void forgetPendingValue();
+
+ /**
+ * Sets the pending value to the default bound value.
+ */
+ void requestSetDefault();
+
+ /**
+ * Checks if the current pending value is equal to its default value
+ */
+ boolean isPendingValueDefault();
+
+ /**
+ * Adds a listener for when the pending value changes
+ */
+ void addListener(BiConsumer<Option<T>, T> changedListener);
+
+ /**
+ * Creates a builder to construct an {@link Option}
+ *
+ * @param <T> type of the option's value
+ * @param typeClass used to capture the type
+ */
+ static <T> Builder<T> createBuilder(Class<T> typeClass) {
+ return new Builder<>(typeClass);
+ }
+
+ class Builder<T> {
+ private Text name = Text.literal("Name not specified!").formatted(Formatting.RED);
+
+ private final List<Function<T, Text>> tooltipGetters = new ArrayList<>();
+
+ private Function<Option<T>, Controller<T>> controlGetter;
+
+ private Binding<T> binding;
+
+ private boolean available = true;