diff --git a/orx-jvm/orx-gui/src/demo/kotlin/DemoAppearance01.kt b/orx-jvm/orx-gui/src/demo/kotlin/DemoAppearance01.kt index ae6b3193..a083f955 100644 --- a/orx-jvm/orx-gui/src/demo/kotlin/DemoAppearance01.kt +++ b/orx-jvm/orx-gui/src/demo/kotlin/DemoAppearance01.kt @@ -19,10 +19,9 @@ fun main() = application { } } - val gui = GUI(GUIAppearance(barWidth = 400)) + val gui = GUI(GUIAppearance(baseColor = ColorRGBa.GRAY.opacify(0.9), barWidth = 400)) gui.compartmentsCollapsedByDefault = false - val settings = @Description("Settings") object { @DoubleParameter("radius", 0.0, 100.0) var radius = 50.0 diff --git a/orx-jvm/orx-gui/src/demo/kotlin/DemoMultiWindow01.kt b/orx-jvm/orx-gui/src/demo/kotlin/DemoMultiWindow01.kt new file mode 100644 index 00000000..9a52c09b --- /dev/null +++ b/orx-jvm/orx-gui/src/demo/kotlin/DemoMultiWindow01.kt @@ -0,0 +1,32 @@ +import org.openrndr.WindowConfiguration +import org.openrndr.application +import org.openrndr.extra.gui.GUI +import org.openrndr.extra.parameters.* +import org.openrndr.window +import kotlin.system.exitProcess + +/** + * Demonstration of multi window GUI in the manual way + */ +fun main() { + // skip this demo on CI + if (System.getProperty("takeScreenshot") == "true") { + exitProcess(0) + } + application { + program { + val settings = object { + @DoubleParameter("radius", 10.0, 100.0) + var radius = 10.0 + } + window(WindowConfiguration(width = 200, resizable = true)) { + val gui = GUI() + gui.add(settings) + extend(gui) + } + extend { + drawer.circle(drawer.bounds.center, settings.radius) + } + } + } +} \ No newline at end of file diff --git a/orx-jvm/orx-gui/src/demo/kotlin/DemoMultiWindow02.kt b/orx-jvm/orx-gui/src/demo/kotlin/DemoMultiWindow02.kt new file mode 100644 index 00000000..162f49bc --- /dev/null +++ b/orx-jvm/orx-gui/src/demo/kotlin/DemoMultiWindow02.kt @@ -0,0 +1,32 @@ +import org.openrndr.WindowConfiguration +import org.openrndr.application +import org.openrndr.extra.gui.GUI +import org.openrndr.extra.gui.WindowedGUI +import org.openrndr.extra.parameters.* +import org.openrndr.window +import kotlin.system.exitProcess + +/** + * Demonstration of multi window GUI using WindowedGUI extension + */ +fun main() { + // skip this demo on CI + if (System.getProperty("takeScreenshot") == "true") { + exitProcess(0) + } + application { + program { + val settings = object { + @DoubleParameter("radius", 10.0, 100.0) + var radius = 10.0 + } + val gui = WindowedGUI() + gui.add(settings) + extend(gui) + + extend { + drawer.circle(drawer.bounds.center, settings.radius) + } + } + } +} \ No newline at end of file diff --git a/orx-jvm/orx-gui/src/main/kotlin/Gui.kt b/orx-jvm/orx-gui/src/main/kotlin/Gui.kt index 301237bf..6e00330b 100644 --- a/orx-jvm/orx-gui/src/main/kotlin/Gui.kt +++ b/orx-jvm/orx-gui/src/main/kotlin/Gui.kt @@ -48,6 +48,10 @@ private class TrackedObjectBinding( private val persistentCompartmentStates = mutableMapOf>() private val persistentSidebarStates = mutableMapOf() +private fun compartmentState(): MutableMap = persistentCompartmentStates.getOrPut(Driver.instance.contextID) { + mutableMapOf() +} + private fun sidebarState(): SidebarState = persistentSidebarStates.getOrPut(Driver.instance.contextID) { SidebarState() } @@ -57,7 +61,7 @@ private fun getPersistedOrDefault( property: KMutableProperty1, obj: Any ): T { - val state = persistentCompartmentStates[Driver.instance.contextID]!![compartmentLabel] + val state = compartmentState()[compartmentLabel] if (state == null) { return property.get(obj) } else { @@ -68,17 +72,19 @@ private fun getPersistedOrDefault( private fun setAndPersist(compartmentLabel: String, property: KMutableProperty1, obj: Any, value: T) { property.set(obj, value) - val state = persistentCompartmentStates[Driver.instance.contextID]!![compartmentLabel]!! + val state = compartmentState()[compartmentLabel] ?: error("item '$compartmentLabel' not in state (${compartmentState()}. ContextID ${Driver.instance.contextID} )") state.parameterValues[property.name] = value } private val logger = KotlinLogging.logger { } -class GUIAppearance(val baseColor: ColorRGBa = ColorRGBa.GRAY, val barWidth: Int = 200) +class GUIAppearance( + val baseColor: ColorRGBa = ColorRGBa.GRAY.opacify(0.99), + val barWidth: Int = 200) @Suppress("unused", "UNCHECKED_CAST") -class GUI( +open class GUI( val appearance: GUIAppearance = GUIAppearance(), val defaultStyles: List = defaultStyles(), ) : Extension { @@ -204,7 +210,7 @@ class GUI( this.width = 100.percent this.display = Display.FLEX this.flexDirection = FlexDirection.Row - this.background = Color.RGBa(appearance.baseColor.copy(alpha = 0.99)) + this.background = Color.RGBa(appearance.baseColor) } styleSheet(has class_ "collapsed") { @@ -223,7 +229,7 @@ class GUI( this.paddingRight = 10.px this.marginRight = 2.px this.height = 100.percent - this.background = Color.RGBa(appearance.baseColor.copy(alpha = 0.99)) + this.background = Color.RGBa(appearance.baseColor) this.overflow = Overflow.Scroll // @@ -360,7 +366,7 @@ class GUI( val collapseClass = ElementClass("collapsed") /* this is guaranteed to be in the dictionary after insertion through add() */ - val collapseState = persistentCompartmentStates[Driver.instance.contextID]!![label]!! + val collapseState = compartmentState()[label]!! if (collapseState.collapsed) { collapsible.classes.add(collapseClass) } @@ -372,7 +378,7 @@ class GUI( if (KeyModifier.CTRL in me.modifiers) { collapsible.classes.remove(collapseClass) - persistentCompartmentStates[Driver.instance.contextID]!!.forEach { + compartmentState().forEach { it.value.collapsed = true } collapseState.collapsed = false diff --git a/orx-jvm/orx-gui/src/main/kotlin/WindowedGUI.kt b/orx-jvm/orx-gui/src/main/kotlin/WindowedGUI.kt new file mode 100644 index 00000000..ef4b233b --- /dev/null +++ b/orx-jvm/orx-gui/src/main/kotlin/WindowedGUI.kt @@ -0,0 +1,31 @@ +package org.openrndr.extra.gui + +import org.openrndr.Extension +import org.openrndr.Program +import org.openrndr.WindowConfiguration +import org.openrndr.extra.parameters.title +import org.openrndr.math.IntVector2 +import org.openrndr.panel.style.StyleSheet +import org.openrndr.panel.style.defaultStyles +import org.openrndr.window + +class WindowedGUI(val appearance: GUIAppearance = GUIAppearance(), val defaultStyles: List = defaultStyles()) : Extension { + override var enabled: Boolean = true + + val addedObjects = mutableListOf>() + fun add(objectWithParameters: T, label: String? = objectWithParameters.title()): T { + addedObjects.add(Pair(objectWithParameters, label)) + return objectWithParameters + } + + + override fun setup(program: Program) { + program.window(WindowConfiguration(width = 200, height = program.height, position = program.window.position.toInt() - IntVector2(200,0) )) { + val gui = GUI(appearance, defaultStyles) + for ((obj, label) in addedObjects) { + gui.add(obj, label) + } + extend(gui) + } + } +} \ No newline at end of file