Skip to content

Commit 0231ec4

Browse files
authored
removeChildAt in O(n) instead of O(n^2) and simplify removeChild (#2319)
1 parent d4d07a7 commit 0231ec4

File tree

2 files changed

+54
-17
lines changed

2 files changed

+54
-17
lines changed

korge/src/korlibs/korge/view/Container.kt

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,29 @@ open class Container(
177177
@KorgeUntested
178178
fun getChildByName(name: String): View? = __children.firstOrNull { it.name == name }
179179

180-
fun removeChildAt(index: Int): Boolean =
181-
removeChild(getChildAtOrNull(index))
180+
fun removeChildAt(index: Int) = removeChildAt(index, 1) == 1
181+
182+
fun removeChildAt(index: Int, count: Int): Int {
183+
if (count <= 0 || index < 0) return 0
184+
val from = index
185+
val to = minOf(index + count, numChildren)
186+
187+
for (removedIndex in from until to) {
188+
val view = getChildAt(removedIndex)
189+
view.parent = null
190+
view.index = -1
191+
}
192+
193+
__children.removeRange(from, to)
194+
195+
for (i in index until numChildren)
196+
__children[i].index = i
182197

183-
// @TODO: Optimize
184-
fun removeChildAt(index: Int, count: Int) {
185-
repeat(count) { removeChildAt(index) }
186198
invalidateZIndexChildren()
199+
invalidateContainer()
200+
invalidateLocalBounds()
201+
202+
return to - from
187203
}
188204

189205
// @TODO: Optimize
@@ -425,14 +441,17 @@ open class Container(
425441

426442
view.parent?.invalidateZIndexChildren()
427443
view.removeFromParent()
444+
428445
val aindex = index.clamp(0, this.numChildren)
429-
view.index = aindex
430446
val children = __children
431447
children.add(aindex, view)
432-
for (n in aindex + 1 until children.size) children[n].index = n // Update other indices
448+
for (n in aindex until numChildren) children[n].index = n // Update other indices
449+
433450
view.parent = this
434451
view.invalidate()
452+
435453
onChildAdded(view)
454+
436455
invalidateZIndexChildren()
437456
invalidateContainer()
438457
invalidateLocalBounds()
@@ -447,16 +466,9 @@ open class Container(
447466
* Remarks: If the parent of [view] is not this container, this function doesn't do anything.
448467
*/
449468
fun removeChild(view: View?): Boolean {
450-
//if (view == null) return false
451469
if (view?.parent !== this) return false
452-
for (i in view.index + 1 until numChildren) __children[i].index--
453-
__children.removeAt(view.index)
454-
view.parent = null
455-
view.index = -1
456-
invalidateZIndexChildren()
457-
invalidateContainer()
458-
invalidateLocalBounds()
459-
return true
470+
471+
return removeChildAt(view.index)
460472
}
461473

462474
/**

korge/test/korlibs/korge/view/ContainerTest.kt

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,33 @@ internal class ContainerTest {
8585
solidRect(1, 1).name("d")
8686
solidRect(1, 1).name("e")
8787
}
88-
c.removeChildAt(1, 2)
88+
89+
val removedCount = c.removeChildAt(1, 2)
90+
91+
assertEquals(removedCount, 2)
92+
8993
assertEquals(listOf("a", "d", "e"), c.children.map { it.name })
94+
95+
// Assert that the indices are correct
96+
for (i in 0 until c.numChildren) {
97+
assertEquals(i, c.children[i].index)
98+
}
99+
}
100+
101+
@Test
102+
fun testRemoveMoreThanPresent() {
103+
val c = Container().apply {
104+
solidRect(1, 1).name("a")
105+
solidRect(1, 1).name("b")
106+
solidRect(1, 1).name("c")
107+
solidRect(1, 1).name("d")
108+
solidRect(1, 1).name("e")
109+
}
110+
111+
val removedCount = c.removeChildAt(0, 10)
112+
113+
assertEquals(5, removedCount)
114+
assertEquals(0, c.children.size)
90115
}
91116

92117
@Test

0 commit comments

Comments
 (0)