[orx-panel] Add WatchObjectDiv
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user