Single Adder
An adder is a proc that defines how to add child widgets to a widget.
It also enables the field that stores child-widgets.
It implicitly receives the parameters widget
of type Widget
(the custom widget itself) and child
of type Widget
(the child-widget to add).
To create a widget that can contain other widgets, you must:
- Add a field to your widget that can store child-Widgets (e.g. one with type
seq[Widget]
) - Define an adder that enables the child-widget-field and adds a given widget to it
- Define how to display the child-widgets in your
view
method
Let's look at an example for a CustomBox
:
import owlkettle
## The custom widget
viewable CustomBox:
myChildren: seq[Widget] # The child-widget field
adder add: # Define the default adder `add`
widget.hasMyChildren = true # Enables mutating `myChildren`
widget.valMyChildren.add(child) # Adds the child-Widget to `myChildren`
method view(state: CustomBoxState): Widget =
gui:
Box(orient = OrientY):
for child in state.myChildren:
insert child # Inserts child-widget into this CustomBox-widget
## The App
viewable App:
discard
method view(state: AppState): Widget =
gui:
Window:
CustomBox():
Label(text = "I was passed in from the outside")
Label(text = "Me too!")
Label(text = "Me three!")
when not defined(owlkettleNimiDocs):
brew(gui(App()))
We define myChildren
and "enable" it in the add
adder via widget.hasMyChildren = true
.
Then we define how to add the child
Widget to it, which in this case is simply us adding it to the seq.
Adding multiple widgets
To pass multiple Widgets to another Widget, iterate over the widgets and insert them. This is the preferred way of doing this.
import owlkettle
## The custom widget
viewable CustomBox2:
myChildren: seq[Widget] # The child-widget field
adder add: # Define the default adder `add`
widget.hasMyChildren = true # Enables mutating `myChildren`
widget.valMyChildren.add(child) # Adds the child-Widget to `myChildren`
method view(state: CustomBox2State): Widget =
gui:
Box(orient = OrientY):
for child in state.myChildren:
insert child # Inserts child-widget into this CustomBox-widget
proc toLabel(text: string): Widget =
Widget gui Label(text = text)
## The App
viewable App2:
discard
method view(state: App2State): Widget =
let labels: seq[Widget] = @[
"I was passed in from the outside".toLabel(),
"Me too!".toLabel(),
"Me three!".toLabel()
]
gui:
Window:
CustomBox2():
for widget in labels:
insert widget
when not defined(owlkettleNimiDocs):
brew(gui(App2()))
NOTE: When instantiating the Label
Widgets we do so using the gui
macro in toLabel
.
This can be done without the gui
macro, but is not advised as you may forget to set the has<Field>
- fields (see the Internals section).
But what if we want to store child-widgets in a table-field on CustomBox
?
We would need to pass the key to store the child-widget under to the adder...