Adders with properties
Let's make a custom widget that stores Widgets in a Table[string, Widget]
and displays the widget next to the key it was stored with.
First we need to add the parameter for the key to our adder.
...
viewable CustomBox:
myChildren: Table[string, Widget] # The child-widget field
adder add {.key: none(string).}:
...
Additional parameters passed to adders are called "properties".
Properties must have a default value, their type is inferred based on that value.
If you do not want to provide a default value, you can use an Option
type.
Let's assert that anyone using CustomBox
also passes a key and doesn't accidentally reuse a key that has already been used to store a Widget that in the table:
import owlkettle
import std/[tables, options, strformat]
viewable CustomBox:
myChildren: Table[string, Widget] # The child-widget field
adder add {.key: none(string).}:
assert key.isSome(), "CustomBox requires you to tell it under which key to store child widgets. Add a 'key' property"
let keyIsFree = not widget.valMyChildren.hasKey(key.get())
assert keyIsFree, fmt"A widget with the key '{key.get()} has already been added to CustomBox. Use a different name"
widget.hasMyChildren = true
widget.valMyChildren[key.get()] = child
method view(state: CustomBoxState): Widget =
gui:
Box(orient = OrientY):
for key in state.myChildren.keys:
Box():
Label(text = key)
insert state.myChildren[key]
## The App
viewable App:
discard
method view(state: AppState): Widget =
gui:
Window:
CustomBox():
Label(text = "I was passed in from the outside") {.key: some("key1").}
Label(text = "Me too!") {.key: some("key2").}
Label(text = "Me three!") {.key: some("key3").}
# Label(text = "Me four!") {.key: some("key3").} # Will cause a runtime error because key3 is already in use
when not defined(owlkettleNimiDocs):
brew(gui(App()))
If we were to remove the "#" in front of the last Label, we would be facing a runtime error produced by the application, since "key3" was already used.
Note: When using optionals, due to the macros involved, you can only use the some(<value>)
/none(<typedesc>)
syntax.