diff options
author | xander <xander@isxander.dev> | 2022-09-01 11:58:49 +0100 |
---|---|---|
committer | xander <xander@isxander.dev> | 2022-09-01 11:58:49 +0100 |
commit | 4d977cc9764ecf0073650f126700f6ff638fa06b (patch) | |
tree | 883e68bbd80874c048b3e34db59bf0aa926b489b /src/main/java/dev/isxander/yacl/api | |
parent | e63a3c989e3a899bdc81558dd2e4c5cc2c659bde (diff) | |
download | YetAnotherConfigLib-4d977cc9764ecf0073650f126700f6ff638fa06b.tar.gz YetAnotherConfigLib-4d977cc9764ecf0073650f126700f6ff638fa06b.tar.bz2 YetAnotherConfigLib-4d977cc9764ecf0073650f126700f6ff638fa06b.zip |
javadoc!
added LongSliderController
renamed Control -> Controller
add minecraft simple option binding constructor
Diffstat (limited to 'src/main/java/dev/isxander/yacl/api')
10 files changed, 324 insertions, 29 deletions
diff --git a/src/main/java/dev/isxander/yacl/api/Binding.java b/src/main/java/dev/isxander/yacl/api/Binding.java index 74120a0..d870d8c 100644 --- a/src/main/java/dev/isxander/yacl/api/Binding.java +++ b/src/main/java/dev/isxander/yacl/api/Binding.java @@ -1,10 +1,17 @@ package dev.isxander.yacl.api; import dev.isxander.yacl.impl.GenericBindingImpl; +import dev.isxander.yacl.mixin.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); @@ -12,7 +19,31 @@ public interface Binding<T> { 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> of(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> of(SimpleOption<T> minecraftOption) { + Validate.notNull(minecraftOption, "`minecraftOption` must not be null"); + + return new GenericBindingImpl<>( + ((SimpleOptionAccessor<T>) (Object) minecraftOption).getDefaultValue(), + minecraftOption::getValue, + minecraftOption::setValue + ); + } } diff --git a/src/main/java/dev/isxander/yacl/api/ButtonOption.java b/src/main/java/dev/isxander/yacl/api/ButtonOption.java index 08436b3..346bfa4 100644 --- a/src/main/java/dev/isxander/yacl/api/ButtonOption.java +++ b/src/main/java/dev/isxander/yacl/api/ButtonOption.java @@ -20,7 +20,7 @@ public interface ButtonOption extends Option<Runnable> { class Builder { private Text name; private final List<Text> tooltipLines = new ArrayList<>(); - private Function<ButtonOption, Control<Runnable>> controlGetter; + private Function<ButtonOption, Controller<Runnable>> controlGetter; private Runnable action; private Builder() { @@ -48,7 +48,7 @@ public interface ButtonOption extends Option<Runnable> { return this; } - public Builder controller(@NotNull Function<ButtonOption, Control<Runnable>> control) { + public Builder controller(@NotNull Function<ButtonOption, Controller<Runnable>> control) { Validate.notNull(control, "`control` cannot be null"); this.controlGetter = control; diff --git a/src/main/java/dev/isxander/yacl/api/ConfigCategory.java b/src/main/java/dev/isxander/yacl/api/ConfigCategory.java index 13552d6..b2bbf95 100644 --- a/src/main/java/dev/isxander/yacl/api/ConfigCategory.java +++ b/src/main/java/dev/isxander/yacl/api/ConfigCategory.java @@ -10,14 +10,29 @@ import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.function.Function; +/** + * 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(); + /** + * Creates a builder to construct a {@link ConfigCategory} + */ static Builder createBuilder() { return new Builder(); } @@ -32,6 +47,11 @@ public interface ConfigCategory { } + /** + * Sets name of the category + * + * @see ConfigCategory#name() + */ public Builder name(@NotNull Text name) { Validate.notNull(name, "`name` cannot be null"); @@ -39,6 +59,14 @@ public interface ConfigCategory { 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"); @@ -46,6 +74,26 @@ public interface ConfigCategory { 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.notEmpty(options, "`options` must not be empty"); + + 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"); @@ -53,6 +101,18 @@ public interface ConfigCategory { 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; + } + public ConfigCategory build() { Validate.notNull(name, "`name` must not be null to build `ConfigCategory`"); Validate.notEmpty(rootOptions, "`at least one option must be added to build `ConfigCategory`"); diff --git a/src/main/java/dev/isxander/yacl/api/Control.java b/src/main/java/dev/isxander/yacl/api/Control.java deleted file mode 100644 index 242b2c8..0000000 --- a/src/main/java/dev/isxander/yacl/api/Control.java +++ /dev/null @@ -1,14 +0,0 @@ -package dev.isxander.yacl.api; - -import dev.isxander.yacl.api.utils.Dimension; -import dev.isxander.yacl.gui.controllers.ControlWidget; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.Text; - -public interface Control<T> { - Option<T> option(); - - Text formatValue(); - - ControlWidget<?> provideWidget(Screen screen, Dimension<Integer> widgetDimension); -} diff --git a/src/main/java/dev/isxander/yacl/api/Controller.java b/src/main/java/dev/isxander/yacl/api/Controller.java new file mode 100644 index 0000000..2c0a5e1 --- /dev/null +++ b/src/main/java/dev/isxander/yacl/api/Controller.java @@ -0,0 +1,30 @@ +package dev.isxander.yacl.api; + +import dev.isxander.yacl.api.utils.Dimension; +import dev.isxander.yacl.gui.controllers.ControllerWidget; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import org.jetbrains.annotations.ApiStatus; + +/** + * 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 + */ + @ApiStatus.Internal + ControllerWidget<?> provideWidget(Screen screen, Dimension<Integer> widgetDimension); +} diff --git a/src/main/java/dev/isxander/yacl/api/NameableEnum.java b/src/main/java/dev/isxander/yacl/api/NameableEnum.java index 12a58c3..9744ce9 100644 --- a/src/main/java/dev/isxander/yacl/api/NameableEnum.java +++ b/src/main/java/dev/isxander/yacl/api/NameableEnum.java @@ -2,6 +2,9 @@ package dev.isxander.yacl.api; import net.minecraft.text.Text; +/** + * Used for the default value formatter of {@link dev.isxander.yacl.gui.controllers.EnumController} + */ public interface NameableEnum { Text getDisplayName(); } diff --git a/src/main/java/dev/isxander/yacl/api/Option.java b/src/main/java/dev/isxander/yacl/api/Option.java index 5a98d50..6598b80 100644 --- a/src/main/java/dev/isxander/yacl/api/Option.java +++ b/src/main/java/dev/isxander/yacl/api/Option.java @@ -5,7 +5,6 @@ import net.minecraft.text.MutableText; import net.minecraft.text.Text; import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -14,27 +13,70 @@ import java.util.function.Function; import java.util.function.Supplier; public interface Option<T> { + /** + * Name of the option + */ @NotNull Text name(); - @Nullable Text tooltip(); - - @NotNull Control<T> control(); - + /** + * 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(); + /** + * Checks if the pending value is not equal to the current set value + */ boolean changed(); - T pendingValue(); + /** + * 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. + */ void applyValue(); + /** + * Sets the pending value to the bound value. + */ void forgetPendingValue(); + /** + * Sets the pending value to the default bound value. + */ void requestSetDefault(); - static <T> Builder<T> createBuilder(Class<T> clazz) { + /** + * 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<>(); } @@ -43,7 +85,7 @@ public interface Option<T> { private final List<Text> tooltipLines = new ArrayList<>(); - private Function<Option<T>, Control<T>> controlGetter; + private Function<Option<T>, Controller<T>> controlGetter; private Binding<T> binding; @@ -51,6 +93,11 @@ public interface Option<T> { } + /** + * Sets the name to be used by the option. + * + * @see Option#name() + */ public Builder<T> name(@NotNull Text name) { Validate.notNull(name, "`name` cannot be null"); @@ -58,6 +105,13 @@ public interface Option<T> { 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 Builder#build()}. + */ public Builder<T> tooltip(@NotNull Text... tooltips) { Validate.notEmpty(tooltips, "`tooltips` cannot be empty"); @@ -65,13 +119,25 @@ public interface Option<T> { return this; } - public Builder<T> controller(@NotNull Function<Option<T>, Control<T>> control) { + /** + * Sets the controller for the option. + * This is how you interact and change the options. + * + * @see dev.isxander.yacl.gui.controllers + */ + public Builder<T> controller(@NotNull Function<Option<T>, Controller<T>> control) { Validate.notNull(control, "`control` cannot be null"); this.controlGetter = control; return this; } + /** + * Sets the binding for the option. + * Used for default, getter and setter. + * + * @see Binding + */ public Builder<T> binding(@NotNull Binding<T> binding) { Validate.notNull(binding, "`binding` cannot be null"); @@ -79,6 +145,15 @@ public interface Option<T> { return this; } + /** + * Sets the binding for the option. + * Shorthand of {@link Binding#of(Object, Supplier, Consumer)} + * + * @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 + * @see Binding + */ public Builder<T> binding(@NotNull T def, @NotNull Supplier<@NotNull T> getter, @NotNull Consumer<@NotNull T> setter) { Validate.notNull(def, "`def` must not be null"); Validate.notNull(getter, "`getter` must not be null"); diff --git a/src/main/java/dev/isxander/yacl/api/OptionGroup.java b/src/main/java/dev/isxander/yacl/api/OptionGroup.java index bedbc82..6a302c4 100644 --- a/src/main/java/dev/isxander/yacl/api/OptionGroup.java +++ b/src/main/java/dev/isxander/yacl/api/OptionGroup.java @@ -5,18 +5,37 @@ import dev.isxander.yacl.impl.OptionGroupImpl; import net.minecraft.text.Text; import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +/** + * Serves as a separator between multiple chunks of options + * that may be too similar or too few to be placed in a separate {@link ConfigCategory}. + * Or maybe you just want your config to feel less dense. + */ public interface OptionGroup { + /** + * Name of the option group, displayed as a separator in the option lists. + * Can be empty. + */ Text name(); + /** + * List of all options in the group + */ @NotNull ImmutableList<Option<?>> options(); + /** + * Always false when using the {@link Builder} + * used to not render the separator if true + */ boolean isRoot(); + /** + * Creates a builder to construct a {@link OptionGroup} + */ static Builder createBuilder() { return new Builder(); } @@ -29,6 +48,11 @@ public interface OptionGroup { } + /** + * Sets name of the group, can be {@link Text#empty()} to just separate options, like sodium. + * + * @see OptionGroup#name() + */ public Builder name(@NotNull Text name) { Validate.notNull(name, "`name` must not be null"); @@ -36,6 +60,12 @@ public interface OptionGroup { return this; } + /** + * Adds an option to group. + * To construct an option, use {@link Option#createBuilder(Class)} + * + * @see OptionGroup#options() + */ public Builder option(@NotNull Option<?> option) { Validate.notNull(option, "`option` must not be null"); @@ -43,6 +73,19 @@ public interface OptionGroup { return this; } + /** + * Adds multiple options to group. + * To construct an option, use {@link Option#createBuilder(Class)} + * + * @see OptionGroup#options() + */ + public Builder options(@NotNull Collection<Option<?>> options) { + Validate.notEmpty(options, "`options` must not be empty"); + + this.options.addAll(options); + return this; + } + public OptionGroup build() { Validate.notEmpty(options, "`options` must not be empty to build `OptionGroup`"); diff --git a/src/main/java/dev/isxander/yacl/api/YetAnotherConfigLib.java b/src/main/java/dev/isxander/yacl/api/YetAnotherConfigLib.java index a31a4fb..34ccc6a 100644 --- a/src/main/java/dev/isxander/yacl/api/YetAnotherConfigLib.java +++ b/src/main/java/dev/isxander/yacl/api/YetAnotherConfigLib.java @@ -10,21 +10,45 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.function.Consumer; +/** + * Main class of the mod. + * Contains all data and used to provide a {@link Screen} + */ public interface YetAnotherConfigLib { - + /** + * Title of the GUI. Only used for Minecraft narration. + */ Text title(); + /** + * Gets all config categories. + */ ImmutableList<ConfigCategory> categories(); + /** + * Ran when changes are saved. Can be used to save config to a file etc. + */ Runnable saveFunction(); + /** + * Ran every time the YACL screen initialises. Can be paired with FAPI to add custom widgets. + */ Consumer<YACLScreen> initConsumer(); + /** + * Generates a Screen to display based on this instance. + * + * @param parent parent screen to open once closed + */ Screen generateScreen(@Nullable Screen parent); + /** + * Creates a builder to construct YACL + */ static Builder createBuilder() { return new Builder(); } @@ -39,6 +63,11 @@ public interface YetAnotherConfigLib { } + /** + * Sets title of GUI for Minecraft narration + * + * @see YetAnotherConfigLib#title() + */ public Builder title(@NotNull Text title) { Validate.notNull(title, "`title` cannot be null"); @@ -46,6 +75,12 @@ public interface YetAnotherConfigLib { return this; } + /** + * Adds a new category. + * To create a category you need to use {@link ConfigCategory#createBuilder()} + * + * @see YetAnotherConfigLib#categories() + */ public Builder category(@NotNull ConfigCategory category) { Validate.notNull(category, "`category` cannot be null"); @@ -53,6 +88,24 @@ public interface YetAnotherConfigLib { return this; } + /** + * Adds multiple categories at once. + * To create a category you need to use {@link ConfigCategory#createBuilder()} + * + * @see YetAnotherConfigLib#categories() + */ + public Builder categories(@NotNull Collection<ConfigCategory> categories) { + Validate.notEmpty(categories, "`categories` cannot be empty"); + + this.categories.addAll(categories); + return this; + } + + /** + * Used to define a save function for when user clicks the Save Changes button + * + * @see YetAnotherConfigLib#saveFunction() + */ public Builder save(@NotNull Runnable saveFunction) { Validate.notNull(saveFunction, "`saveFunction` cannot be null"); @@ -60,6 +113,11 @@ public interface YetAnotherConfigLib { return this; } + /** + * Defines a consumer that is accepted every time the YACL screen initialises + * + * @see YetAnotherConfigLib#initConsumer() + */ public Builder screenInit(@NotNull Consumer<YACLScreen> initConsumer) { Validate.notNull(initConsumer, "`initConsumer` cannot be null"); diff --git a/src/main/java/dev/isxander/yacl/api/utils/OptionUtils.java b/src/main/java/dev/isxander/yacl/api/utils/OptionUtils.java index ed51683..ab46b5b 100644 --- a/src/main/java/dev/isxander/yacl/api/utils/OptionUtils.java +++ b/src/main/java/dev/isxander/yacl/api/utils/OptionUtils.java @@ -9,20 +9,29 @@ import java.util.function.Consumer; import java.util.function.Function; public class OptionUtils { + /** + * Consumes all options, ignoring groups and categories. + * When consumer returns true, this function stops iterating. + */ public static void consumeOptions(YetAnotherConfigLib yacl, Function<Option<?>, Boolean> consumer) { for (ConfigCategory category : yacl.categories()) { for (OptionGroup group : category.groups()) { for (Option<?> option : group.options()) { - if (!consumer.apply(option)) return; + if (consumer.apply(option)) return; } } } } + /** + * Consumes all options, ignoring groups and categories. + * + * @see OptionUtils#consumeOptions(YetAnotherConfigLib, Function) + */ public static void forEachOptions(YetAnotherConfigLib yacl, Consumer<Option<?>> consumer) { consumeOptions(yacl, (opt) -> { consumer.accept(opt); - return true; + return false; }); } } |