Skip to content

Commit

Permalink
[fix] Fix component rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
bibi-reden committed Oct 2, 2024
1 parent b688663 commit 83fdb68
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,21 @@ import io.wispforest.owo.ui.component.Components
import io.wispforest.owo.ui.container.CollapsibleContainer
import io.wispforest.owo.ui.container.Containers
import io.wispforest.owo.ui.container.FlowLayout
import io.wispforest.owo.ui.core.Component
import io.wispforest.owo.ui.core.Positioning
import io.wispforest.owo.ui.core.Sizing
import io.wispforest.owo.ui.core.VerticalAlignment
import net.minecraft.entity.attribute.ClampedEntityAttribute
import net.minecraft.entity.attribute.EntityAttribute
import net.minecraft.registry.Registries
import net.minecraft.text.Text
import net.minecraft.util.Identifier

class AttributeFunctionProvider(val option: Option<AttributeFunctionConfig>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider {
private val backing = option.value().data.toMutableMap()

private val trackedEntryComponents: MutableMap<Identifier, MutableMap<Identifier, CollapsibleContainer>> = mutableMapOf()
private val headerComponents: MutableMap<Identifier, Component> = mutableMapOf()
private val entryComponents: MutableMap<Identifier, Component> = mutableMapOf()

private fun insertEntry(entryId: Identifier, insertingFunction: AttributeFunction, functions: MutableList<AttributeFunction>, at: Int? = null) {
if (at == null || at >= functions.size) functions.add(insertingFunction)
Expand All @@ -39,17 +42,17 @@ class AttributeFunctionProvider(val option: Option<AttributeFunctionConfig>) : F

private fun getOrCreateEntryContainer(id: Identifier, isDefault: Boolean): CollapsibleFoldableContainer {
return childById(CollapsibleFoldableContainer::class.java, id.toString()) ?: CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), attributeIdToText(id, isDefault), true).also { cf ->
trackedEntryComponents[id] = mutableMapOf()
headerComponents[id] = cf
cf.id(id.toString())

if (!isDefault) {
cf.child(Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(15))
.apply {
verticalAlignment(VerticalAlignment.CENTER)
gap(10)
id("dock")
}
.also { fl ->
cf.child(Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(15))
.apply {
verticalAlignment(VerticalAlignment.CENTER)
gap(10)
id("dock")
}
.also { fl ->
if (!isDefault) {
fl.child(RemoveButtonComponent { backing.remove(id); refreshAndDisplayAttributes() }
.renderer(ButtonRenderers.STANDARD))

Expand Down Expand Up @@ -83,26 +86,25 @@ class AttributeFunctionProvider(val option: Option<AttributeFunctionConfig>) : F
}
.renderer(ButtonRenderers.STANDARD)
)

fl.child(
Components.button(Text.translatable("text.config.data_attributes.buttons.add")) {
backing[id]?.let {
val list = it.toMutableList()
list.add(AttributeFunction())
backing[id] = list
}
refreshAndDisplayAttributes()
}
.renderer(ButtonRenderers.STANDARD)
)
}
)
}

fl.child(
Components.button(Text.translatable("text.config.data_attributes.buttons.add")) {
val entry = backing[id]?.toMutableList() ?: mutableListOf()
entry.add(AttributeFunction())
backing[id] = entry
refreshAndDisplayAttributes(true)
}
.renderer(ButtonRenderers.STANDARD)
)
}
)

child(cf)
}
}

private fun createEntry(function: AttributeFunction, parentId: Identifier, isDefault: Boolean, parent: CollapsibleFoldableContainer, index: Int? = null): CollapsibleContainer {
private fun createEntry(function: AttributeFunction, parentId: Identifier, isDefault: Boolean, parent: CollapsibleFoldableContainer): CollapsibleContainer {
// find if it exists already to ignore the default
val located = parent.childById(CollapsibleContainer::class.java, "${function.id}#child-fn")
if (located != null) return located
Expand All @@ -112,63 +114,62 @@ class AttributeFunctionProvider(val option: Option<AttributeFunctionConfig>) : F
id("${function.id}#child-fn")

val attribute = Registries.ATTRIBUTE[function.id]
if (attribute == null) {
if (attribute !is EntityAttribute) {
titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid"))
} else if (isDefault) {
titleLayout().tooltip(Text.translatable("text.config.data_attributes_data_entry.default"))
} else {
if (attribute is ClampedEntityAttribute) {
tooltip(Text.translatable("text.config.data_attributes.data_entry.function_child", function.id, attribute.minValue, attribute.maxValue))
titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.function_child", function.id, attribute.minValue, attribute.maxValue))
}
}

child(Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(15))
.apply {
verticalAlignment(VerticalAlignment.BOTTOM)
gap(10)
}
.also { fl ->
if (!isDefault) {
if (!isDefault) {
child(Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(15))
.apply {
verticalAlignment(VerticalAlignment.BOTTOM)
gap(10)
}
.also { fl ->
fl.child(RemoveButtonComponent { backing[parentId]?.let { backing[parentId] = it.filter { it.id != function.id } }; refreshAndDisplayAttributes() }
.renderer(ButtonRenderers.STANDARD))
}

fl.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) {
if (fl.childById(FlowLayout::class.java, "edit-field") == null) {
val field = EditFieldComponent(
{ field, str ->
val predId = Identifier.tryParse(str) ?: return@EditFieldComponent true
if (backing[parentId]?.find { it.id == predId } != null) {
field.textBox.setEditableColor(0xe54d48)
}
else if (!Registries.ATTRIBUTE.containsId(predId)) {
field.textBox.setEditableColor(0xf2e1c0)
}
else {
field.textBox.setEditableColor(0x69d699)
}
true
},
{
val newId = Identifier.tryParse(it.textBox.text.toString()) ?: return@EditFieldComponent
val newFunction = function.copy(id = newId)
val currentList = backing[parentId]
if (!Registries.ATTRIBUTE.containsId(newId) || currentList?.find { it.id == newId } != null) return@EditFieldComponent
// ensured that this exists and is possible to swap
val list = currentList?.filter { it.id != function.id }?.toMutableList() ?: return@EditFieldComponent
list.add(0, newFunction)
backing[parentId] = list
refreshAndDisplayAttributes()
},
EditFieldComponent::remove
)
child(0, field)
fl.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) {
if (fl.childById(FlowLayout::class.java, "edit-field") == null) {
val field = EditFieldComponent(
{ field, str ->
val predId = Identifier.tryParse(str) ?: return@EditFieldComponent true
if (backing[parentId]?.find { it.id == predId } != null) {
field.textBox.setEditableColor(0xe54d48)
}
else if (!Registries.ATTRIBUTE.containsId(predId)) {
field.textBox.setEditableColor(0xf2e1c0)
}
else {
field.textBox.setEditableColor(0x69d699)
}
true
},
{
val newId = Identifier.tryParse(it.textBox.text.toString()) ?: return@EditFieldComponent
val newFunction = function.copy(id = newId)
val currentList = backing[parentId]
if (!Registries.ATTRIBUTE.containsId(newId) || currentList?.find { it.id == newId } != null) return@EditFieldComponent
// ensured that this exists and is possible to swap
val list = currentList?.filter { it.id != function.id }?.toMutableList() ?: return@EditFieldComponent
list.add(0, newFunction)
backing[parentId] = list
refreshAndDisplayAttributes()
},
EditFieldComponent::remove
)
child(0, field)
}
}
.renderer(ButtonRenderers.STANDARD)
)
}
.renderer(ButtonRenderers.STANDARD)
)
}
)
)
}

child(textBoxComponent(
Text.translatable("text.config.data_attributes.data_entry.functions.value"),
Expand All @@ -177,7 +178,7 @@ class AttributeFunctionProvider(val option: Option<AttributeFunctionConfig>) : F
onChange = {
it.toDoubleOrNull()?.let { v ->
backing[parentId] = (backing.remove(parentId)?.toMutableList() ?: mutableListOf()).apply {
insertEntry(parentId, function.copy(value = v), this, index)
insertEntry(parentId, function.copy(value = v), this)
}
refreshAndDisplayAttributes()
}
Expand All @@ -198,7 +199,7 @@ class AttributeFunctionProvider(val option: Option<AttributeFunctionConfig>) : F
it.message = Text.translatable("text.config.data_attributes.enum.functionBehavior.${function.behavior.name.lowercase()}")

backing[parentId] = (backing.remove(parentId)?.toMutableList() ?: mutableListOf()).apply {
insertEntry(parentId, function.copy(behavior = function.behavior), this, index)
insertEntry(parentId, function.copy(behavior = function.behavior), this)
}

refreshAndDisplayAttributes()
Expand All @@ -212,8 +213,8 @@ class AttributeFunctionProvider(val option: Option<AttributeFunctionConfig>) : F
child(SearchAnchorComponent(titleLayout(), Option.Key.ROOT, { function.id.toString() }, { Text.translatable(function.id.toTranslationKey()).toString() }))
}

if (index != null) parent.child(index, container) else parent.child(container)
trackedEntryComponents[parentId]!![function.id] = container
parent.child(container)
entryComponents[function.id] = container

// force a rearrangement to bring the dock up top~
parent.childById(FlowLayout::class.java, "dock")?.let {
Expand All @@ -227,24 +228,23 @@ class AttributeFunctionProvider(val option: Option<AttributeFunctionConfig>) : F
private fun createFunctionEntries(functions: List<AttributeFunction>, parentId: Identifier, parent: CollapsibleFoldableContainer) {
functions.forEachIndexed { index, function ->
val isDefault = backing[parentId]?.find { it.id == function.id } == null
createEntry(function, parentId, isDefault, parent, index)
createEntry(function, parentId, isDefault, parent)
}
}

private fun refreshAndDisplayAttributes() {
for ((key, map) in trackedEntryComponents) {
for (container in map.values) {
container.id(null)
container.remove()
}
map.clear()

// ensure cleanup of dead keys
if (key !in backing) childById(CollapsibleContainer::class.java, key.toString())?.also {
it.id(null)
it.remove()
private fun refreshAndDisplayAttributes(clearHeaders: Boolean = true) {
if (clearHeaders) {
headerComponents.values.forEach { component ->
component.id(null)
component.remove()
}
headerComponents.clear()
}
entryComponents.values.forEach { component ->
component.id(null)
component.remove()
}
entryComponents.clear()

for ((id, functions) in backing) {
createFunctionEntries(functions, id, getOrCreateEntryContainer(id, !backing.containsKey(id)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import net.minecraft.text.Text
import net.minecraft.util.Identifier

class EntityTypesProvider(val option: Option<Map<Identifier, EntityTypeData>>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider {
val backing = HashMap(option.value())
private val backing = HashMap(option.value())

val headerComponents: MutableMap<Identifier, Component> = mutableMapOf()
val entryComponents: MutableMap<Identifier, Component> = mutableMapOf()
private val headerComponents: MutableMap<Identifier, Component> = mutableMapOf()
private val entryComponents: MutableMap<Identifier, Component> = mutableMapOf()

private fun createEntries(id: Identifier, types: Map<Identifier, Double>, isDefault: Boolean = false): CollapsibleFoldableContainer {
val container = childById(CollapsibleFoldableContainer::class.java, id.toString()) ?: CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), entityTypeIdentifierToText(id, isDefault), true).also { ct ->
Expand Down

0 comments on commit 83fdb68

Please sign in to comment.