Hint

Refer to QMK’s documentation for details on how to use community modules

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): Where nodes is an array of ui_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_ABSOLUTE(x)
[source]

x pixels in size

UI_RELATIVE(x)
[source]

x % of parent’s size

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.

UI_REMAINING()
[source]

Claim the parent’s remaining (not used by siblings) size.

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. Returning false 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;