Widget Roadmap
AGT Widget Roadmap — FULLY SHIPPED
The Phase 2 widget set (buttons, inputs, lists, menus, dialogs, containers, the hex editor) is complete. This document captured the next tranche of high-value widgets for AGT’s target domain — pre-boot instrumentation and diagnostic dashboards, where an operator watches live hardware readings (temperatures, voltages, fan RPM, test pass/fail) on a GOP framebuffer.
Every widget below is now SHIPPED (see the per-entry (SHIPPED) tags and
the build-order summary at the bottom); this doc now stands as the record of
what was built and why. None was blocked: the drawing substrate was already
in place — axl-gfx exposes
axl_gfx_draw_line, axl_gfx_path_arc, the axl_gfx_path_* builder
(move_to / line_to / curve_to / close), and axl_gfx_stroke_path /
fill_path, all surfaced through AgtDrawContext (draw_line,
draw_polyline, stroke_path, fill_path) — the same primitives the
rounded frames and procedural stock icons already use. So the gauges, dials,
and charts need no new substrate, only widget code.
Conventions for each. A new widget follows the house style: derive the
right level of the AgtFrame chain, a static-map message dispatch
(AGT_MAP_*), a fluent build() builder + positional ctors, keyboard
operability (focus policy + key handlers), TDD (make test), and a visual
baseline where it renders deterministically (animated readouts pin a phase
for the baseline, as AgtSpinner does). Class names use the Agt prefix.
Tier 1 — Instrumentation (the core gap)
These are the widgets a live diagnostic dashboard is built from, and the single biggest capability AGT is missing relative to mature embedded GUIs.
AgtLight — status light / LED indicator
What: a small colored indicator (circle or rounded square) with a discrete state — e.g.
OFF/OK(green) /WARN(amber) /ERROR(red) /BUSY— optionally blinking, optionally with a trailing caption. Bitmap-faced and solid-color variants.Why: the canonical per-test / per-device pass-fail-running cue; a column of these IS the status panel of a diagnostic run.
Design:
AgtLight : AgtFrame. An enumStatemapped to palette tokens;set_state()+set_blink(bool)(reuse theAgtCursorBlink/AgtAnimcadence so it pulses without per-app timers). Drawn with a filled circle (anaxl_gfx_path_arcfull sweep, or a rounded fill). Optional borrowed caption to the right.Effort: Low. No new substrate; closest existing analogue is the stock- icon draw path.
AgtScale / AgtMeter — linear analog meter
What: a horizontal or vertical track with tick marks, a labeled range
[min, max], and a moving indicator (needle or fill) showing the current value — a thermometer / VU-meter / bar gauge. Optional colored threshold bands (green/amber/red zones).Why: the at-a-glance analog readout for a single scalar (temperature, voltage, utilization) with its safe/warn/critical bands shown inline.
Design:
AgtScale : AgtFrame. Shares the value/range model withAgtProgressBar(which is effectively a scale with no ticks); adds tick generation, optional band ranges, and an indicator.set_range,set_value,set_bands(...),set_orientation. Ticks + needle viadraw_line; fill viafill_rect.Effort: Low–Medium. Largely an
AgtProgressBarsuperset.
AgtDial — circular / needle gauge
What: a round gauge — an arc scale with tick marks and a needle (or a filled arc) pointing at the current value over
[min, max]. Finite-sweep (bounded, e.g. 270°) and full-circle variants; solid-drawn and bitmap-faced.Why: the classic instrument-cluster readout (RPM, temperature, pressure); reads faster than a number for “is this in the normal zone.”
Design:
AgtDial : AgtFrame. Map value → angle; draw the scale arc (axl_gfx_path_arc), major/minor ticks (draw_lineat computed angles), and the needle (a line/triangle from the hub). A small trig helper (sin/cos) for tick/needle endpoints.set_range,set_value,set_sweep(deg), optional band arcs.Effort: Medium. Arc + angular tick math; substrate ready (
path_arc+stroke_path).
AgtChart — line / multi-line / strip chart
What: a 2-D plot of one or more data series with axes, gridlines, and labels. Two key modes: a line chart (a fixed set of points) and a strip chart (a scrolling time series — new samples push in at the right, old ones scroll off the left), the live-trace view.
Why: the only way to show a reading’s history — voltage ripple, a temperature ramp during a stress test, fan response over time. Turns a point reading into a trend.
Design:
AgtChart : AgtFrame(or a thin layer overAgtCanvas’s custom-paint surface). A series model (ring buffer per series for the strip variant), axis/range mapping (auto or fixed), gridlines + tick labels, and a polyline per series (draw_polyline).add_series,push_sample/set_points,set_y_range,set_grid. The strip variant redraws on a timer/frame-clock like the other animated widgets.Effort: Medium–High (the largest lift here: axis math, series storage, efficient incremental redraw). No new substrate.
Tier 2 — Secure input
AgtPasswordField — masked text entry
What: a single-line field that renders a mask glyph (bullet
•or*) per codepoint instead of the character, with the full standard editing keys but no plaintext leakage (copy disabled or masked).Why: BIOS / admin / drive passwords and other secret entry in a pre-boot tool — currently impossible without echoing the secret on screen.
Design:
AgtPasswordField : AgtEditField. The edit model and key handling are inherited unchanged; the override is purely the render path — draw N mask glyphs instead of the text run — plus suppressing clipboard copy/cut of the secret.set_echo_char(uint32_t)to pick the mask glyph.Effort: Low. A focused subclass over the now-complete
AgtEditField.
Tier 3 — Specialized views
AgtTableEdit — editable cell grid (SHIPPED)
What: a grid of editable cells with a column header and cell navigation — like a table, but you can type into cells. (Shipped as
AgtTableEdit, not the originally-sketchedAgtSpreadSheetname: it is an editable table, not a spreadsheet — no formulas/ranges — andAgtGridalready owns “grid”.)Why: structured data entry / parameter tables (test limits, config matrices) that an operator edits in place.
Shipped design: a new shared base
AgtTableBasewas extracted from the (previously standalone) read-onlyAgtTableViewand now backs both widgets — the column schema, per-cell-text row model, virtualized-viewport geometry, ownedAgtScrollBar, command-target plumbing, and draw skeleton live there; three protected hooks carry the variation.AgtTableEdit : AgtTableBaseadds a single ACTIVE CELL(row,col), arrow/Home/End/PageUp/ PageDown navigation, and in-cell editing via ONE reusable overlaidAgtEditFieldrepositioned over the active cell (F2 / Enter / double-click / type-to-edit; Enter commits + moves down, Tab commits + moves right wrapping, Escape cancels, focus-out commits). Per-columneditablegate; string cells; emitsAGT_SEL_COMMANDon a cell commit.Effort: Medium–High. The in-cell editor + the focus-restore reentrancy guard were the work.
AgtLogView — scrolling console / log view (SHIPPED)
What: a scrolling text region that text is appended to, auto-scrolling to the tail, with a bounded scrollback and minimal control-code handling (CR/LF/tab). Read-only — one-directional output, no input.
Why: live command / test output and serial-console capture inside the UI — the “what is it doing right now” pane.
Design:
AgtLogView : AgtFrameover a circular line ring buffer.append(text),clear(), scrollback cap, follow-tail. Monospace, owned scrollbar, pager keys. (Originally drafted as “AgtTerminal”; renamed so theAgtTerminalname is free for the real interactive emulator below — a log pane is not a tty.)Effort: Medium. Done.
AgtTerminal — interactive terminal emulator (SHIPPED)
What: a real terminal emulator — bidirectional: it renders a stream AND takes keyboard input back to the stream, with cursor addressing, a screen grid (not just a line list), and a meaningful subset of ANSI/VT escape sequences. The interactive counterpart to the read-only
AgtLogView.Why: a live shell / serial console the operator can type into — e.g. a serial-console-over-BMC view, an EFI-shell pane, or a debug REPL inside the diagnostic UI.
AgtLogViewonly shows output; this is a console.Shipped design:
AgtTerminal : AgtFrameover a screen-buffer model (a cols×rows cell grid ofCell{codepoint,fg,bg,attr}+ cursor + pen + a bounded scrollback ring).feed(bytes)is a ground/ESC/CSI state machine over a bounded VT subset: UTF-8 printables with auto-wrap, C0 CR/LF/TAB/BS, cursor moves (CSI A/B/C/D/H/f/G/d), erase (CSI J/K), SGR (bold/underline/inverse, 16-color + 256-indexed fg/bg, default), save/restore cursor,ESC c. The WRITE side,emit_key, maps keystrokes → bytes (printables, Enter→CR, Backspace→DEL, Ctrl-letter→control byte, arrows/Home/End/PgUp/PgDn→xterm sequences) through aset_on_inputcallback the consumer drains to a pty/serial/EFI-shell pipe. Render: monospace per-cell over a dark console well with the 16+6×6×6+grayscale ANSI palette, bold/underline/inverse, a block cursor, and an owned scrollbar with follow-tail over the scrollback. Scroll regions, the alternate screen, selection/copy, and resize-reflow are deferred (a fixed cols on resize is the v0.1 behavior).Effort: High. The VT parser + screen model + input round-trip were the work; a pty/serial backend is the consumer’s to wire.
AgtProgressDialog — modal/modeless progress dialog
What: a small dialog wrapping a caption, an
AgtProgressBar(determinate or indeterminateAgtSpinner), and an optional Cancel button.Why: the standard “working… N%” affordance for a long-running test or scan, with a way to abort.
Design: a composite —
AgtProgressDialog : AgtDialogassembling an existing progress bar + label + button. Determinate (set_progress) and indeterminate (spinner) modes; works modal (run) or modeless (show, now that modeless dialogs exist).Effort: Low. Pure composition of shipped parts.
Tier 4 — Ergonomic / niche
These round out parity; each is a small extension of an existing widget. All three SHIPPED.
Horizontal list (orientation on AgtListBox) (SHIPPED)
What: the existing single-selection list laid out left-to-right instead of top-to-bottom (a strip of choices / a filmstrip).
Design: a new
Orientation(ctor arg +set_orientation+ builder.horizontal()); the model + selection are unchanged, only the layout + scrollbar axis flip (bottom strip vs right). Effort: Low–Medium. Done.
Sortable table columns (SHIPPED)
What: a clickable column header that sorts the rows by that column (asc/desc toggle, sort-direction caret in the header).
Design:
AgtTableView::set_sortable+ per-columnSortMode(TEXT/NUMERIC) +sort_by; a header click reorders the row-pointer array (selection preserved by identity) and the sorted header shows a caret. Effort: Medium. Done.
Suggested order
By diagnostic-dashboard value and ascending effort:
AgtLight— highest value-to-effort; the status panel building block.AgtScale/AgtMeter— analog scalar readout; near-superset ofAgtProgressBar.AgtPasswordField— small, unblocks secure entry, leans on the now- complete field.AgtProgressDialog— pure composition; cheap win.AgtDial— the instrument-cluster gauge; moderate trig/arc work.AgtChart— the trend view; the biggest lift, highest payoff for live monitoring.AgtLogView(done) — the read-only log/console pane.The Tier-4 ergonomic extensions (done) — multi-line button caption, horizontal
AgtListBox, sortableAgtTableViewcolumns.AgtTableEdit(done) — the editable cell grid (on the new sharedAgtTableBase).AgtTerminal(done) — the interactive VT/ANSI terminal emulator.
Shipped so far (items 1–10): the instrumentation family (AgtLight, AgtScale,
AgtDial, AgtChart), AgtPasswordField, AgtProgressDialog, the
declarative settings-forms framework (AgtForm / AgtFormBrowser),
AgtLogView, the Tier-4 extensions (multi-line button caption, horizontal
AgtListBox, sortable AgtTableView columns), AgtTableEdit (editable
cell grid; the shared AgtTableBase now backs both table widgets), and
AgtTerminal (interactive VT/ANSI emulator). The widget roadmap is fully
shipped.
See AGT-Design.md §”Widget set” for the shipped roster and
the house conventions every one of these must follow.