aboutsummaryrefslogtreecommitdiff
path: root/common/src/main/java/dev/isxander/yacl/impl
diff options
context:
space:
mode:
authorisXander <xandersmith2008@gmail.com>2023-05-21 12:41:45 +0100
committerisXander <xandersmith2008@gmail.com>2023-05-21 12:41:45 +0100
commit21afea0da3956f2d8cca81a54fa9820152e0c077 (patch)
treee5944f94a5f85d3fcbe048da633e62f5357fe835 /common/src/main/java/dev/isxander/yacl/impl
parente51af159ba3eba5ebda976bea1c1957cddeee7c6 (diff)
downloadYetAnotherConfigLib-21afea0da3956f2d8cca81a54fa9820152e0c077.tar.gz
YetAnotherConfigLib-21afea0da3956f2d8cca81a54fa9820152e0c077.tar.bz2
YetAnotherConfigLib-21afea0da3956f2d8cca81a54fa9820152e0c077.zip
Start overhauling UI
Diffstat (limited to 'common/src/main/java/dev/isxander/yacl/impl')
-rw-r--r--common/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java17
-rw-r--r--common/src/main/java/dev/isxander/yacl/impl/LabelOptionImpl.java10
-rw-r--r--common/src/main/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java5
-rw-r--r--common/src/main/java/dev/isxander/yacl/impl/ListOptionImpl.java15
-rw-r--r--common/src/main/java/dev/isxander/yacl/impl/OptionDescriptionImpl.java124
-rw-r--r--common/src/main/java/dev/isxander/yacl/impl/OptionImpl.java40
6 files changed, 188 insertions, 23 deletions
diff --git a/common/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java b/common/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java
index 11da99e..f0e0bdd 100644
--- a/common/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java
+++ b/common/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java
@@ -19,7 +19,7 @@ import java.util.function.Function;
@ApiStatus.Internal
public final class ButtonOptionImpl implements ButtonOption {
private final Component name;
- private final Component tooltip;
+ private final OptionDescription description;
private final BiConsumer<YACLScreen, ButtonOption> action;
private boolean available;
private final Controller<BiConsumer<YACLScreen, ButtonOption>> controller;
@@ -27,13 +27,13 @@ public final class ButtonOptionImpl implements ButtonOption {
public ButtonOptionImpl(
@NotNull Component name,
- @Nullable Component tooltip,
+ @Nullable OptionDescription description,
@NotNull BiConsumer<YACLScreen, ButtonOption> action,
boolean available,
@NotNull Function<ButtonOption, Controller<BiConsumer<YACLScreen, ButtonOption>>> controlGetter
) {
this.name = name;
- this.tooltip = tooltip;
+ this.description = description;
this.action = action;
this.available = available;
this.controller = controlGetter.apply(this);
@@ -46,8 +46,13 @@ public final class ButtonOptionImpl implements ButtonOption {
}
@Override
+ public @NotNull OptionDescription description() {
+ return description;
+ }
+
+ @Override
public @NotNull Component tooltip() {
- return tooltip;
+ return description().description();
}
@Override
@@ -162,7 +167,7 @@ public final class ButtonOptionImpl implements ButtonOption {
public Builder tooltip(@NotNull Component... tooltips) {
Validate.notNull(tooltips, "`tooltips` cannot be empty");
- tooltipLines.addAll(List.of(tooltips));
+ //tooltipLines.addAll(List.of(tooltips));
return this;
}
@@ -212,7 +217,7 @@ public final class ButtonOptionImpl implements ButtonOption {
concatenatedTooltip.append(line);
}
- return new ButtonOptionImpl(name, concatenatedTooltip, action, available, controlGetter);
+ return new ButtonOptionImpl(name, OptionDescription.createBuilder().name(name).description(concatenatedTooltip).build(), action, available, controlGetter);
}
}
}
diff --git a/common/src/main/java/dev/isxander/yacl/impl/LabelOptionImpl.java b/common/src/main/java/dev/isxander/yacl/impl/LabelOptionImpl.java
index 732a373..2a7759c 100644
--- a/common/src/main/java/dev/isxander/yacl/impl/LabelOptionImpl.java
+++ b/common/src/main/java/dev/isxander/yacl/impl/LabelOptionImpl.java
@@ -19,6 +19,7 @@ import java.util.function.BiConsumer;
public final class LabelOptionImpl implements LabelOption {
private final Component label;
private final Component name = Component.literal("Label Option");
+ private final OptionDescription description;
private final Component tooltip = Component.empty();
private final LabelController labelController;
private final Binding<Component> binding;
@@ -27,6 +28,10 @@ public final class LabelOptionImpl implements LabelOption {
this.label = label;
this.labelController = new LabelController(this);
this.binding = Binding.immutable(label);
+ this.description = OptionDescription.createBuilder()
+ .name(this.name)
+ .description(this.label)
+ .build();
}
@Override
@@ -40,6 +45,11 @@ public final class LabelOptionImpl implements LabelOption {
}
@Override
+ public @NotNull OptionDescription description() {
+ return description;
+ }
+
+ @Override
public @NotNull Component tooltip() {
return tooltip;
}
diff --git a/common/src/main/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java b/common/src/main/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java
index c15efe6..d02259e 100644
--- a/common/src/main/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java
+++ b/common/src/main/java/dev/isxander/yacl/impl/ListOptionEntryImpl.java
@@ -34,6 +34,11 @@ public final class ListOptionEntryImpl<T> implements ListOptionEntry<T> {
}
@Override
+ public @NotNull OptionDescription description() {
+ return group.description();
+ }
+
+ @Override
public @NotNull Component tooltip() {
return Component.empty();
}
diff --git a/common/src/main/java/dev/isxander/yacl/impl/ListOptionImpl.java b/common/src/main/java/dev/isxander/yacl/impl/ListOptionImpl.java
index f47493c..24fe2b1 100644
--- a/common/src/main/java/dev/isxander/yacl/impl/ListOptionImpl.java
+++ b/common/src/main/java/dev/isxander/yacl/impl/ListOptionImpl.java
@@ -19,7 +19,7 @@ import java.util.stream.Collectors;
@ApiStatus.Internal
public final class ListOptionImpl<T> implements ListOption<T> {
private final Component name;
- private final Component tooltip;
+ private final OptionDescription description;
private final Binding<List<T>> binding;
private final T initialValue;
private final List<ListOptionEntry<T>> entries;
@@ -31,9 +31,9 @@ public final class ListOptionImpl<T> implements ListOption<T> {
private final List<BiConsumer<Option<List<T>>, List<T>>> listeners;
private final List<Runnable> refreshListeners;
- public ListOptionImpl(@NotNull Component name, @NotNull Component tooltip, @NotNull Binding<List<T>> binding, @NotNull T initialValue, @NotNull Class<T> typeClass, @NotNull Function<ListOptionEntry<T>, Controller<T>> controllerFunction, ImmutableSet<OptionFlag> flags, boolean collapsed, boolean available, Collection<BiConsumer<Option<List<T>>, List<T>>> listeners) {
+ public ListOptionImpl(@NotNull Component name, @NotNull OptionDescription description, @NotNull Binding<List<T>> binding, @NotNull T initialValue, @NotNull Class<T> typeClass, @NotNull Function<ListOptionEntry<T>, Controller<T>> controllerFunction, ImmutableSet<OptionFlag> flags, boolean collapsed, boolean available, Collection<BiConsumer<Option<List<T>>, List<T>>> listeners) {
this.name = name;
- this.tooltip = tooltip;
+ this.description = description;
this.binding = binding;
this.initialValue = initialValue;
this.entryFactory = new EntryFactory(controllerFunction);
@@ -54,8 +54,13 @@ public final class ListOptionImpl<T> implements ListOption<T> {
}
@Override
+ public @NotNull OptionDescription description() {
+ return this.description;
+ }
+
+ @Override
public @NotNull Component tooltip() {
- return this.tooltip;
+ return description().description();
}
@Override
@@ -332,7 +337,7 @@ public final class ListOptionImpl<T> implements ListOption<T> {
concatenatedTooltip.append(line);
}
- return new ListOptionImpl<>(name, concatenatedTooltip, binding, initialValue, typeClass, controllerFunction, ImmutableSet.copyOf(flags), collapsed, available, listeners);
+ return new ListOptionImpl<>(name, OptionDescription.createBuilder().name(name).description(concatenatedTooltip).build(), binding, initialValue, typeClass, controllerFunction, ImmutableSet.copyOf(flags), collapsed, available, listeners);
}
}
}
diff --git a/common/src/main/java/dev/isxander/yacl/impl/OptionDescriptionImpl.java b/common/src/main/java/dev/isxander/yacl/impl/OptionDescriptionImpl.java
new file mode 100644
index 0000000..f57a410
--- /dev/null
+++ b/common/src/main/java/dev/isxander/yacl/impl/OptionDescriptionImpl.java
@@ -0,0 +1,124 @@
+package dev.isxander.yacl.impl;
+
+import dev.isxander.yacl.api.OptionDescription;
+import dev.isxander.yacl.gui.ImageRenderer;
+import net.minecraft.ChatFormatting;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.ResourceLocation;
+import org.apache.commons.lang3.Validate;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+
+public record OptionDescriptionImpl(Component descriptiveName, Component description, CompletableFuture<Optional<ImageRenderer>> image) implements OptionDescription {
+ public static class BuilderImpl implements Builder {
+ private Component name;
+ private Component description;
+ private CompletableFuture<Optional<ImageRenderer>> image = CompletableFuture.completedFuture(Optional.empty());
+ private boolean imageUnset = true;
+
+ @Override
+ public Builder name(Component name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public Builder description(Component description) {
+ this.description = description;
+ return this;
+ }
+
+ @Override
+ public Builder image(ResourceLocation image, int width, int height) {
+ Validate.isTrue(imageUnset, "Image already set!");
+ Validate.isTrue(width > 0, "Width must be greater than 0!");
+ Validate.isTrue(height > 0, "Height must be greater than 0!");
+
+ this.image = CompletableFuture.completedFuture(Optional.of(new ImageRenderer.TextureBacked(image, width, height)));
+ imageUnset = false;
+ return this;
+ }
+
+ @Override
+ public Builder image(Path path, ResourceLocation uniqueLocation) {
+ Validate.isTrue(imageUnset, "Image already set!");
+ this.image = CompletableFuture.supplyAsync(() -> ImageRenderer.NativeImageBacked.createFromPath(path, uniqueLocation));
+ imageUnset = false;
+ return this;
+ }
+
+ @Override
+ public Builder gifImage(ResourceLocation image) {
+ Validate.isTrue(imageUnset, "Image already set!");
+ this.image = CompletableFuture.supplyAsync(() -> {
+ try {
+ return Optional.of(ImageRenderer.AnimatedNativeImageBacked.createGIFFromTexture(image));
+ } catch (IOException e) {
+ e.printStackTrace();
+ return Optional.empty();
+ }
+ });
+ imageUnset = false;
+ return this;
+ }
+
+ @Override
+ public Builder gifImage(Path path, ResourceLocation uniqueLocation) {
+ Validate.isTrue(imageUnset, "Image already set!");
+ this.image = CompletableFuture.supplyAsync(() -> {
+ try {
+ return Optional.of(ImageRenderer.AnimatedNativeImageBacked.createGIF(new FileInputStream(path.toFile()), uniqueLocation));
+ } catch (IOException e) {
+ e.printStackTrace();
+ return Optional.empty();
+ }
+ });
+ imageUnset = false;
+ return this;
+ }
+
+ @Override
+ public Builder webpImage(ResourceLocation image, int frameDelayMS) {
+ Validate.isTrue(imageUnset, "Image already set!");
+ this.image = CompletableFuture.supplyAsync(() -> {
+ try {
+ return Optional.of(ImageRenderer.AnimatedNativeImageBacked.createWEBPFromTexture(image, frameDelayMS));
+ } catch (IOException e) {
+ e.printStackTrace();
+ return Optional.empty();
+ }
+ });
+ imageUnset = false;
+ return this;
+ }
+
+ @Override
+ public Builder webpImage(Path path, ResourceLocation uniqueLocation, int frameDelayMS) {
+ Validate.isTrue(imageUnset, "Image already set!");
+ this.image = CompletableFuture.supplyAsync(() -> {
+ try {
+ return Optional.of(ImageRenderer.AnimatedNativeImageBacked.createWEBP(new FileInputStream(path.toFile()), uniqueLocation, frameDelayMS));
+ } catch (IOException e) {
+ e.printStackTrace();
+ return Optional.empty();
+ }
+ });
+ imageUnset = false;
+ return this;
+ }
+
+ @Override
+ public OptionDescription build() {
+ Validate.notNull(name, "Name must be set!");
+
+ if (description == null)
+ description = Component.empty();
+
+ return new OptionDescriptionImpl(name.copy().withStyle(ChatFormatting.BOLD), description, image);
+ }
+ }
+}
diff --git a/common/src/main/java/dev/isxander/yacl/impl/OptionImpl.java b/common/src/main/java/dev/isxander/yacl/impl/OptionImpl.java
index 4b65d56..ef4d13b 100644
--- a/common/src/main/java/dev/isxander/yacl/impl/OptionImpl.java
+++ b/common/src/main/java/dev/isxander/yacl/impl/OptionImpl.java
@@ -1,11 +1,9 @@
package dev.isxander.yacl.impl;
import com.google.common.collect.ImmutableSet;
-import dev.isxander.yacl.api.Binding;
-import dev.isxander.yacl.api.Controller;
-import dev.isxander.yacl.api.Option;
-import dev.isxander.yacl.api.OptionFlag;
+import dev.isxander.yacl.api.*;
import net.minecraft.ChatFormatting;
+import net.minecraft.Util;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentContents;
import net.minecraft.network.chat.MutableComponent;
@@ -23,7 +21,7 @@ import java.util.function.Supplier;
@ApiStatus.Internal
public final class OptionImpl<T> implements Option<T> {
private final Component name;
- private Component tooltip;
+ private OptionDescription description;
private final Controller<T> controller;
private final Binding<T> binding;
private boolean available;
@@ -38,7 +36,7 @@ public final class OptionImpl<T> implements Option<T> {
public OptionImpl(
@NotNull Component name,
- @Nullable Function<T, Component> tooltipGetter,
+ @NotNull Function<T, OptionDescription> descriptionFunction,
@NotNull Function<Option<T>, Controller<T>> controlGetter,
@NotNull Binding<T> binding,
boolean available,
@@ -54,7 +52,9 @@ public final class OptionImpl<T> implements Option<T> {
this.listeners = new ArrayList<>(listeners);
this.controller = controlGetter.apply(this);
- addListener((opt, pending) -> tooltip = tooltipGetter.apply(pending));
+ var memoizedDescriptionFunction = Util.memoize(descriptionFunction);
+ addListener((opt, pending) -> description = memoizedDescriptionFunction.apply(pending));
+
requestSet(binding().getValue());
}
@@ -64,8 +64,13 @@ public final class OptionImpl<T> implements Option<T> {
}
@Override
+ public @NotNull OptionDescription description() {
+ return this.description;
+ }
+
+ @Override
public @NotNull Component tooltip() {
- return tooltip;
+ return description.description();
}
@Override
@@ -147,6 +152,7 @@ public final class OptionImpl<T> implements Option<T> {
public static class BuilderImpl<T> implements Builder<T> {
private Component name = Component.literal("Name not specified!").withStyle(ChatFormatting.RED);
+ private Function<T, OptionDescription> descriptionFunction = null;
private final List<Function<T, Component>> tooltipGetters = new ArrayList<>();
private Function<Option<T>, Controller<T>> controlGetter;
@@ -176,6 +182,17 @@ public final class OptionImpl<T> implements Option<T> {
}
@Override
+ public Builder<T> description(@NotNull OptionDescription description) {
+ return description(opt -> description);
+ }
+
+ @Override
+ public Builder<T> description(@NotNull Function<T, OptionDescription> descriptionFunction) {
+ this.descriptionFunction = descriptionFunction;
+ return this;
+ }
+
+ @Override
public Builder<T> tooltip(@NotNull Function<T, Component> tooltipGetter) {
Validate.notNull(tooltipGetter, "`tooltipGetter` cannot be null");
@@ -292,12 +309,11 @@ public final class OptionImpl<T> implements Option<T> {
return concatenatedTooltip;
};
-
- if (instant) {
- listeners.add((opt, pendingValue) -> opt.applyValue());
+ if (descriptionFunction == null) {
+ descriptionFunction = opt -> OptionDescription.createBuilder().name(name).description(concatenatedTooltipGetter.apply(opt)).build();
}
- return new OptionImpl<>(name, concatenatedTooltipGetter, controlGetter, binding, available, ImmutableSet.copyOf(flags), typeClass, listeners);
+ return new OptionImpl<>(name, descriptionFunction, controlGetter, binding, available, ImmutableSet.copyOf(flags), typeClass, listeners);
}
}
}