Add WatchDiv demo

This commit is contained in:
Edwin Jakobs
2020-05-08 11:03:44 +02:00
parent 43edd55d68
commit 2dc7fb1b75
3 changed files with 136 additions and 5 deletions

View File

@@ -10,6 +10,8 @@ sourceSets {
dependencies { dependencies {
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion") demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
demoImplementation("org.openrndr:openrndr-dialogs:$openrndrVersion")
demoImplementation("com.google.code.gson:gson:$gsonVersion")
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion") demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion") demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion")
demoImplementation(sourceSets.getByName("main").output) demoImplementation(sourceSets.getByName("main").output)

View File

@@ -0,0 +1,123 @@
import com.google.gson.Gson
import org.openrndr.application
import org.openrndr.dialogs.openFileDialog
import org.openrndr.dialogs.saveFileDialog
import org.openrndr.panel.controlManager
import org.openrndr.panel.elements.*
import org.openrndr.panel.style.*
import java.io.File
// -- these have to be top-level classes or Gson will silently fail.
private class ConfigItem {
var value: Double = 0.0
}
private class ProgramState {
var rows = 1
var columns = 1
val matrix = mutableListOf(mutableListOf(ConfigItem()))
fun copyTo(programState: ProgramState) {
programState.rows = rows
programState.columns = columns
programState.matrix.clear()
programState.matrix.addAll(matrix)
}
fun save(file: File) {
file.writeText(Gson().toJson(this))
}
fun load(file: File) {
Gson().fromJson(file.readText(), ProgramState::class.java).copyTo(this)
}
}
fun main() = application {
configure {
width = 900
height = 720
}
program {
val programState = ProgramState()
val cm = controlManager {
layout {
styleSheet(has class_ "matrix") {
this.width = 100.percent
}
styleSheet(has class_ "row") {
this.display = Display.FLEX
this.flexDirection = FlexDirection.Row
this.width = 100.percent
child(has type "slider") {
this.width = 80.px
}
}
button {
label = "save"
clicked {
saveFileDialog(supportedExtensions = listOf("json")) {
programState.save(it)
}
}
}
button {
label = "load"
clicked {
openFileDialog(supportedExtensions = listOf("json")) {
programState.load(it)
}
}
}
slider {
label = "rows"
precision = 0
bind(programState::rows)
events.valueChanged.listen {
while (programState.matrix.size > programState.rows) {
programState.matrix.removeAt(programState.matrix.size - 1)
}
while (programState.matrix.size < programState.rows) {
programState.matrix.add(MutableList(programState.columns) { ConfigItem() })
}
}
}
slider {
label = "columns"
precision = 0
bind(programState::columns)
events.valueChanged.listen {
for (row in programState.matrix) {
while (row.size > programState.columns) {
row.removeAt(row.size - 1)
}
while (row.size < programState.columns) {
row.add(ConfigItem())
}
}
}
}
watchDiv("matrix", watchList = programState.matrix) { row ->
watchDiv("row", watchList = row) { item ->
this.id = "some-row"
slider {
label = "value"
bind(item::value)
}
}
}
}
}
extend(cm)
}
}

View File

@@ -5,12 +5,13 @@ import kotlinx.coroutines.yield
import org.openrndr.draw.Drawer import org.openrndr.draw.Drawer
import org.openrndr.launch import org.openrndr.launch
class WatchDiv<T : Any>(val watchList: List<T>, val builder: WatchDiv<T>.(T) -> Unit) : Div(), DisposableElement { class WatchDiv<T : Any>(private val watchList: List<T>, private val builder: WatchDiv<T>.(T) -> Unit) : Div(), DisposableElement {
override var disposed: Boolean = false override var disposed: Boolean = false
var listState = emptyList<T>() private var listState = emptyList<T>()
var watchJob : Job? = null private var watchJob: Job? = null
override fun dispose() { override fun dispose() {
super.dispose()
for (child in children) { for (child in children) {
child.parent = null child.parent = null
(child as? DisposableElement)?.dispose() (child as? DisposableElement)?.dispose()
@@ -18,7 +19,7 @@ class WatchDiv<T : Any>(val watchList: List<T>, val builder: WatchDiv<T>.(T) ->
children.clear() children.clear()
} }
private fun regenerate() { fun regenerate() {
var regenerate = false var regenerate = false
if (listState.size != watchList.size) { if (listState.size != watchList.size) {
regenerate = true regenerate = true
@@ -45,7 +46,7 @@ class WatchDiv<T : Any>(val watchList: List<T>, val builder: WatchDiv<T>.(T) ->
} }
} }
override fun draw(drawer: Drawer) { fun checkJob() {
if (watchJob == null) { if (watchJob == null) {
watchJob = (root() as Body).controlManager.program.launch { watchJob = (root() as Body).controlManager.program.launch {
while (!disposed) { while (!disposed) {
@@ -54,6 +55,9 @@ class WatchDiv<T : Any>(val watchList: List<T>, val builder: WatchDiv<T>.(T) ->
} }
} }
} }
}
override fun draw(drawer: Drawer) {
checkJob()
super.draw(drawer) super.draw(drawer)
} }
} }
@@ -62,4 +66,6 @@ fun <T : Any> Element.watchDiv(vararg classes: String, watchList: List<T>, build
val wd = WatchDiv(watchList, builder) val wd = WatchDiv(watchList, builder)
wd.classes.addAll(classes.map { ElementClass(it) }) wd.classes.addAll(classes.map { ElementClass(it) })
this.append(wd) this.append(wd)
wd.regenerate()
wd.checkJob()
} }