mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-03 13:58:28 +08:00
Slightly optimized bindChildrenTo for the frequent case where all list cell elements have been replaced.
This commit is contained in:
parent
e492b28aac
commit
4792dc1172
@ -65,9 +65,12 @@ abstract class AbstractDependentListCell<E> :
|
||||
observer(
|
||||
ListChangeEvent(
|
||||
value,
|
||||
listOf(
|
||||
ListChange.Structural(index = 0, removed = emptyList(), inserted = value),
|
||||
),
|
||||
listOf(ListChange.Structural(
|
||||
index = 0,
|
||||
prevSize = 0,
|
||||
removed = emptyList(),
|
||||
inserted = value,
|
||||
)),
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -81,7 +84,15 @@ abstract class AbstractDependentListCell<E> :
|
||||
computeElements()
|
||||
|
||||
emitDependencyChanged(
|
||||
ListChangeEvent(elements, listOf(ListChange.Structural(0, oldElements, elements)))
|
||||
ListChangeEvent(
|
||||
elements,
|
||||
listOf(ListChange.Structural(
|
||||
index = 0,
|
||||
prevSize = oldElements.size,
|
||||
removed = oldElements,
|
||||
inserted = elements,
|
||||
)),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -49,9 +49,12 @@ abstract class AbstractListCell<E> : AbstractCell<List<E>>(), ListCell<E> {
|
||||
observer(
|
||||
ListChangeEvent(
|
||||
value,
|
||||
listOf(
|
||||
ListChange.Structural(index = 0, removed = emptyList(), inserted = value),
|
||||
),
|
||||
listOf(ListChange.Structural(
|
||||
index = 0,
|
||||
prevSize = 0,
|
||||
removed = emptyList(),
|
||||
inserted = value
|
||||
)),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ class FilteredListCell<E>(
|
||||
|
||||
override fun dependencyChanged(dependency: Dependency, event: ChangeEvent<*>?) {
|
||||
if (event is ListChangeEvent<*>) {
|
||||
val prevSize = elements.size
|
||||
val filteredChanges = mutableListOf<ListChange<E>>()
|
||||
|
||||
for (change in event.changes) {
|
||||
@ -95,6 +96,7 @@ class FilteredListCell<E>(
|
||||
filteredChanges.add(
|
||||
ListChange.Structural(
|
||||
eventIndex,
|
||||
prevSize,
|
||||
removed,
|
||||
inserted
|
||||
)
|
||||
@ -140,6 +142,7 @@ class FilteredListCell<E>(
|
||||
filteredChanges.add(
|
||||
ListChange.Structural(
|
||||
insertIndex,
|
||||
prevSize,
|
||||
removed = emptyList(),
|
||||
inserted = listOf(change.updated),
|
||||
)
|
||||
@ -167,6 +170,7 @@ class FilteredListCell<E>(
|
||||
filteredChanges.add(
|
||||
ListChange.Structural(
|
||||
index,
|
||||
prevSize,
|
||||
removed = listOf(change.updated),
|
||||
inserted = emptyList(),
|
||||
)
|
||||
|
@ -32,7 +32,15 @@ class ImmutableListCell<E>(private val elements: List<E>) : AbstractDependency()
|
||||
|
||||
override fun observeList(callNow: Boolean, observer: ListObserver<E>): Disposable {
|
||||
if (callNow) {
|
||||
observer(ListChangeEvent(value, listOf(ListChange.Structural(0, emptyList(), value))))
|
||||
observer(ListChangeEvent(
|
||||
value,
|
||||
listOf(ListChange.Structural(
|
||||
index = 0,
|
||||
prevSize = 0,
|
||||
removed = emptyList(),
|
||||
inserted = value,
|
||||
)),
|
||||
))
|
||||
}
|
||||
|
||||
return nopDisposable()
|
||||
|
@ -13,6 +13,7 @@ sealed class ListChange<out E> {
|
||||
*/
|
||||
class Structural<out E>(
|
||||
val index: Int,
|
||||
val prevSize: Int,
|
||||
/**
|
||||
* The elements that were removed from the list at [index].
|
||||
*
|
||||
@ -27,7 +28,9 @@ sealed class ListChange<out E> {
|
||||
* be mutated when the originating [ListCell] is mutated.
|
||||
*/
|
||||
val inserted: List<E>,
|
||||
) : ListChange<E>()
|
||||
) : ListChange<E>() {
|
||||
val allRemoved: Boolean get() = removed.size == prevSize
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a change to an element in a list cell. Will only be emitted if the list is
|
||||
|
@ -50,7 +50,12 @@ class SimpleListCell<E>(
|
||||
elementDependents[index] = ElementDependent(index, element)
|
||||
}
|
||||
|
||||
changes.add(ListChange.Structural(index, listOf(removed), listOf(element)))
|
||||
changes.add(ListChange.Structural(
|
||||
index,
|
||||
prevSize = elements.size,
|
||||
removed = listOf(removed),
|
||||
inserted = listOf(element),
|
||||
))
|
||||
ChangeManager.changed(this)
|
||||
|
||||
return removed
|
||||
@ -63,17 +68,23 @@ class SimpleListCell<E>(
|
||||
copyAndResetWrapper()
|
||||
elements.add(element)
|
||||
|
||||
finalizeStructuralChange(index, emptyList(), listOf(element))
|
||||
finalizeStructuralChange(
|
||||
index,
|
||||
prevSize = index,
|
||||
removed = emptyList(),
|
||||
inserted = listOf(element),
|
||||
)
|
||||
}
|
||||
|
||||
override fun add(index: Int, element: E) {
|
||||
checkIndex(index, elements.size)
|
||||
val prevSize = elements.size
|
||||
checkIndex(index, prevSize)
|
||||
emitMightChange()
|
||||
|
||||
copyAndResetWrapper()
|
||||
elements.add(index, element)
|
||||
|
||||
finalizeStructuralChange(index, emptyList(), listOf(element))
|
||||
finalizeStructuralChange(index, prevSize, removed = emptyList(), inserted = listOf(element))
|
||||
}
|
||||
|
||||
override fun remove(element: E): Boolean {
|
||||
@ -91,34 +102,41 @@ class SimpleListCell<E>(
|
||||
checkIndex(index, elements.lastIndex)
|
||||
emitMightChange()
|
||||
|
||||
val prevSize = elements.size
|
||||
|
||||
copyAndResetWrapper()
|
||||
val removed = elements.removeAt(index)
|
||||
|
||||
finalizeStructuralChange(index, listOf(removed), emptyList())
|
||||
finalizeStructuralChange(index, prevSize, removed = listOf(removed), inserted = emptyList())
|
||||
return removed
|
||||
}
|
||||
|
||||
override fun replaceAll(elements: Iterable<E>) {
|
||||
emitMightChange()
|
||||
|
||||
val prevSize = this.elements.size
|
||||
val removed = elementsWrapper
|
||||
|
||||
copyAndResetWrapper()
|
||||
this.elements.replaceAll(elements)
|
||||
|
||||
finalizeStructuralChange(0, removed, elementsWrapper)
|
||||
finalizeStructuralChange(index = 0, prevSize, removed, inserted = elementsWrapper)
|
||||
}
|
||||
|
||||
override fun replaceAll(elements: Sequence<E>) {
|
||||
emitMightChange()
|
||||
|
||||
val prevSize = this.elements.size
|
||||
val removed = elementsWrapper
|
||||
|
||||
copyAndResetWrapper()
|
||||
this.elements.replaceAll(elements)
|
||||
|
||||
finalizeStructuralChange(0, removed, elementsWrapper)
|
||||
finalizeStructuralChange(index = 0, prevSize, removed, inserted = elementsWrapper)
|
||||
}
|
||||
|
||||
override fun splice(fromIndex: Int, removeCount: Int, newElement: E) {
|
||||
val prevSize = elements.size
|
||||
val removed = ArrayList<E>(removeCount)
|
||||
|
||||
for (i in fromIndex until (fromIndex + removeCount)) {
|
||||
@ -131,17 +149,19 @@ class SimpleListCell<E>(
|
||||
repeat(removeCount) { elements.removeAt(fromIndex) }
|
||||
elements.add(fromIndex, newElement)
|
||||
|
||||
finalizeStructuralChange(fromIndex, removed, listOf(newElement))
|
||||
finalizeStructuralChange(fromIndex, prevSize, removed, inserted = listOf(newElement))
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
emitMightChange()
|
||||
|
||||
val prevSize = elements.size
|
||||
val removed = elementsWrapper
|
||||
|
||||
copyAndResetWrapper()
|
||||
elements.clear()
|
||||
|
||||
finalizeStructuralChange(0, removed, emptyList())
|
||||
finalizeStructuralChange(index = 0, prevSize, removed, inserted = emptyList())
|
||||
}
|
||||
|
||||
override fun sortWith(comparator: Comparator<E>) {
|
||||
@ -157,7 +177,12 @@ class SimpleListCell<E>(
|
||||
throwable = e
|
||||
}
|
||||
|
||||
finalizeStructuralChange(0, removed, elementsWrapper)
|
||||
finalizeStructuralChange(
|
||||
index = 0,
|
||||
prevSize = elements.size,
|
||||
removed,
|
||||
inserted = elementsWrapper,
|
||||
)
|
||||
|
||||
if (throwable != null) {
|
||||
throw throwable
|
||||
@ -200,7 +225,12 @@ class SimpleListCell<E>(
|
||||
}
|
||||
}
|
||||
|
||||
private fun finalizeStructuralChange(index: Int, removed: List<E>, inserted: List<E>) {
|
||||
private fun finalizeStructuralChange(
|
||||
index: Int,
|
||||
prevSize: Int,
|
||||
removed: List<E>,
|
||||
inserted: List<E>,
|
||||
) {
|
||||
if (dependents.isNotEmpty() && extractDependencies != null) {
|
||||
repeat(removed.size) {
|
||||
elementDependents.removeAt(index).dispose()
|
||||
@ -218,7 +248,7 @@ class SimpleListCell<E>(
|
||||
}
|
||||
}
|
||||
|
||||
changes.add(ListChange.Structural(index, removed, inserted))
|
||||
changes.add(ListChange.Structural(index, prevSize, removed, inserted))
|
||||
ChangeManager.changed(this)
|
||||
}
|
||||
|
||||
|
@ -273,8 +273,12 @@ private fun <T> bindChildrenTo(
|
||||
list.observeList(callNow = true) { event: ListChangeEvent<T> ->
|
||||
for (change in event.changes) {
|
||||
if (change is ListChange.Structural) {
|
||||
repeat(change.removed.size) {
|
||||
parent.removeChild(parent.childNodes[change.index].unsafeCast<Node>())
|
||||
if (change.allRemoved) {
|
||||
parent.innerHTML = ""
|
||||
} else {
|
||||
repeat(change.removed.size) {
|
||||
parent.removeChild(parent.childNodes[change.index].unsafeCast<Node>())
|
||||
}
|
||||
}
|
||||
|
||||
childrenRemoved(change.index, change.removed.size)
|
||||
|
Loading…
Reference in New Issue
Block a user