8.18.1.46. Buttons
Six shapes of click trigger. All six use ClickState;
state.clicked is the per-frame bool, state.click_count
accumulates across frames.
button(IDENT, (text = "..")) // the workhorse
small_button(IDENT, (text = "..")) // no frame padding
arrow_button(IDENT, (text = "..", dir = ...)) // triangle glyph
invisible_button(IDENT, (text = "..", size = ...)) // hit area, no render
image_button(IDENT, (text = "..", // textured button
user_texture_id = tex_id,
size = ...))
tab_item_button(IDENT, (text = "..", // button styled as tab,
flags = ...)) // inside a tab_bar
Source: modules/dasImgui/examples/tutorial/buttons.das.
8.18.1.46.1. Walkthrough
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: buttons — six shapes of click trigger.
21//
22// button(IDENT, (text = "..")) — the workhorse.
23// small_button(IDENT, (text = "..")) — no frame padding,
24// for inline tools.
25// arrow_button(IDENT, (text = "..", dir = ...)) — triangular glyph,
26// ImGuiDir.{Up,Down,
27// Left,Right}.
28// invisible_button(IDENT, (text = "..", size = ...)) — hit area without
29// rendering — overlay
30// a clickable region
31// on a drawlist scene.
32// image_button(IDENT, (text = "..", — textured button. The
33// user_texture_id = tex_id, font atlas works as
34// size = ...)) a no-setup texture.
35// tab_item_button(IDENT, (text = "..", — button styled as a
36// flags = ...)) tab — MUST be called
37// INSIDE a tab_bar.
38//
39// All six use `ClickState`: `state.clicked` is the per-frame click bool,
40// `state.click_count` accumulates total clicks.
41//
42// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/buttons.das
43// LIVE: daslang-live modules/dasImgui/examples/tutorial/buttons.das
44//
45// DRIVE (when running live):
46// curl -X POST -d '{"name":"imgui_click","args":{"target":"BT_WIN/BT_GO"}}' \
47// localhost:9090/command
48// curl -X POST -d '{"name":"imgui_click","args":{"target":"BT_WIN/BAR/BT_ADD"}}' \
49// localhost:9090/command
50// =============================================================================
51
52[export]
53def init() {
54 live_create_window("dasImgui buttons tutorial", 800, 720)
55 live_imgui_init(live_window)
56 let io & = unsafe(GetIO())
57 GetStyle().FontScaleMain = 1.4
58}
59
60[export]
61def update() { // nolint:STYLE038
62 if (!live_begin_frame()) return
63 begin_frame()
64
65 ImGui_ImplGlfw_NewFrame()
66 apply_synth_io_override()
67 NewFrame()
68
69 SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond.Always)
70 SetNextWindowSize(ImVec2(760.0f, 680.0f), ImGuiCond.Always)
71 window(BT_WIN, (text = "buttons tutorial", closable = false,
72 flags = ImGuiWindowFlags.None)) {
73
74 text("Six shapes — ClickState everywhere; state.click_count accumulates.")
75 text(BT_HINT, (text = "Plain / small / arrow / invisible / image / tab_item — pick by visual fit."))
76 separator()
77
78 // ---- Stage 1: button — the workhorse ----
79 if (button(BT_GO, (text = "Go"))) {
80 // Hook your click handler here.
81 }
82 text("BT_GO clicks = {BT_GO.click_count}")
83 spacing()
84
85 // ---- Stage 2: small_button — no padding, inline tool ----
86 small_button(BT_SMALL, (text = "quit"))
87 text("BT_SMALL clicks = {BT_SMALL.click_count} // SmallButton has zero frame padding")
88 spacing()
89
90 // ---- Stage 3: arrow_button — directional pair ----
91 arrow_button(BT_BACK, (text = "##back", dir = ImGuiDir.Left)); same_line(BT_SL1)
92 arrow_button(BT_FWD, (text = "##fwd", dir = ImGuiDir.Right))
93 text("nav clicks: back={BT_BACK.click_count}, fwd={BT_FWD.click_count}")
94 spacing()
95
96 // ---- Stage 4: invisible_button — hit area without a glyph ----
97 text("Invisible hotspot below (120×24, no glyph):")
98 invisible_button(BT_HOT, (text = "##hotspot", size = float2(120.0f, 24.0f)))
99 text("BT_HOT clicks = {BT_HOT.click_count} // overlay on a drawlist / image / etc.")
100 spacing()
101
102 // ---- Stage 5: image_button — textured button (font atlas) ----
103 let io & = unsafe(GetIO())
104 if (io.Fonts.TexData != null) {
105 image_button(BT_IMG, (text = "##font",
106 user_texture_id = io.Fonts.TexRef,
107 size = float2(48.0f, 48.0f)))
108 text("BT_IMG clicks = {BT_IMG.click_count} // textured 48×48 of the font atlas")
109 }
110 spacing()
111
112 // ---- Stage 6: tab_item_button — must live inside a tab_bar ----
113 text("tab_item_button — leading '?' tallies, trailing '+' grows the bar:")
114 tab_bar(BT_BAR, (text = "MyBar",
115 flags = ImGuiTabBarFlags.FittingPolicyShrink)) {
116 tab_item_button(BT_HELP, (text = "?",
117 flags = ImGuiTabItemFlags.Leading |
118 ImGuiTabItemFlags.NoTooltip))
119 tab_item_button(BT_ADD, (text = "+",
120 flags = ImGuiTabItemFlags.Trailing |
121 ImGuiTabItemFlags.NoTooltip))
122 tab_item(BT_TAB_A, (text = "alpha", closable = false,
123 flags = ImGuiTabItemFlags.None)) {
124 text(BT_BODY_A, (text = "tab alpha body"))
125 }
126 tab_item(BT_TAB_B, (text = "beta", closable = false,
127 flags = ImGuiTabItemFlags.None)) {
128 text(BT_BODY_B, (text = "tab beta body"))
129 }
130 }
131 text("BT_HELP clicks = {BT_HELP.click_count}, BT_ADD clicks = {BT_ADD.click_count}")
132 }
133
134 end_of_frame()
135 Render()
136 var w, h : int
137 live_get_framebuffer_size(w, h)
138 glViewport(0, 0, w, h)
139 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
140 glClear(GL_COLOR_BUFFER_BIT)
141 live_imgui_render()
142
143 live_end_frame()
144}
145
146[export]
147def shutdown() {
148 live_imgui_shutdown()
149 live_destroy_window()
150}
151
152[export]
153def main() {
154 init()
155 while (!exit_requested()) {
156 update()
157 }
158 shutdown()
159}
8.18.1.46.1.1. Requires
Already in the baseline boost layer:
imgui/imgui_widgets_builtin— every*_buttonrail.imgui/imgui_containers_builtin—tab_bar/tab_itemfor thetab_item_buttonhost.imgui/imgui_boost_runtime—ClickState(shared across all six widgets).
8.18.1.46.1.2. button — the workhorse
The default click trigger. Returns true on the frame the user
clicked; state.click_count tallies across frames:
if (button(SAVE, (text = "Save"))) {
// one-shot handler — runs once per click
}
// OR drive on accumulated count:
text("saves: {SAVE.click_count}")
size = (0, 0) lets ImGui auto-size to the label. Pass an explicit
size for fixed-width toolbar rows.
8.18.1.46.1.3. small_button — zero padding
Same widget shape; SmallButton() drops the frame padding. Use for
inline tool strips that need to feel like part of the surrounding
text:
text("Status: ")
same_line()
small_button(REFRESH, (text = "refresh"))
No size arg — small_button always auto-sizes.
8.18.1.46.1.4. arrow_button — directional glyph
A triangle pointing in one of four directions. dir : ImGuiDir picks
the direction:
arrow_button(BACK, (text = "##back", dir = ImGuiDir.Left)); same_line()
arrow_button(FWD, (text = "##fwd", dir = ImGuiDir.Right))
The text is the ImGui label (mostly "##name" to suppress visible
text — the glyph carries the meaning). Each call needs its own IDENT
(separate ClickState).
8.18.1.46.1.5. invisible_button — hit area only
Renders nothing, but captures clicks inside its bbox. The canonical use: overlay a hit area on top of a drawlist scene, image, or custom glyph:
invisible_button(HOTSPOT, (text = "##hotspot",
size = float2(120.0f, 24.0f)))
if (HOTSPOT.clicked) {
// capture click on the scene below
}
Requires an explicit size — there’s no glyph to derive bounds from.
ImGui still tracks hover and click via IsItemHovered() /
IsItemClicked(), so it composes with the rest of the imgui
interaction stack.
8.18.1.46.1.6. image_button — textured trigger
Renders a texture as the button face. user_texture_id : void? is
ImGui’s opaque texture handle — on GL it’s the GL texture id cast to
void?. The font atlas (io.Fonts.TexID) is always available and
makes for a no-setup demo target:
let io & = unsafe(GetIO())
let font_tex = io.Fonts.TexID
if (font_tex != null) {
image_button(BTN, (text = "##font",
user_texture_id = font_tex,
size = float2(48.0f, 48.0f)))
}
Real apps load their own textures via stbi or
LoadTextureFromFile helpers (see examples/imgui_demo/widgets.das
for the 8-button image-grid pattern). uv0 / uv1 slice into the
texture; bg_col / tint_col modulate the rendered face.
8.18.1.46.1.7. tab_item_button — button styled as a tab
A click trigger that visually matches sibling tab_item headers.
Must live inside a tab_bar body. Flag with Leading to anchor
to the start of the bar, Trailing to the end — the canonical
? / + row:
tab_bar(BAR, (text = "MyTabBar",
flags = ImGuiTabBarFlags.FittingPolicyResizeDown)) {
if (tab_item_button(HELP, (text = "?",
flags = ImGuiTabItemFlags.Leading |
ImGuiTabItemFlags.NoTooltip))) {
// open help popup
}
if (tab_item_button(ADD, (text = "+",
flags = ImGuiTabItemFlags.Trailing |
ImGuiTabItemFlags.NoTooltip))) {
// push a new entry
}
tab_item(TAB_A, (text = "alpha", closable = false,
flags = ImGuiTabItemFlags.None)) {
text(BODY_A, (text = "tab body"))
}
}
Unlike tab_item it has no content pane (no block body) — it’s a
trigger only. See Tab bar for the regular tab pattern.
8.18.1.46.1.8. Driving from outside
Every *_button accepts imgui_click and snapshot probes:
# Plain button
curl -X POST -d '{"name":"imgui_click","args":{"target":"BT_WIN/BT_GO"}}' \
localhost:9090/command
# Tab-bar-nested button — path includes the bar segment
curl -X POST -d '{"name":"imgui_click","args":{"target":"BT_WIN/BT_BAR/BT_HELP"}}' \
localhost:9090/command
8.18.1.46.1.9. Caller-owned variant
For sites where the click target lives on an external bool, use
edit_button from imgui_boost_runtime (see
External-pointer editing rail).
See also
Full source: modules/dasImgui/examples/tutorial/buttons.das
Features-side demo: modules/dasImgui/examples/features/triggers.das — every
ClickState widget in one window, useful for imgui_click smoke
testing.
Sibling tutorials: Color (color_button is a special button variant), Tab bar (where tab_item_button lives).
Boost macros — the macro layer.