[orx-panel] Add WatchObjectDiv

This commit is contained in:
Edwin Jakobs
2020-07-15 14:31:43 +02:00
parent 3a6e787a46
commit 31dd1a6fa2
4 changed files with 172 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
package org.openrndr.panel.elements
import kotlinx.coroutines.Job
import kotlinx.coroutines.yield
import org.openrndr.draw.Drawer
import org.openrndr.launch
import org.openrndr.panel.elements.*
import org.openrndr.panel.hash.watchHash
import kotlin.reflect.KMutableProperty0
class WatchObjectDiv<T:Any>(
val watchObject: T,
private val builder: WatchObjectDiv<T>.(T) -> Unit
) : Div(),
DisposableElement {
override var disposed: Boolean = false
private var objectStateHash = watchHash(watchObject)
private var watchJob: Job? = null
override fun dispose() {
super.dispose()
for (child in children) {
child.parent = null
(child as? DisposableElement)?.dispose()
}
children.clear()
}
fun regenerate(force: Boolean = false) {
var regenerate = force
if (watchHash(watchObject) != objectStateHash) {
regenerate = true
}
if (regenerate) {
for (child in children) {
child.parent = null
(child as? DisposableElement)?.dispose()
}
objectStateHash = watchHash(watchObject)
children.clear()
builder(watchObject)
requestRedraw()
}
}
fun checkJob() {
if (watchJob == null) {
watchJob = (root() as? Body)?.controlManager?.program?.launch {
while (!disposed) {
regenerate()
yield()
}
}
}
}
override fun draw(drawer: Drawer) {
checkJob()
super.draw(drawer)
}
}
fun <T : Any> Element.watchObjectDiv(
vararg classes: String,
watchObject: T,
builder: WatchObjectDiv<T>.(T) -> Unit
) : WatchObjectDiv<T> {
val wd = WatchObjectDiv(watchObject, builder)
wd.classes.addAll(classes.map { ElementClass(it) })
this.append(wd)
wd.regenerate(true)
wd.checkJob()
return wd
}

View File

@@ -0,0 +1,19 @@
package org.openrndr.panel.hash
import kotlin.reflect.KProperty0
import kotlin.reflect.full.declaredMemberProperties
fun watchHash(toHash: Any): Int {
var hash = 0
for (property in toHash::class.declaredMemberProperties) {
val v = (property.getter)(toHash)
if (v is KProperty0<*>) {
val pv = v.get()
hash = 31 * hash + (pv?.hashCode() ?: 0)
} else {
hash = 31 * hash + (v?.hashCode() ?: 0)
}
}
return hash
}