moon_ui.event
Event code indicating that no event is available.
Event code requesting a redraw.
Event code for a mouse-button press.
Event code for a mouse-button release.
Event code for mouse-pointer motion.
Event code for keyboard input.
Event code for a window resize.
Event code requesting window closure.
Backend key code for Backspace.
Backend key code for Tab.
Backend key code for Return.
Backend key code for Escape.
Backend key code for Home.
Backend key code for the left arrow.
Backend key code for the right arrow.
Backend key code for End.
Backend key code for Delete.
One backend-independent input event.
kind: int | Which event this is, as one of the |
|---|---|
x: int | Pointer column in pixels, for a mouse event. |
y: int | Pointer row in pixels, for a mouse event. |
button: int | Button index, for a press or release. |
key: int | Key code, for a key event. |
ch: string | Typed text, for a text-input event. |
width: int | New window width, for a resize. |
height: int | New window height, for a resize. |
A no-op event (kind EV_NONE).
moon_ui.font
Bitmap glyph width in pixels.
Bitmap glyph height in pixels.
Pixels above the bitmap font baseline.
Pixels below the bitmap font baseline.
First supported ASCII code point.
Last supported ASCII code point.
Flat glyph rows: (LAST - FIRST + 1) glyphs x HEIGHT ints; in each row int, bit x (1 << x) set means the pixel x columns from the left is on. Call once and keep the array; it allocates per call.
moon_ui.sdl
An open SDL window/renderer plus the glyph bitmaps text draws from. Value-copied freely; open/resize return updated values.
window: *void | The SDL window handle. |
|---|---|
renderer: *void | The SDL renderer drawing goes through. |
glyphs: [int] | Bitmap rows of the built-in font, as |
ascent: int | Pixels from the baseline to the top of the font. |
descent: int | Pixels from the baseline to the bottom of the font. |
width: int | Current window width in pixels. |
height: int | Current window height in pixels. |
Opens a width x height window titled title. bg (0xRRGGBB) is the first clear color. Returns none when SDL cannot open a display.
title: Window title.width: Window width in pixels.height: Window height in pixels.bg: First clear colour, as0xRRGGBB.
use moon_ui.sdl
fn main() {
match sdl.open("moon", 320, 180, 0x101828) {
some(backend) => {
sdl.fill_rect(backend, 10, 10, 100, 40, 0x7DD3FC)
sdl.stroke_rect(backend, 10, 10, 100, 40, 0xFFFFFF)
sdl.line(backend, 10, 70, 200, 70, 0xFFFFFF)
sdl.fill_circle(backend, 30, 90, 20, 0x7DD3FC)
sdl.text(backend, 60, 90, "moon", 0xFFFFFF)
println(sdl.text_width(backend, "moon"))
println(sdl.line_height(backend))
sdl.present(backend)
if sdl.pending(backend) { println(sdl.next_event(backend)) }
sdl.sync(backend)
sdl.close(backend)
},
none => println("no display"),
}
}Records the new window size (the SDL renderer tracks it on its own).
b: The open window this draws on.width: New window width in pixels.height: New window height in pixels.
Fills a rectangle on the drawing target.
b: The open window this draws on.x: Left edge in pixels.y: Top edge in pixels.w: Width in pixels.h: Height in pixels.color: Colour as0xRRGGBB.
1px outline of the rectangle.
b: The open window this draws on.x: Left edge in pixels.y: Top edge in pixels.w: Width in pixels.h: Height in pixels.color: Colour as0xRRGGBB.
Draws a line on the target.
b: The open window this draws on.x1: Start column in pixels.y1: Start row in pixels.x2: End column in pixels.y2: End row in pixels.color: Colour as0xRRGGBB.
Filled circle inside the (x, y, d, d) square, rasterized in moon as one horizontal span per row. Odd diameters center exactly; even diameters use the upper-left of the two candidate centers.
b: The open window this draws on.x: Left edge of the bounding square.y: Top edge of the bounding square.d: Diameter in pixels.color: Colour as0xRRGGBB.
Circle outline inside the (x, y, d, d) square: span endpoints per row, plus the transposed pass so shallow arcs have no gaps.
b: The open window this draws on.x: Left edge of the bounding square.y: Top edge of the bounding square.d: Diameter in pixels.color: Colour as0xRRGGBB.
Line height (ascent + descent) of the built-in font.
b: The open window this draws on.
Draws s with its baseline at y (use b.ascent to convert from a top coordinate). Glyph rows are drawn as horizontal runs of set bits; characters outside the font's ASCII range render as blanks.
b: The open window this draws on.x: Left edge of the first glyph, in pixels.y: Baseline row in pixels.s: Text to draw.color: Colour as0xRRGGBB.
Flips the finished frame to the window.
b: The open window this draws on.
True when an event is already queued (next_event will not block). SDL_PollEvent with a null pointer peeks without dequeuing.
_b: The open window, unused: the SDL queue is global.
Blocks for the next SDL event and translates it. Events the UI does not model translate to EV_NONE and should be ignored.
_b: The open window, unused: the SDL queue is global.
Makes queued OS events visible to pending (used by tests).
_b: The open window, unused: the SDL queue is global.
Closes the resource.
b: The window and renderer to release.
moon_ui.ui
Sentinel for color parameters: "use the theme default".
Widget kinds carried by both specs and arena nodes.
Column | A container stacking its children vertically. |
|---|---|
Row | A container laying its children out horizontally. |
Label | Static text. |
Button | A clickable button. |
Checkbox | A box that toggles between ticked and clear. |
TextBox | A single-line editable text field. |
Slider | A draggable value along a track. |
Progress | A read-only fill showing progress. |
Rectangle | A plain filled rectangle. |
Radio | A stack of mutually exclusive options. |
Canvas | A free-form region painted by a callback. |
Cross-axis alignment of a container's children.
Start | Flush with the leading edge. |
|---|---|
Center | Centred on the cross axis. |
End | Flush with the trailing edge. |
Font metrics the layout runs against. run installs the backend font; tests install a fake (fixed advance per character).
measure: fn(string) -> int | Pixel width of a string in the installed font. |
|---|---|
ascent: int | Pixels from the baseline to the top of the font. |
descent: int | Pixels from the baseline to the bottom of the font. |
Fixed-advance metrics for headless layout tests.
char_w: Pixels every character advances.ascent: Pixels from the baseline to the top of the font.descent: Pixels from the baseline to the bottom of the font.
One arena widget: the spec fields plus computed geometry (x/y/w/h) and runtime editing state (cursor/scroll for a TextBox).
kind: Kind | Which widget this is. |
|---|---|
id: string | Name callbacks address the widget by; empty is unaddressable. |
parent: int | Arena index of the enclosing container, or -1 for the root. |
children: [int] | Arena indices of the children, in paint order. |
text: string | Label, button caption, or text-field contents. |
options: [string] | Choice labels, for a radio group. |
selected: int | Index of the chosen option, for a radio group. |
checked: bool | Whether the box is ticked, for a checkbox. |
value: float | Current value, for a slider or progress bar. |
min: float | Lowest value the slider or progress bar represents. |
max: float | Highest value the slider or progress bar represents. |
width: int | Requested width in pixels; 0 lets the layout decide. |
height: int | Requested height in pixels; 0 lets the layout decide. |
padding: int | Pixels of inset between a container and its children. |
spacing: int | Pixels between adjacent children of a container. |
color: int | Foreground colour as |
bg: int | Background colour as |
align: Align | How children sit on the cross axis of a container. |
on_click: fn(Ctx) -> void | Called with a context handle when the widget is clicked. |
on_change: fn(Ctx) -> void | Called with a context handle when the value changes. |
draw: fn(Painter) -> void | Called each frame with a canvas-relative painter, for a canvas. |
x: int | Computed left edge in window pixels. |
y: int | Computed top edge in window pixels. |
w: int | Computed width in pixels. |
h: int | Computed height in pixels. |
cursor: int | Caret byte offset, for a text field. |
scroll: int | Horizontal scroll offset in pixels, for a text field. |
A running UI. build allocates one managed instance, while the node arena and id table keep their ordinary collection identity.
nodes: [Node] | The widget arena, in paint order. |
|---|---|
ids: {string: int} | Widget ids to their arena indices. |
state: Shared | Hover, focus, drag, and window bookkeeping. |
metrics: Metrics | The font metrics layout measures against. |
The handle widget callbacks receive; query and mutate widgets by id.
app: *App | The running application the callback may query and mutate. |
|---|
Drawing surface handed to a canvas widget's draw callback; coordinates are relative to the canvas origin.
b: Backend | The backend the drawing lands on. |
|---|---|
x: int | Left edge of the canvas in window pixels. |
y: int | Top edge of the canvas in window pixels. |
w: int | Canvas width in pixels. |
h: int | Canvas height in pixels. |
A widget spec node; construct via the functions below, not literally.
kind: Kind | Which widget this is. |
|---|---|
id: string | Name callbacks address the widget by; empty is unaddressable. |
text: string | Label, button caption, or text-field contents. |
options: [string] | Choice labels, for a radio group. |
selected: int | Index of the chosen option, for a radio group. |
checked: bool | Whether the box is ticked, for a checkbox. |
value: float | Current value, for a slider or progress bar. |
min: float | Lowest value the slider or progress bar represents. |
max: float | Highest value the slider or progress bar represents. |
width: int | Requested width in pixels; 0 lets the layout decide. |
height: int | Requested height in pixels; 0 lets the layout decide. |
padding: int | Pixels of inset between a container and its children. |
spacing: int | Pixels between adjacent children of a container. |
color: int | Foreground colour as |
bg: int | Background colour as |
align: Align | How children sit on the cross axis of a container. |
on_click: fn(Ctx) -> void | Called with a context handle when the widget is clicked. |
on_change: fn(Ctx) -> void | Called with a context handle when the value changes. |
draw: fn(Painter) -> void | Called each frame with a canvas-relative painter, for a canvas. |
children: [Widget] | Child specs, for a container. |
A top-level window spec.
title: string | Window title. |
|---|---|
width: int | Window width in pixels. |
height: int | Window height in pixels. |
bg: int | Clear colour as |
children: [Widget] | Widgets of the root container. |
Creates a window widget and its root child container.
title: Window title.width: Window width in pixels.height: Window height in pixels.bg: Clear colour as0xRRGGBB.children: Widgets of the root container.
use moon_ui.ui
fn increment(ctx: ui.Ctx) {
ctx.set_text("count", to_string(std.strings.parse_int(ctx.text("count")) + 1))
ctx.set_checked("enabled", true)
ctx.set_value("progress", 75.0)
ctx.set_selected("mode", 1)
}
fn draw_chart(painter: ui.Painter) {
painter.fill_rect(0, 0, painter.width(), painter.height(), 0x101828)
painter.line(8, painter.height() - 8, painter.width() - 8, 8, 0x7DD3FC)
painter.circle(16, 16, 10, 0xFFFFFF)
painter.text(28, 10, "moon", 0xFFFFFF)
}
fn main() {
ui.run(ui.window(
title: "moon",
width: 420,
height: 300,
children: [ui.column(padding: 16, spacing: 10, children: [
ui.label("0", id: "count"),
ui.row(spacing: 8, children: [
ui.button("Increment", on_click: increment),
ui.checkbox("Enabled", id: "enabled"),
]),
ui.textbox(id: "name", placeholder: "Project name"),
ui.slider(id: "volume", value: 25.0),
ui.progress(id: "progress", value: 25.0),
ui.radio(["Debug", "Release"], id: "mode"),
ui.rectangle(width: 40, height: 8, color: 0x7DD3FC),
ui.canvas(draw: draw_chart, width: 180, height: 80),
])],
))
}Vertical container. align positions children on the cross (x) axis.
children: Widgets stacked top to bottom.spacing: Pixels between adjacent children.padding: Pixels of inset around the whole container.align: How children sit on the x axis.width: Requested width in pixels; 0 lets the layout decide.height: Requested height in pixels; 0 lets the layout decide.bg: Background colour as0xRRGGBB, orUNSETfor none.
Horizontal container. align positions children on the cross (y) axis.
children: Widgets laid out left to right.spacing: Pixels between adjacent children.padding: Pixels of inset around the whole container.align: How children sit on the y axis.width: Requested width in pixels; 0 lets the layout decide.height: Requested height in pixels; 0 lets the layout decide.bg: Background colour as0xRRGGBB, orUNSETfor none.
Creates a button widget.
text: Caption to display.id: Name callbacks address the widget by.on_click: Called with a context handle when the button is clicked.width: Requested width in pixels; 0 fits the caption.height: Requested height in pixels; 0 fits the caption.
Creates a checkbox widget.
text: Label beside the box.id: Name callbacks address the widget by.checked: Whether the box starts ticked.on_change: Called with a context handle when the value changes.
Single-line editable text field. text under the cursor keys, backspace, delete, home/end; fires on_change after every edit.
id: Name callbacks address the widget by.text: Initial contents.placeholder: Text shown while the field is empty.width: Field width in pixels.on_change: Called with a context handle after every edit.
Creates a slider widget.
id: Name callbacks address the widget by.value: Initial value.min: Lowest value the track represents.max: Highest value the track represents.width: Track width in pixels.on_change: Called with a context handle as the handle moves.
Creates a progress widget.
id: Name callbacks address the widget by.value: Initial value.min: Value the bar reads as empty.max: Value the bar reads as full.width: Bar width in pixels.height: Bar height in pixels.
Creates a rectangle widget.
width: Width in pixels.height: Height in pixels.color: Colour as0xRRGGBB, orUNSETto inherit.
A stack of mutually exclusive options; selected is the chosen index.
options: Labels of the mutually exclusive choices.id: Name callbacks address the widget by.selected: Index of the chosen option.on_change: Called with a context handle when the choice changes.
Free-form drawing region; draw runs each frame with a Painter whose coordinates are canvas-relative.
draw: Called each frame with a canvas-relative painter.id: Name callbacks address the widget by.width: Canvas width in pixels.height: Canvas height in pixels.
Flattens a window spec into one managed App arena. run does this for you; tests call it directly and pair it with fake_metrics.
win: The window spec to flatten into an arena.
use moon_ui.event
use moon_ui.event.UiEvent
use moon_ui.ui
fn main() {
let app = ui.build(ui.window(
width: 320,
height: 180,
children: [ui.label("Ready", id: "status")],
))
app.metrics = ui.fake_metrics(6, 11, 2)
ui.layout(app)
ui.dispatch(app, UiEvent {
kind: event.EV_RESIZE,
x: 0,
y: 0,
button: 0,
key: 0,
ch: "",
width: 640,
height: 360,
})
ui.dispatch(app, event.no_event())
println(app.nodes.len())
}The text of the widget with this id ("" when the id is unknown).
id: Identifier of the widget to address.
Replaces the text of the named widget.
id: Identifier of the widget to address.text: New contents.
Reports whether the named checkbox is selected.
id: Identifier of the widget to address.
Sets the checked state of the named widget.
id: Identifier of the widget to address.checked: New checked state.
Current value of a slider or progress bar.
id: Identifier of the widget to address.
Sets the numeric value of the named widget.
id: Identifier of the widget to address.value: New value, clamped to the widget range.
Selected option index of a radio group.
id: Identifier of the widget to address.
Sets the selected index of the named widget.
id: Identifier of the widget to address.selected: Index of the option to choose.
Ends the run loop after the current event.
Computes every node's geometry for the current metrics and window size.
app: The application whose node geometry is recomputed.
Feeds one input event through the interaction model: hover/press/focus tracking, click and change callbacks, text editing, slider drags.
app: The application to feed the event to.ev: One input event from the backend.
Returns the drawing-target width.
Returns the drawing-target height.
Fills a rectangle on the drawing target.
x: Left edge, relative to the canvas.y: Top edge, relative to the canvas.w: Width in pixels.h: Height in pixels.color: Colour as0xRRGGBB.
Strokes a rectangle on the drawing target.
x: Left edge, relative to the canvas.y: Top edge, relative to the canvas.w: Width in pixels.h: Height in pixels.color: Colour as0xRRGGBB.
Draws a line on the target.
x1: Start column, relative to the canvas.y1: Start row, relative to the canvas.x2: End column, relative to the canvas.y2: End row, relative to the canvas.color: Colour as0xRRGGBB.
Strokes a circle on the drawing target.
x: Left edge of the bounding square, relative to the canvas.y: Top edge of the bounding square, relative to the canvas.d: Diameter in pixels.color: Colour as0xRRGGBB.
Fills a circle on the drawing target.
x: Left edge of the bounding square, relative to the canvas.y: Top edge of the bounding square, relative to the canvas.d: Diameter in pixels.color: Colour as0xRRGGBB.
Draws s with its top-left corner at (x, y).
x: Left edge of the text, relative to the canvas.y: Top edge of the text, relative to the canvas.s: Text to draw.color: Colour as0xRRGGBB.
Returns the displayed terminal-cell width of text.
s: Text to measure.
Repaints the whole frame to the backend's pixmap and presents it.
app: The application to draw.b: The backend to draw on.
Opens the window and runs the event loop until the user closes it or a callback calls ctx.quit(). Prints a note and returns when no X display is reachable.
win: The window spec to open and drive.
Opens the window, paints one frame, drains any queued events, paints again, and closes. Used by integration tests to exercise the real X pipeline headlessly. Returns false when no display is reachable.
win: The window spec to open, paint, and close.