8.18.1.16. Group
group brackets BeginGroup/EndGroup — a pure layout container
with no chrome, no flags, and no observable state. What it does is
combine its children into a single layout unit so that:
same_line after the closing brace continues from the group’s right edge, not the last widget’s. Two stacked column blocks share a row by sandwiching
same_line()between two groups.IsItemHovered /
IsItemActive/GetItemRect*after the group report against the combined bbox of every widget inside. Lets a tooltip attach to “anywhere in the icon-plus-label cluster” with no manual rectangle math.
GroupState is empty. The path push still happens, so widgets inside
group(LEFT_GRP) register under <window>/LEFT_GRP/<leaf>.
Source: modules/dasImgui/examples/tutorial/group.das.
8.18.1.16.1. Walkthrough
The recording walks the three patterns. First it toggles a checkbox in each of
the two side-by-side blocks — both stay live while same_line keeps them on
one row. Then it hovers the middle of the [i] Info cluster, not the button,
and the tooltip still fires — proof that IsItemHovered after EndGroup
reads against the whole group’s bounding box. Finally it drags the row’s slider
and the value updates on the line below. Every step is a real synth gesture the
recording asserts landed.
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: group — BeginGroup/EndGroup pure layout grouping.
21//
22// group(IDENT) { body }
23//
24// Treats several widgets as a single layout unit. Two effects:
25//
26// 1. Same-line stacking — same_line() after the group's closing brace
27// continues from the group's right edge, not the last widget's. Useful
28// for laying out (label-block | value-block | edit-block) rows.
29//
30// 2. Hit-test the whole group — IsItemHovered() / IsItemActive() called
31// after EndGroup() report against the group's combined bbox. Lets a
32// tooltip attach to "anywhere inside the icon-plus-label cluster".
33//
34// GroupState is empty — no flags, no observables. Pure structural marker.
35// The path push still happens, so a checkbox inside group(LEFT_GRP) is
36// reachable at GRP_WIN/LEFT_GRP/L_WIRE.
37//
38// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/group.das
39// LIVE: daslang-live modules/dasImgui/examples/tutorial/group.das
40// =============================================================================
41
42[export]
43def init() {
44 live_create_window("dasImgui group tutorial", 720, 480)
45 live_imgui_init(live_window)
46 let io & = unsafe(GetIO())
47 GetStyle().FontScaleMain = 1.4
48}
49
50[export]
51def update() {
52 if (!live_begin_frame()) return
53 begin_frame()
54
55 ImGui_ImplGlfw_NewFrame()
56 apply_synth_io_override()
57 NewFrame()
58
59 SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond.Always)
60 SetNextWindowSize(ImVec2(680.0f, 440.0f), ImGuiCond.Always)
61 window(GRP_WIN, (text = "group tutorial", closable = false,
62 flags = ImGuiWindowFlags.None)) {
63
64 text("group(IDENT) takes a block and treats its widgets as one layout unit.")
65 separator()
66
67 // ---- A: two side-by-side groups via same_line ----
68 text("A) Two groups + same_line: each block stacks vertically; same_line")
69 text(" between them keeps the right block's top aligned with the left.")
70 group(LEFT_GRP) {
71 text("Left block")
72 checkbox(L_WIRE, (text = "Wireframe"))
73 checkbox(L_GRID, (text = "Show grid"))
74 // Narrow the slider so LEFT_GRP leaves enough room for RIGHT_GRP
75 // on the same row at FontGlobalScale 1.4 + 680 px content width.
76 SetNextItemWidth(160.0f)
77 slider_int(L_FRAMES, (text = "frame limit"))
78 }
79 same_line((spacing = 24.0f))
80 group(RIGHT_GRP) {
81 text("Right block")
82 checkbox(R_VSYNC, (text = "VSync"))
83 checkbox(R_FULL, (text = "Fullscreen"))
84 small_button(R_APPLY, (text = "Apply"))
85 }
86 separator()
87
88 // ---- B: group as a tooltip hit-test surface ----
89 text("B) Hit-test a whole cluster - hover anywhere in the row below.")
90 group(HOVER_GRP) {
91 text("[i] Info")
92 same_line()
93 text("hover me anywhere in this row")
94 same_line()
95 small_button(HOVER_BTN, (text = "Action"))
96 }
97 if (IsItemHovered(ImGuiHoveredFlags.None)) {
98 tooltip(GRP_TIP) {
99 text("BeginTooltip while the whole group is hovered.")
100 text("IsItemHovered() after EndGroup() reports against the combined bbox.")
101 }
102 }
103 separator()
104
105 // ---- C: group used as a "row" with right-aligned status ----
106 text("C) The (label | value | button) row pattern.")
107 group(ROW_GRP) {
108 text("Speed:")
109 same_line()
110 slider_float(ROW_SPEED, (text = "##speed"))
111 same_line()
112 small_button(ROW_RESET, (text = "Reset"))
113 }
114 text("ROW_SPEED.value = {ROW_SPEED.value}")
115 }
116
117 end_of_frame()
118 Render()
119 var w, h : int
120 live_get_framebuffer_size(w, h)
121 glViewport(0, 0, w, h)
122 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
123 glClear(GL_COLOR_BUFFER_BIT)
124 live_imgui_render()
125
126 live_end_frame()
127}
128
129[export]
130def shutdown() {
131 live_imgui_shutdown()
132 live_destroy_window()
133}
134
135[export]
136def main() {
137 init()
138 while (!exit_requested()) {
139 update()
140 }
141 shutdown()
142}
8.18.1.16.1.1. Requires
Already in the baseline boost layer:
imgui/imgui_containers_builtin—groupplustooltip,same_line,separator.imgui/imgui_widgets_builtin— leaves used inside the group.
8.18.1.16.1.2. Two columns via same_line
The classic use: stack two column blocks side by side without manually computing column widths.
group(LEFT_GRP) {
text("Left block")
checkbox(L_WIRE, (text = "Wireframe"))
// Narrow the slider so the left group leaves room for the
// right group on the same row.
SetNextItemWidth(160.0f)
slider_int(L_FRAMES, (text = "frame limit"))
}
same_line((spacing = 24.0f))
group(RIGHT_GRP) {
text("Right block")
checkbox(R_VSYNC, (text = "VSync"))
small_button(R_APPLY, (text = "Apply"))
}
Without the groups, same_line would only join the previous widget
(the slider) to the next, leaving the rest of the right block to
overlap. The group treats four widgets as one item for same_line’s
“continue from the right edge” semantics.
8.18.1.16.1.3. Hit-testing a cluster
IsItemHovered after EndGroup applies to the whole group’s bbox.
The tutorial uses it to gate a manual tooltip:
group(HOVER_GRP) {
text("[i] Info")
same_line()
text("hover me anywhere in this row")
same_line()
small_button(HOVER_BTN, (text = "Action"))
}
if (IsItemHovered(ImGuiHoveredFlags.None)) {
tooltip(GRP_TIP) {
text("BeginTooltip while the whole group is hovered.")
}
}
Hovering the icon, the label, the button — any of them — fires the
tooltip. No need for IsItemHovered on each child or for Set...
rectangle hacks. The group’s bbox subsumes everything.
Note that HOVER_BTN is still independently clickable. Group hit-test
reads over the cluster but does NOT block child events.
8.18.1.16.1.5. Why no flags?
ImGui’s BeginGroup/EndGroup take no parameters. The wrapper’s
only argument is the IDENT. GroupState carries an
@optional _placeholder field so the [container] auto-emitter
has something to serialize — the field is unused and the JV payload
is {}.
8.18.1.16.1.6. Standalone vs live
Same convention as the other tutorials.
8.18.1.16.1.7. Driving from outside
The group itself isn’t open/close-driveable (nothing to open). Its children are reachable at the composed path:
curl -X POST -d '{"name":"imgui_force_set","args":{"target":"GRP_WIN/ROW_GRP/ROW_SPEED","value":0.75}}' \
localhost:9090/command
curl -X POST -d '{"name":"imgui_click","args":{"target":"GRP_WIN/ROW_GRP/ROW_RESET"}}' \
localhost:9090/command
See also
Full source: modules/dasImgui/examples/tutorial/group.das
Features-side demo: modules/dasImgui/examples/features/containers_window.das — uses
group alongside child to lay out a window’s right pane.
Sibling: Containers — umbrella container tour.
Boost macros — the macro layer.