Under the Hood
This section contains a technical explanation of how functions populate the user interface. It is not necessary to understand this to use Easel, so don't feel like you need to read this!
In Easel, the UI hierarchy is composed of elements, which in turn may have more elements inside them.
Elements that have children are called parent elements.
Parent elements generally contain one slot where their children are displayed,
For example, the Panel element displays a framed border in the user interface,
and then inside there is a slot where it children are displayed inside the panel.
A parent element function calls its subblock to populate its slot with child elements.
The subblock is given a ui parameter which identifies the slot where the child elements will be inserted.
In order to reduce clutter, the ui parameter is normally omitted from the subblock parameter list
and only passed implicitly.
pub fn Example() {
Transmission { SayHello } // implicit ui parameter
Transmission ui { SayHello(ui=) } // equivalent, but with explicit ui parameter
}
pub fn SayHello([ui]) {
%("Hello, world!")
}
The compiler applies special magic to ui parameters.
Each time the ui parameter is read, the compiler decorates the value with a unique index within the slot.
This way, if the same line of code is executed again,
the child element function will replace the previously emitted element because its slot number is the same.
This enables user interfaces to be updated dynamically with ease.
This magic applies to any function parameter named ui or
that begins with the prefix ui: (for example ui:header or ui:whenOn).
pub fn Example() {
Transmission {
H1 { "The great counter" }
P {
let counter = 0
on Tick(1s) {
counter += 1
"We have waited " + counter + " seconds"
// the above text replaces the previous text every second
// because it is written to the same index within the slot
}
}
}
}
When emitting UI elements within a loop, the compiler automatically looks after clearing the elements from the previous iteration before emitting the new ones. This may seem obvious, but if it did not do this, the example below would display both "I am even" and "I am odd" at the same time after the second iteration as the two strings are emitted to different slot numbers. Cleanup is necessary and performed with precision by the compiler so Easel developers never need to worry about this situation.
pub fn Example() {
Transmission {
for i in Range(0,10) {
if i % 2 == 0 {
"I am even"
} else {
"I am odd"
}
await Tick(1s)
}
}
}
The ui parameter is magic, meaning it is given special treatment by the compiler.
The magic only applies when ui is a parameter.
A local variable named ui is not magic.
Reassigning the value of a ui parameter to another variable will not bestow the magic upon the new variable.
To keep the magic working, you should basically never touch ui parameters directly.