[orx-panel] Add explicit contract checks for lambdas with callsInPlace
This commit is contained in:
@@ -11,6 +11,9 @@ import org.openrndr.panel.layout.Layouter
|
||||
import org.openrndr.panel.style.*
|
||||
import org.openrndr.panel.style.Display
|
||||
import org.openrndr.shape.Rectangle
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
@@ -493,7 +496,11 @@ class ControlManagerBuilder(val controlManager: ControlManager) {
|
||||
controlManager.layouter.styleSheets.addAll(styleSheets.flatMap { it.flatten() })
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun layout(init: Body.() -> Unit) {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val body = Body(controlManager)
|
||||
body.init()
|
||||
controlManager.body = body
|
||||
@@ -517,10 +524,14 @@ fun ControlManager.layout(init: Body.() -> Unit) {
|
||||
this.body = body
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Program.controlManager(
|
||||
defaultStyles: List<StyleSheet> = defaultStyles(),
|
||||
builder: ControlManagerBuilder.() -> Unit
|
||||
): ControlManager {
|
||||
contract {
|
||||
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val cm = ControlManager()
|
||||
cm.program = this
|
||||
cm.fontManager.register("default", resourceUrl("/fonts/Roboto-Regular.ttf"))
|
||||
|
||||
@@ -2,25 +2,45 @@ package org.openrndr.panel.elements
|
||||
|
||||
import org.openrndr.draw.Drawer
|
||||
import org.openrndr.panel.ControlManager
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.layout(init: Element.() -> Unit) {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
init()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun layout(controlManager: ControlManager, init: Body.() -> Unit): Body {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val body = Body(controlManager)
|
||||
body.init()
|
||||
return body
|
||||
}
|
||||
|
||||
fun <T : Element> Element.initElement(classes: Array<out String>, element: T, init: T.() -> Unit): Element {
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun <T : Element> Element.initElement(classes: Array<out String>, element: T, init: T.() -> Unit): T {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
append(element)
|
||||
element.classes.addAll(classes.map { ElementClass(it) })
|
||||
element.init()
|
||||
return element
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.button(vararg classes: String, label: String = "button", init: Button.() -> Unit): Button {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val button = Button().apply {
|
||||
this.classes.addAll(classes.map { ElementClass(it) })
|
||||
this.id = id
|
||||
@@ -34,19 +54,56 @@ fun Button.clicked(listener: (Button.ButtonEvent) -> Unit) {
|
||||
events.clicked.listen(listener)
|
||||
}
|
||||
|
||||
fun Element.slider(vararg classes: String, init: Slider.() -> Unit) = initElement(classes, Slider(), init) as Slider
|
||||
fun Element.toggle(vararg classes: String, init: Toggle.() -> Unit) = initElement(classes, Toggle(), init) as Toggle
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.slider(vararg classes: String, init: Slider.() -> Unit) : Slider {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, Slider(), init) as Slider
|
||||
}
|
||||
|
||||
fun Element.colorpicker(vararg classes: String, init: Colorpicker.() -> Unit) = initElement(classes, Colorpicker(), init)
|
||||
fun Element.colorpickerButton(vararg classes: String, init: ColorpickerButton.() -> Unit) = initElement(classes, ColorpickerButton(), init)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.toggle(vararg classes: String, init: Toggle.() -> Unit): Toggle {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, Toggle(), init) as Toggle
|
||||
}
|
||||
|
||||
fun Element.xyPad(vararg classes: String, init: XYPad.() -> Unit) = initElement(classes, XYPad(), init) as XYPad
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.colorpicker(vararg classes: String, init: Colorpicker.() -> Unit): Colorpicker {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, Colorpicker(), init)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.colorpickerButton(vararg classes: String, init: ColorpickerButton.() -> Unit): ColorpickerButton {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, ColorpickerButton(), init)
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.xyPad(vararg classes: String, init: XYPad.() -> Unit): XYPad {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, XYPad(), init) as XYPad
|
||||
}
|
||||
|
||||
fun Canvas.draw(f: (Drawer) -> Unit) {
|
||||
this.userDraw = f
|
||||
}
|
||||
|
||||
fun Element.canvas(vararg classes: String, init: Canvas.() -> Unit) : Canvas {
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.canvas(vararg classes: String, init: Canvas.() -> Unit): Canvas {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val canvas = Canvas()
|
||||
classes.forEach { canvas.classes.add(ElementClass(it)) }
|
||||
canvas.init()
|
||||
@@ -54,40 +111,104 @@ fun Element.canvas(vararg classes: String, init: Canvas.() -> Unit) : Canvas {
|
||||
return canvas
|
||||
}
|
||||
|
||||
fun Element.dropdownButton(vararg classes: String, id: String? = null, label: String = "button", init: DropdownButton.() -> Unit) = initElement(classes, DropdownButton().apply {
|
||||
this.id = id
|
||||
this.label = label
|
||||
}, init)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.dropdownButton(
|
||||
vararg classes: String,
|
||||
id: String? = null,
|
||||
label: String = "button",
|
||||
init: DropdownButton.() -> Unit
|
||||
): DropdownButton {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, DropdownButton().apply {
|
||||
this.id = id
|
||||
this.label = label
|
||||
}, init)
|
||||
}
|
||||
|
||||
fun Element.envelopeButton(vararg classes: String, init: EnvelopeButton.() -> Unit) = initElement(classes, EnvelopeButton().apply {}, init)
|
||||
fun Element.envelopeEditor(vararg classes: String, init: EnvelopeEditor.() -> Unit) = initElement(classes, EnvelopeEditor().apply {}, init)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.envelopeButton(vararg classes: String, init: EnvelopeButton.() -> Unit): EnvelopeButton {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, EnvelopeButton().apply {}, init)
|
||||
}
|
||||
|
||||
fun Element.sequenceEditor(vararg classes: String, init: SequenceEditor.() -> Unit) = initElement(classes, SequenceEditor().apply {}, init)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.envelopeEditor(vararg classes: String, init: EnvelopeEditor.() -> Unit): EnvelopeEditor {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, EnvelopeEditor().apply {}, init)
|
||||
}
|
||||
|
||||
fun Element.slidersVector2(vararg classes: String, init: SlidersVector2.() -> Unit) = initElement(classes, SlidersVector2().apply {}, init)
|
||||
fun Element.slidersVector3(vararg classes: String, init: SlidersVector3.() -> Unit) = initElement(classes, SlidersVector3().apply {}, init)
|
||||
fun Element.slidersVector4(vararg classes: String, init: SlidersVector4.() -> Unit) = initElement(classes, SlidersVector4().apply {}, init)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.sequenceEditor(vararg classes: String, init: SequenceEditor.() -> Unit): SequenceEditor {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, SequenceEditor().apply {}, init)
|
||||
}
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.slidersVector2(vararg classes: String, init: SlidersVector2.() -> Unit): SlidersVector2 {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, SlidersVector2().apply {}, init)
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.slidersVector3(vararg classes: String, init: SlidersVector3.() -> Unit): SlidersVector3 {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, SlidersVector3().apply {}, init)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.slidersVector4(vararg classes: String, init: SlidersVector4.() -> Unit): SlidersVector4 {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, SlidersVector4().apply {}, init)
|
||||
}
|
||||
|
||||
|
||||
fun Element.textfield(vararg classes: String, init: Textfield.() -> Unit) = initElement(classes, Textfield(), init)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.textfield(vararg classes: String, init: Textfield.() -> Unit): Textfield {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return initElement(classes, Textfield(), init)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun DropdownButton.item(init: Item.() -> Unit): Item {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val item = Item().apply(init)
|
||||
|
||||
|
||||
append(item)
|
||||
return item
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.div(vararg classes: String, init: Div.() -> Unit): Div {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val div = Div()
|
||||
initElement(classes, div, init)
|
||||
return div
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
inline fun <reified T : TextElement> Element.textElement(classes: Array<out String>, init: T.() -> String): T {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
@Suppress("DEPRECATION") val te = T::class.java.newInstance()
|
||||
te.classes.addAll(classes.map { ElementClass(it) })
|
||||
te.text(te.init())
|
||||
@@ -95,8 +216,33 @@ inline fun <reified T : TextElement> Element.textElement(classes: Array<out Stri
|
||||
return te
|
||||
}
|
||||
|
||||
fun Element.p(vararg classes: String, init: P.() -> String): P = textElement(classes, init)
|
||||
fun Element.h1(vararg classes: String, init: H1.() -> String): H1 = textElement(classes, init)
|
||||
fun Element.h2(vararg classes: String, init: H2.() -> String): H2 = textElement(classes, init)
|
||||
fun Element.h3(vararg classes: String, init: H3.() -> String): H3 = textElement(classes, init)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.p(vararg classes: String, init: P.() -> String): P {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return textElement(classes, init)
|
||||
}
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.h1(vararg classes: String, init: H1.() -> String): H1 {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return textElement(classes, init)
|
||||
}
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.h2(vararg classes: String, init: H2.() -> String): H2 {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return textElement(classes, init)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun Element.h3(vararg classes: String, init: H3.() -> String): H3 {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return textElement(classes, init)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.panel.style.PropertyInheritance.INHERIT
|
||||
import org.openrndr.panel.style.PropertyInheritance.RESET
|
||||
import java.util.*
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
enum class PropertyInheritance {
|
||||
@@ -232,7 +234,11 @@ fun StyleSheet.flatten(): List<StyleSheet> {
|
||||
return listOf(this) + children.flatMap { it.flatten() }
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun styleSheet(selector: CompoundSelector = CompoundSelector.DUMMY, init: StyleSheet.() -> Unit): StyleSheet {
|
||||
contract {
|
||||
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return StyleSheet(selector).apply {
|
||||
init()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user