8.18.1.8. Layout primitives
ImGui’s layout cursor advances after every widget — each button,
text, or other rail bumps the cursor to the next line by default.
Four boost rails move the cursor without rendering anything visible:
same_line(IDENT)— keep the next widget on the current row (wrapsImGui::SameLine).spacing(IDENT)— insert one line of vertical gap.new_line(IDENT)— advance one full text-line of vertical space.dummy((size = float2(x, y)))— reserve arbitrary cursor space without rendering.
All four accept the [widget]-style optional IDENT; the tutorial
shows IDENTs on same_line / spacing / new_line (useful when
playwright tests assert their snapshot entries) and the anonymous
dummy form (cursor reservation that no test targets).
All four share EmptyMarkerState — the payload is {}, but the
snapshot still records that the marker fired, so playwright tests can
assert "spacing#3 was rendered between button A and button B".
if (button(BTN_A, (text = "A"))) { /* ... */ }
same_line(SL_AB)
if (button(BTN_B, (text = "B"))) { /* ... */ }
same_line(SL_BC)
if (button(BTN_C, (text = "C"))) { /* ... */ }
spacing(SP_TOP)
new_line(NL_INSERT)
dummy((size = float2(0.0f, 40.0f)))
Source: modules/dasImgui/examples/tutorial/layout_primitives.das.
8.18.1.8.1. Walkthrough
The markers render nothing, so the recording’s self-check is that each named
marker fired: it narrates the same_line row while asserting the three
buttons and both same_line markers are on screen, then the spacing and
new_line markers in turn (record_check_rendered on each). A marker that
silently dropped out of the layout would abort the recording.
1options gen2
2options _comment_hygiene = true
3
4require imgui
5require imgui_app
6require opengl/opengl_boost
7require live/glfw_live
8require live/live_api
9require live/live_commands
10require live/live_vars
11require live_host
12require imgui/imgui_live
13require imgui/imgui_boost_runtime
14require imgui/imgui_boost_v2
15require imgui/imgui_widgets_builtin
16require imgui/imgui_containers_builtin
17require imgui/imgui_visual_aids
18
19// =============================================================================
20// TUTORIAL: layout_primitives — boost v2 cursor-positioning widgets.
21//
22// Layout markers move the imgui cursor without rendering anything. They share
23// EmptyMarkerState — payload is `{}`, but the snapshot still records the
24// widget existed, so playwright can assert "spacing#3 was rendered".
25//
26// Covers: same_line / new_line / spacing / dummy
27//
28// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/layout_primitives.das
29// LIVE: daslang-live modules/dasImgui/examples/tutorial/layout_primitives.das
30// =============================================================================
31
32[export]
33def init() {
34 live_create_window("dasImgui layout primitives", 1000, 640)
35 live_imgui_init(live_window)
36 let io & = unsafe(GetIO())
37 GetStyle().FontScaleMain = 1.4
38}
39
40[export]
41def update() {
42 if (!live_begin_frame()) return
43 begin_frame()
44
45 ImGui_ImplGlfw_NewFrame()
46 apply_synth_io_override()
47 NewFrame()
48
49 SetNextWindowPos(ImVec2(60.0, 60.0), ImGuiCond.Always)
50 SetNextWindowSize(ImVec2(600.0, 360.0), ImGuiCond.Always)
51 window(LAYOUT_WIN, (text = "Layout primitives", closable = false,
52 flags = ImGuiWindowFlags.None)) {
53 text("Three buttons on one row - same_line() keeps them inline.")
54 if (button(BTN_A, (text = "A"))) {
55 print("A\n")
56 }
57 same_line(SL_AB)
58 if (button(BTN_B, (text = "B"))) {
59 print("B\n")
60 }
61 same_line(SL_BC)
62 if (button(BTN_C, (text = "C"))) {
63 print("C\n")
64 }
65
66 spacing(SP_TOP)
67 text("spacing() inserts a small vertical gap (1 line).")
68
69 spacing(SP_MID)
70 spacing(SP_MID2)
71 spacing(SP_MID3)
72 text("Three spacing() calls stack; cheap if you don't want a Dummy.")
73
74 new_line(NL_INSERT)
75 text("new_line() == one full text-line of vertical space.")
76
77 dummy((size = float2(0.0f, 40.0f)))
78 text("dummy(size) reserves arbitrary cursor space.")
79 }
80
81 end_of_frame()
82 Render()
83 var w, h : int
84 live_get_framebuffer_size(w, h)
85 glViewport(0, 0, w, h)
86 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
87 glClear(GL_COLOR_BUFFER_BIT)
88 live_imgui_render()
89
90 live_end_frame()
91}
92
93[export]
94def shutdown() {
95 live_imgui_shutdown()
96 live_destroy_window()
97}
98
99[export]
100def main() {
101 init()
102 while (!exit_requested()) {
103 update()
104 }
105 shutdown()
106}
8.18.1.8.1.1. Requires
Baseline boost layer (imgui/imgui_boost_v2 re-exports
imgui/imgui_layout_builtin). No extra modules.
8.18.1.8.1.2. When to reach for each
same_line is the workhorse — every multi-column row, every label-then-input
pattern uses it. Pass an explicit offset if the next widget needs a
column-aligned position; default packs against the previous item.
spacing is a minimal 1-line gap — cheaper to read than dummy when
you just want breathing room between sections. Stack three of them if you
want a slightly larger gap without committing to a fixed pixel height.
new_line is conceptually \n at the layout level — one full text
line. Useful when the current row had a tall widget and you want the next
row to start fresh from the left margin without accumulating Y from the
tall content.
dummy(size) reserves an arbitrary rectangle. Pass size = float2(0, 40)
for a 40-pixel-tall invisible spacer. The X component can pre-allocate a
horizontal slot too — useful for grid-like alignment when widgets vary in
width.
8.18.1.8.1.3. Snapshot shape
Each layout marker registers an entry under its ident with kind
"empty_marker":
curl -X POST -d '{"name":"imgui_snapshot"}' localhost:9090/command \
| jq '.globals."LAYOUT_WIN/SL_AB"'
Tests that want to verify “this layout was produced” can walk the
snapshot and confirm the markers fired in the expected order — see
modules/dasImgui/tests/test_layout_primitives.das for the assertion shape.
See also
Full source: modules/dasImgui/examples/tutorial/layout_primitives.das
Companion tutorial: Layout — the higher-level layout
helpers (with_indent, with_item_width, with_text_wrap_pos).
Integration test: modules/dasImgui/tests/test_layout_primitives.das.
Boost macros — the macro layer.