ui¶
Composable design of GUIs over QP, based on a hierarchy of nodes.
This system was designed for flexibility, because computing each element’s position and size by hand was a PITA and prone to errors. It also wasn’t dynamic, in the sense that if some element of the screen wasn’t being drawn (eg #if’ed away), sizes wouldn’t adapt and leave a gap.
-
UI_CHILDREN(x)¶
[source] - A node can have children, this is represented by:
.children = UI_CHILDREN(nodes)
: Wherenodes
is an array ofui_node_t
’s
- To compute the size of each child, parents must specify how their size will be shared between all children.
.split_direction = UI_SPLIT_DIR_{LEFT_RIGHT,RIGHT_LEFT}
: All children are as tall as parent, and size splits horizontally.split_direction = UI_SPLIT_DIR_{TOP_BOTTOM,BOTTOM_TOP}
: All children are as wide as parent, and size splits vertically
Every node must define how big they want to be by setting .node_size
to the following macros:
-
UI_FONT(x)¶
[source] x times the font’s height. Can only be used within vertical split node.
Warning
Executes``qp_load_font_mem((void*)node->args)`` to compute size. That is, the node’s
args
must point to a structure whose first element is a font’s array.
-
UI_IMAGE(x)¶
[source] x times a image’s width/height (depending on parent’s split direction).
Warning
Executes``qp_load_image_mem((void*)node->args)`` to compute size. That is, the node’s
args
must point to a structure whose first element is an image’s array.
-
bool ui_init(ui_node_t *root, ui_coord_t width, ui_coord_t height)¶
[source] Once you’ve declared a node tree, use this function to compute all nodes’ size/position.
If the input can’t be resolved (eg children don’t fit into parent), function will flag the node as invalid, and return false.
Hint
If a node must run some validation (eg: its computed height >= font used), it can provide an
.init
function. Returningfalse
from it means that requirements weren’t met, causing tree’s resolution to fail.
-
bool ui_render(ui_node_t *root, painter_device_t display)¶
[source] You shall use this function to render all nodes.
Each node describes how it’s rendered by providing a
.render
function. If it needs to track some state, it may use the.args
field to store a pointer into whichever structure. Return value is the time (in ms) before calling it again.0
means “do not repeat”You want run this function periodically (ie: from
housekeeping_task_user
).Warning
There isn’t any kind of limitation to the area in which each node can draw. This means that nodes are expected to respect the boundaries provided, with checks like
if (qp_textwidth(font, text) > self->size.x) return;