8.19.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.19.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
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: group — BeginGroup/EndGroup pure layout grouping.
22//
23// group(IDENT) { body }
24//
25// Treats several widgets as a single layout unit. Two effects:
26//
27// 1. Same-line stacking — same_line() after the group's closing brace
28// continues from the group's right edge, not the last widget's. Useful
29// for laying out (label-block | value-block | edit-block) rows.
30//
31// 2. Hit-test the whole group — IsItemHovered() / IsItemActive() called
32// after EndGroup() report against the group's combined bbox. Lets a
33// tooltip attach to "anywhere inside the icon-plus-label cluster".
34//
35// GroupState is empty — no flags, no observables. Pure structural marker.
36// The path push still happens, so a checkbox inside group(LEFT_GRP) is
37// reachable at GRP_WIN/LEFT_GRP/L_WIRE.
38//
39// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/group.das
40// LIVE: daslang-live modules/dasImgui/examples/tutorial/group.das
41// =============================================================================
42
43[export]
44def init() {
45 live_create_window("dasImgui group tutorial", 720, 480)
46 live_imgui_init(live_window)
47 let io & = unsafe(GetIO())
48 GetStyle().FontScaleMain = 1.4
49}
50
51[export]
52def update() {
53 if (!live_begin_frame()) return
54 begin_frame()
55
56 ImGui_ImplGlfw_NewFrame()
57 apply_synth_io_override()
58 NewFrame()
59
60 SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond.Always)
61 SetNextWindowSize(ImVec2(680.0f, 440.0f), ImGuiCond.Always)
62 window(GRP_WIN, (text = "group tutorial", closable = false,
63 flags = ImGuiWindowFlags.None)) {
64
65 text("group(IDENT) takes a block and treats its widgets as one layout unit.")
66 separator()
67
68 // ---- A: two side-by-side groups via same_line ----
69 text("A) Two groups + same_line: each block stacks vertically; same_line")
70 text(" between them keeps the right block's top aligned with the left.")
71 group(LEFT_GRP) {
72 text("Left block")
73 checkbox(L_WIRE, (text = "Wireframe"))
74 checkbox(L_GRID, (text = "Show grid"))
75 // Narrow the slider so LEFT_GRP leaves enough room for RIGHT_GRP
76 // on the same row at FontGlobalScale 1.4 + 680 px content width.
77 SetNextItemWidth(160.0f)
78 slider_int(L_FRAMES, (text = "frame limit"))
79 }
80 same_line((spacing = 24.0f))
81 group(RIGHT_GRP) {
82 text("Right block")
83 checkbox(R_VSYNC, (text = "VSync"))
84 checkbox(R_FULL, (text = "Fullscreen"))
85 small_button(R_APPLY, (text = "Apply"))
86 }
87 separator()
88
89 // ---- B: group as a tooltip hit-test surface ----
90 text("B) Hit-test a whole cluster - hover anywhere in the row below.")
91 group(HOVER_GRP) {
92 text("[i] Info")
93 same_line()
94 text("hover me anywhere in this row")
95 same_line()
96 small_button(HOVER_BTN, (text = "Action"))
97 }
98 if (IsItemHovered(ImGuiHoveredFlags.None)) {
99 tooltip(GRP_TIP) {
100 text("BeginTooltip while the whole group is hovered.")
101 text("IsItemHovered() after EndGroup() reports against the combined bbox.")
102 }
103 }
104 separator()
105
106 // ---- C: group used as a "row" with right-aligned status ----
107 text("C) The (label | value | button) row pattern.")
108 group(ROW_GRP) {
109 text("Speed:")
110 same_line()
111 slider_float(ROW_SPEED, (text = "##speed"))
112 same_line()
113 small_button(ROW_RESET, (text = "Reset"))
114 }
115 text("ROW_SPEED.value = {ROW_SPEED.value}")
116 }
117
118 end_of_frame()
119 Render()
120 var w, h : int
121 live_get_framebuffer_size(w, h)
122 glViewport(0, 0, w, h)
123 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
124 glClear(GL_COLOR_BUFFER_BIT)
125 live_imgui_render()
126
127 live_end_frame()
128}
129
130[export]
131def shutdown() {
132 live_imgui_shutdown()
133 live_destroy_window()
134}
135
136[export]
137def main() {
138 init()
139 while (!exit_requested()) {
140 update()
141 maybe_collect_gc()
142 }
143 shutdown()
144}
8.19.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.19.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.19.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.19.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.19.16.1.6. Standalone vs live
Same convention as the other tutorials.
8.19.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.