diff options
Diffstat (limited to 'src/main/kotlin/dev/isxander/yacl3/dsl/API.kt')
-rw-r--r-- | src/main/kotlin/dev/isxander/yacl3/dsl/API.kt | 183 |
1 files changed, 128 insertions, 55 deletions
diff --git a/src/main/kotlin/dev/isxander/yacl3/dsl/API.kt b/src/main/kotlin/dev/isxander/yacl3/dsl/API.kt index 87778e5..cd2c483 100644 --- a/src/main/kotlin/dev/isxander/yacl3/dsl/API.kt +++ b/src/main/kotlin/dev/isxander/yacl3/dsl/API.kt @@ -1,63 +1,154 @@ package dev.isxander.yacl3.dsl import dev.isxander.yacl3.api.* +import net.minecraft.network.chat.CommonComponents import net.minecraft.network.chat.Component +import java.util.concurrent.CompletableFuture +import kotlin.properties.ReadOnlyProperty -interface YACLDsl { - val namespaceKey: String +interface Buildable<T> { + val built: CompletableFuture<T> - val categories: YACLDslReference + fun build(): T +} - fun title(component: Component) - fun title(block: () -> Component) +fun <T> CompletableFuture<T>.onReady(block: (T) -> Unit) = + this.whenComplete { result, _ -> result?.let(block) } - fun category(id: String, block: CategoryDsl.() -> Unit): ConfigCategory +operator fun <T> CompletableFuture<out ParentRegistrar<*, *, T>>.get(id: String): CompletableFuture<T> = + thenCompose { it[id] } - fun save(block: () -> Unit) +typealias FutureOption<T> = CompletableFuture<Option<T>> + +fun <T> CompletableFuture<OptionRegistrar>.futureRef(id: String): FutureOption<T> = + thenCompose { it.futureRef(id) } + +fun YetAnotherConfigLib(id: String, block: RootDsl.() -> Unit) = + RootDslImpl(id).apply(block).build() + +interface ParentRegistrar<T, DSL, INNER> { + fun register(id: String, registrant: T): T + + fun register(id: String, block: DSL.() -> Unit): T + + /** Registers a registrant via delegation - if id is not provided, the delegated property name is used */ + fun registering(id: String? = null, block: DSL.() -> Unit): RegisterableActionDelegateProvider<DSL, T> + + /** Creates a delegated future reference to a registrant that may or may not exist yet */ + val futureRef: ReadOnlyProperty<Any?, CompletableFuture<T>> + + /** Creates a future reference to a registrant that may or may not exist yet */ + fun futureRef(id: String): CompletableFuture<T> + + /** Gets a registrant with the id, if it exists */ + fun ref(id: String): T? + + /** Creates a delegated property that returns a registrant with a matching id, or null if it does not exist at the time of calling */ + val ref: ReadOnlyProperty<Any?, T?> + + operator fun get(id: String): CompletableFuture<INNER> } -interface OptionAddableDsl { - fun <T : Any> option(id: String, block: OptionDsl<T>.() -> Unit): Option<T> +interface OptionRegistrar { + /** Registers an option that has already been built. */ + fun <T, OPT : Option<T>> register(id: String, option: OPT): OPT + + /** Registers a regular option */ + fun <T> register(id: String, block: OptionDsl<T>.() -> Unit): Option<T> + + /** Registers a regular option via delegation */ + fun <T> registering(id: String? = null, block: OptionDsl<T>.() -> Unit): RegisterableActionDelegateProvider<OptionDsl<T>, Option<T>> + + fun <T> futureRef(id: String): CompletableFuture<Option<T>> + fun <T> futureRef(): RegisterableDelegateProvider<CompletableFuture<Option<T>>> + + fun <T> ref(id: String? = null): ReadOnlyProperty<Any?, Option<T>?> + + + fun registerLabel(id: String): LabelOption + val registeringLabel: RegisterableDelegateProvider<LabelOption> + + fun registerLabel(id: String, text: Component): LabelOption + + fun registerLabel(id: String, builder: TextLineBuilderDsl.() -> Unit): LabelOption + + fun registerButton(id: String, block: ButtonOptionDsl.() -> Unit): ButtonOption + fun registeringButton(id: String? = null, block: ButtonOptionDsl.() -> Unit): RegisterableActionDelegateProvider<ButtonOptionDsl, ButtonOption> } -interface CategoryDsl : OptionAddableDsl { - val groups: CategoryDslReference - val options: GroupDslReference +typealias CategoryRegistrar = ParentRegistrar<ConfigCategory, CategoryDsl, GroupRegistrar> +typealias GroupRegistrar = ParentRegistrar<OptionGroup, GroupDsl, OptionRegistrar> + +interface RootDsl { + val rootKey: String + val rootId: String + val thisRoot: CompletableFuture<YetAnotherConfigLib> - fun group(id: String, block: GroupDsl.() -> Unit): OptionGroup + val categories: CategoryRegistrar + + fun title(component: Component) + fun title(block: () -> Component) + + fun screenInit(block: () -> Unit) + fun save(block: () -> Unit) +} + +interface CategoryDsl : Buildable<ConfigCategory> { + val categoryKey: String + val categoryId: String + val thisCategory: CompletableFuture<ConfigCategory> + + val groups: GroupRegistrar + val rootOptions: OptionRegistrar fun name(component: Component) fun name(block: () -> Component) fun tooltip(vararg component: Component) - fun tooltipBuilder(block: TooltipBuilderDsl.() -> Unit) - fun useDefaultTooltip(lines: Int = 1) + fun tooltip(block: TextLineBuilderDsl.() -> Unit) } -interface GroupDsl : OptionAddableDsl { - val options: GroupDslReference +interface GroupDsl : Buildable<OptionGroup> { + val groupKey: String + val groupId: String + val thisGroup: CompletableFuture<OptionGroup> + + val options: OptionRegistrar fun name(component: Component) fun name(block: () -> Component) - fun descriptionBuilder(block: OptionDescription.Builder.() -> Unit) fun description(description: OptionDescription) - fun useDefaultDescription(lines: Int = 1) + fun descriptionBuilder(block: OptionDescription.Builder.() -> Unit) + fun OptionDescription.Builder.addDefaultText(lines: Int? = null) = + addDefaultText("$groupKey.description", lines) +} + +interface OptionDsl<T> : Option.Builder<T>, Buildable<Option<T>> { + val optionKey: String + val optionId: String + val thisOption: CompletableFuture<Option<T>> + + fun OptionDescription.Builder.addDefaultText(lines: Int? = null) = + addDefaultText("$optionKey.description", lines) } -interface OptionDsl<T> : Option.Builder<T> { - val option: FutureValue<Option<T>> +interface ButtonOptionDsl : ButtonOption.Builder, Buildable<ButtonOption> { + val optionKey: String + val optionId: String + val thisOption: CompletableFuture<ButtonOption> - fun OptionDescription.Builder.addDefaultDescription(lines: Int? = null) + fun OptionDescription.Builder.addDefaultText(lines: Int? = null) = + addDefaultText("$optionKey.description", lines) } -interface TooltipBuilderDsl { +interface TextLineBuilderDsl { fun text(component: Component) fun text(block: () -> Component) operator fun Component.unaryPlus() - class Delegate(private val tooltipFunction: (Component) -> Unit) : TooltipBuilderDsl { + class Delegate(private val tooltipFunction: (Component) -> Unit) : TextLineBuilderDsl { override fun text(component: Component) { tooltipFunction(component) } @@ -70,36 +161,18 @@ interface TooltipBuilderDsl { text(this) } } -} - -interface YACLDslReference : Reference<CategoryDslReference> { - fun get(): YetAnotherConfigLib? - - val isBuilt: Boolean - - fun registering(block: CategoryDsl.() -> Unit): RegisterableDelegateProvider<CategoryDsl, ConfigCategory> -} -interface CategoryDslReference : Reference<GroupDslReference> { - fun get(): ConfigCategory? - - val root: GroupDslReference - - val isBuilt: Boolean - - fun registering(block: GroupDsl.() -> Unit): RegisterableDelegateProvider<GroupDsl, OptionGroup> -} - -interface GroupDslReference { - fun get(): OptionGroup? - - operator fun <T> get(id: String): FutureValue<Option<T>> - - val isBuilt: Boolean - - fun <T : Any> registering(block: OptionDsl<T>.() -> Unit): RegisterableDelegateProvider<OptionDsl<T>, Option<T>> + companion object { + fun createText(block: TextLineBuilderDsl.() -> Unit): Component { + val text = Component.empty() + var first = true + val builder = Delegate { + if (!first) text.append(CommonComponents.NEW_LINE) + text.append(it) + first = false + } + block(builder) + return text + } + } } - - - - |