8.19.5. Narrative widgets
The narrative family is dasImgui’s set of read-only display widgets — text
emission with optional color, emphasis, bullets, or label/value framing.
All share a NarrativeState (or LabelTextState) payload that echoes
the call-site string back into the snapshot, so playwright tests can
assert “the label says what I expect” without any layout state.
Every rail accepts an optional leading ident. Pass one — text(IDENT,
(text = "...")) — and the widget registers at NARRATIVE_WIN/IDENT so a
snapshot can target it by name; omit it — text("...") — and it registers
under an auto-generated source-line key instead. This tutorial passes an
ident on every call so each line is assertable.
The nine rails:
text(IDENT, (text = "..."))— one line of plain text. Implemented viaTextUnformatted(no printf-style format expansion).text_unformatted(IDENT, (text = "..."))— explicit alias fortext; identical implementation. Exists so call sites can signal intent.text_wrapped(IDENT, (text = "..."))— reflows long strings to the window’s content edge.text_colored(IDENT, (color = float4(...), text = ...))— colored variant.text_disabled(IDENT, (text = "..."))— greyed for non-actionable hints.bullet(IDENT)— bullet glyph alone.bullet_text(IDENT, (text = "..."))— bullet glyph + text bundled.label_text(IDENT, (key = ..., value = ...))— two-string display, both echoed into the payload.separator_text(IDENT, (text = "..."))— horizontal rule with a centered label.
Source: modules/dasImgui/examples/tutorial/narrative_widgets.das.
8.19.5.1. Walkthrough
These widgets take no input, so the recording is a voiced, self-verifying tour: each beat narrates a group while the cursor points at it and asserts the widget rendered and echoed its call-site string into the snapshot — the “the label says what I expect” claim made concrete. A missing or wrong value aborts the recording at teardown instead of shipping.
1options gen2
2options _comment_hygiene = true
3options gc
4
5require imgui
6require imgui_app
7require opengl/opengl_boost
8require live/glfw_live
9require live/live_api
10require live/live_commands
11require live/live_vars
12require live_host
13require imgui/imgui_live
14require imgui/imgui_boost_runtime
15require imgui/imgui_boost_v2
16require imgui/imgui_widgets_builtin
17require imgui/imgui_containers_builtin
18require imgui/imgui_visual_aids
19
20// =============================================================================
21// TUTORIAL: narrative_widgets — boost v2 read-only display widgets.
22//
23// All eight share a NarrativeState (or LabelTextState) payload: the call-site
24// string echoes back into the snapshot so playwright tests can assert "the
25// label says what I expect". No focus, no click, no telemetry beyond `value`.
26//
27// Covers: text / text_unformatted / text_wrapped / text_colored / text_disabled
28// / bullet / bullet_text / label_text / separator_text
29//
30// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/narrative_widgets.das
31// LIVE: daslang-live modules/dasImgui/examples/tutorial/narrative_widgets.das
32//
33// DRIVE (when running live):
34// curl -X POST -d '{"name":"imgui_snapshot"}' localhost:9090/command \
35// | jq '.globals."NARRATIVE_WIN/BULLET_MARK".payload.value'
36// =============================================================================
37
38[export]
39def init() {
40 live_create_window("dasImgui narrative widgets", 760, 600)
41 live_imgui_init(live_window)
42 let io & = unsafe(GetIO())
43 GetStyle().FontScaleMain = 1.4
44}
45
46[export]
47def update() {
48 if (!live_begin_frame()) return
49 begin_frame()
50
51 ImGui_ImplGlfw_NewFrame()
52 apply_synth_io_override()
53 NewFrame()
54
55 SetNextWindowPos(ImVec2(60.0, 60.0), ImGuiCond.Always)
56 SetNextWindowSize(ImVec2(640.0, 480.0), ImGuiCond.Always)
57 window(NARRATIVE_WIN, (text = "Narrative widgets", closable = false,
58 flags = ImGuiWindowFlags.None)) {
59 // Each call passes an explicit ident so the widget registers at
60 // NARRATIVE_WIN/<ident> and a snapshot can assert "the label says what
61 // I expect". NarrativeState.value mirrors the call-site string.
62 text(PLAIN_LINE, (text = "text() - one line, telemetry-visible."))
63
64 // text_wrapped reflows to the window's content edge.
65 text_wrapped(WRAPPED_LINE, (text = "text_wrapped() reflows long strings to the window's right edge. Resize the window and the layout follows; the snapshot still carries the full source string regardless of wrapping."))
66
67 separator_text(SEP_COLOR, (text = "Color and emphasis"))
68
69 // Colored / disabled - visual variants, same payload shape.
70 text_colored(COLORED_LINE, (color = float4(0.7f, 0.9f, 0.4f, 1.0f),
71 text = "text_colored() with an inline float4 color."))
72 text_disabled(DISABLED_LINE, (text = "text_disabled() - greyed for non-actionable hints."))
73
74 separator_text(SEP_BULLET, (text = "Bulleted lines"))
75
76 // bullet() emits the marker glyph; bullet_text() bundles marker + text.
77 bullet(BULLET_MARK)
78 bullet_text(BULLET_FIRST, (text = "First point of interest."))
79 bullet_text(BULLET_SECOND, (text = "Second point - bullet glyph plus text in one call."))
80
81 separator_text(SEP_LABEL, (text = "Label/value pair"))
82
83 // label_text - two-string display, both strings echo into the payload.
84 label_text(VERSION_LABEL, (key = "Version", value = "v2.0-detour"))
85 }
86
87 end_of_frame()
88 Render()
89 var w, h : int
90 live_get_framebuffer_size(w, h)
91 glViewport(0, 0, w, h)
92 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
93 glClear(GL_COLOR_BUFFER_BIT)
94 live_imgui_render()
95
96 live_end_frame()
97}
98
99[export]
100def shutdown() {
101 live_imgui_shutdown()
102 live_destroy_window()
103}
104
105[export]
106def main() {
107 init()
108 while (!exit_requested()) {
109 update()
110 maybe_collect_gc()
111 }
112 shutdown()
113}
8.19.5.1.1. Requires
Baseline boost layer (imgui/imgui_boost_v2 re-exports
imgui/imgui_widgets_builtin). No extra modules.
8.19.5.1.2. text vs text_unformatted vs text_wrapped
text(s)— emitssthrough ImGui’sTextUnformatted(s). No printf-style format expansion; the string is rendered verbatim.text_unformatted(s)— identical totext(s)(sameTextUnformattedcall). Exists as an explicit-intent alias for call sites whereunformattedreads better, or where you want to underscore the no-printf-expansion contract for readers.text_wrapped(s)— emits throughTextWrapped(s)so the text reflows at the window’s content edge. The wrap position respectswith_text_wrap_posif you’ve pushed one.
The payload shape is identical for all three; the alias-pair
(text / text_unformatted) renders identically, while
text_wrapped is the one that actually changes rendering behavior.
8.19.5.1.3. Colored vs disabled
text_colored((color, text)) takes an inline float4 and renders the
text in that color. Useful for status callouts, error indicators, or
section accents. The color is per-call — no scope push needed.
text_disabled(s) renders in ImGui’s StyleColor.TextDisabled — the
greyed tone used for inert menu items and hints. The most common use is
the (?) help marker glyph (see Flat tooltips).
8.19.5.1.4. Bullets
bullet(IDENT) emits the marker glyph alone — useful when you want
custom content (a colored swatch, an icon) immediately after the bullet.
bullet_text(IDENT, (text = "...")) is the bundled form — glyph + text
in one call. Use this 95% of the time; reach for bullet(IDENT) +
same_line + custom-glyph only when you genuinely need the manual
layout.
8.19.5.1.5. label_text
label_text((key, value)) maps to ImGui’s LabelText(key, value).
ImGui draws the value text on the left and the key as a label to its
right — so (key = "Version", value = "v2.0-detour") renders
v2.0-detour on the left with Version to its right. Both strings
round-trip through the snapshot payload, so snapshot-driven property
tests get both halves for assertion.
8.19.5.1.6. separator_text
separator_text("Section name") is a horizontal rule with the label
centered above it. Use it to break a long window into named sections;
much easier to scan than separator() followed by text("Section
name").
8.19.5.1.7. Snapshot shape
With an ident, a narrative widget registers at NARRATIVE_WIN/IDENT —
a stable path you can pull a field from. Without one it still surfaces a
path, but keyed by source line (NARRATIVE_WIN/:61:8), which shifts when
you edit the file; pass an ident whenever a test or driver needs to target
the line.
curl -X POST -d '{"name":"imgui_snapshot"}' localhost:9090/command \
| jq '.globals."NARRATIVE_WIN/VERSION_LABEL".payload.value'
See also
Full source: modules/dasImgui/examples/tutorial/narrative_widgets.das
Integration tests: modules/dasImgui/tests/test_narrative_text.das,
modules/dasImgui/tests/test_narrative_bullet.das,
modules/dasImgui/tests/test_narrative_separator.das.
Boost macros — the macro layer.