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