8.19.48. tree_node_ex + image
Two leaf widgets the container-shaped variants don’t cover.
tree_node_ex is the explicit-control sibling of the tree_node
container; image is the display-only sibling of image_button.
tree_node_ex(IDENT, (text = "..", flags = ...)) // returns open bool
// caller pairs tree_pop()
image(IDENT, (user_texture_id = tex_id, size = .., // display only
uv0 = .., uv1 = .., tint_col = .., // no ClickState
border_col = ..))
Source: modules/dasImgui/examples/tutorial/tree_image_misc.das.
8.19.48.1. Walkthrough
The recording clicks the tree_node_ex header to expand it - the three
children appear and the node’s returned open bool flips to true - then
moves to the display-only image. The expand is verified against that open
flag and the image against its on-screen presence, so a click that failed to
open the node would abort the recording.
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_layout_builtin
19require imgui/imgui_visual_aids
20
21// =============================================================================
22// TUTORIAL: tree_node_ex + image — two widgets the container-shaped variants
23// don't cover.
24//
25// tree_node_ex(IDENT, (text = "..", flags = ...)) — leaf form. Returns
26// the open bool;
27// caller pairs
28// TreePop() when
29// needed (when no
30// NoTreePushOnOpen
31// flag).
32//
33// image(IDENT, (user_texture_id = tex_id, size = .., — display widget.
34// uv0 = .., uv1 = .., tint_col = .., No state-tracked
35// border_col = ..)) click / hover; cf.
36// image_button for
37// the click trigger.
38//
39// tree_node_ex is the explicit-control sibling of `tree_node` (the
40// container). Use it when you need the open/closed bool to gate sibling
41// work, OR when you want NoTreePushOnOpen / Bullet / Leaf flags that
42// the container form doesn't surface cleanly.
43//
44// image is the display-only sibling of image_button — no ClickState, no
45// frame padding, no click semantics.
46//
47// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/tree_image_misc.das
48// LIVE: daslang-live modules/dasImgui/examples/tutorial/tree_image_misc.das
49// =============================================================================
50
51[export]
52def init() {
53 live_create_window("dasImgui tree_node_ex + image tutorial", 980, 720)
54 live_imgui_init(live_window)
55 let io & = unsafe(GetIO())
56 GetStyle().FontScaleMain = 1.4
57}
58
59[export]
60def update() {
61 if (!live_begin_frame()) return
62 begin_frame()
63
64 ImGui_ImplGlfw_NewFrame()
65 apply_synth_io_override()
66 NewFrame()
67
68 SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond.Always)
69 SetNextWindowSize(ImVec2(760.0f, 620.0f), ImGuiCond.Always)
70 window(TI_WIN, (text = "tree_node_ex + image tutorial", closable = false,
71 flags = ImGuiWindowFlags.None)) {
72
73 text("Two leaf widgets the container-shaped variants don't cover.")
74 text(TI_HINT, (text = "tree_node_ex returns the bool; image is display-only (no click)."))
75 separator()
76
77 // ---- Stage 1: tree_node_ex — leaf form, caller controls TreePop ----
78 text("tree_node_ex (leaf form - caller pairs TreePop):")
79 if (tree_node_ex(TI_TREE, (text = "Group", flags = ImGuiTreeNodeFlags.None))) {
80 text(" child A")
81 text(" child B")
82 text(" child C")
83 tree_pop()
84 }
85 spacing()
86
87 // ---- Stage 2: image — display, no click ----
88 text("image (display widget - paints a texture; no ClickState):")
89 let io & = unsafe(GetIO())
90 if (io.Fonts.TexData != null) {
91 image(TI_IMG, (user_texture_id = io.Fonts.TexRef,
92 size = float2(128.0f, 128.0f),
93 uv0 = float2(0.0f, 0.0f),
94 uv1 = float2(1.0f, 1.0f),
95 tint_col = float4(1.0f, 1.0f, 1.0f, 1.0f),
96 border_col = float4(0.6f, 0.6f, 0.6f, 1.0f)))
97 text("font atlas at 128x128 - no click, no padding; cf image_button.")
98 }
99 }
100
101 end_of_frame()
102 Render()
103 var w, h : int
104 live_get_framebuffer_size(w, h)
105 glViewport(0, 0, w, h)
106 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
107 glClear(GL_COLOR_BUFFER_BIT)
108 live_imgui_render()
109
110 live_end_frame()
111}
112
113[export]
114def shutdown() {
115 live_imgui_shutdown()
116 live_destroy_window()
117}
118
119[export]
120def main() {
121 init()
122 while (!exit_requested()) {
123 update()
124 maybe_collect_gc()
125 }
126 shutdown()
127}
8.19.48.1.1. Requires
imgui/imgui_widgets_builtin—tree_node_exandimage.imgui/imgui_layout_builtin—tree_pop().imgui/imgui_boost_runtime—TreeNodeState/ImageState.
8.19.48.1.2. tree_node_ex vs tree_node (container)
The container form (tree_node(IDENT, (text, flags)) { ... }) is
what you reach for 90% of the time: it auto-pairs TreePush /
TreePop, the body block carries the children:
// Container form — body is the open-state branch:
tree_node(GROUP, (text = "Group", flags = ImGuiTreeNodeFlags.None)) {
text(" child A")
text(" child B")
}
tree_node_ex is the leaf form: it returns the open bool, and the
caller decides what to do with it. Use it when:
You want to render sibling content outside the open-state branch (a row of inline controls that should appear next to the header regardless of open state).
You’re passing
NoTreePushOnOpen— that skips the TreePush, so a matchingtree_pop()would underflow the stack. The leaf form makes the asymmetry explicit.The flag set you want (
Leaf,Bullet,SpanAllColumns, etc.) doesn’t compose well with the container body shape.
if (tree_node_ex(GROUP, (text = "Group",
flags = ImGuiTreeNodeFlags.None))) {
text(" child A")
text(" child B")
tree_pop()
}
The matching tree_pop() is YOUR responsibility — easy to forget
when refactoring. Prefer tree_node unless one of the cases above
applies.
8.19.48.1.4. Driving from outside
Both widgets surface their payload via imgui_snapshot — no
imgui_force_set channels (the texture is caller-owned, the open state
is local to tree_node_ex’s call site):
curl -X POST -d '{"name":"imgui_snapshot"}' localhost:9090/command \
| jq '.globals."TI_WIN/TI_TREE".payload, .globals."TI_WIN/TI_IMG".payload'
See also
Full source: modules/dasImgui/examples/tutorial/tree_image_misc.das
Container sibling: Tree node (and Collapsing header for the unbordered-open variant).
Click sibling: Buttons (image_button section).
Features-side demo: modules/dasImgui/examples/features/display_image.das.
Boost macros — the macro layer.