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: examples/tutorial/buttons.das.
Walkthrough
1options gen2
2
3require imgui
4require imgui_app
5require opengl/opengl_boost
6require live/glfw_live
7require live/live_api
8require live/live_commands
9require live/live_vars
10require live_host
11require imgui/imgui_live
12require imgui/imgui_boost_runtime
13require imgui/imgui_boost_v2
14require imgui/imgui_widgets_builtin
15require imgui/imgui_containers_builtin
16require imgui/imgui_visual_aids
17
18// =============================================================================
19// TUTORIAL: buttons — six shapes of click trigger.
20//
21// button(IDENT, (text = "..")) — the workhorse.
22// small_button(IDENT, (text = "..")) — no frame padding,
23// for inline tools.
24// arrow_button(IDENT, (text = "..", dir = ...)) — triangular glyph,
25// ImGuiDir.{Up,Down,
26// Left,Right}.
27// invisible_button(IDENT, (text = "..", size = ...)) — hit area without
28// rendering — overlay
29// a clickable region
30// on a drawlist scene.
31// image_button(IDENT, (text = "..", — textured button. The
32// user_texture_id = tex_id, font atlas works as
33// size = ...)) a no-setup texture.
34// tab_item_button(IDENT, (text = "..", — button styled as a
35// flags = ...)) tab — MUST be called
36// INSIDE a tab_bar.
37//
38// All six use `ClickState`: `state.clicked` is the per-frame click bool,
39// `state.click_count` accumulates total clicks.
40//
41// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/buttons.das
42// LIVE: daslang-live modules/dasImgui/examples/tutorial/buttons.das
43//
44// DRIVE (when running live):
45// curl -X POST -d '{"name":"imgui_click","args":{"target":"BT_WIN/BT_GO"}}' \
46// localhost:9090/command
47// curl -X POST -d '{"name":"imgui_click","args":{"target":"BT_WIN/BAR/BT_ADD"}}' \
48// localhost:9090/command
49// =============================================================================
50
51[export]
52def init() {
53 live_create_window("dasImgui buttons tutorial", 800, 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, 680.0f), ImGuiCond.Always)
70 window(BT_WIN, (text = "buttons tutorial", closable = false,
71 flags = ImGuiWindowFlags.None)) {
72
73 text("Six shapes — ClickState everywhere; state.click_count accumulates.")
74 text(BT_HINT, (text = "Plain / small / arrow / invisible / image / tab_item — pick by visual fit."))
75 separator()
76
77 // ---- Stage 1: button — the workhorse ----
78 if (button(BT_GO, (text = "Go"))) {
79 // Hook your click handler here.
80 }
81 text("BT_GO clicks = {BT_GO.click_count}")
82 spacing()
83
84 // ---- Stage 2: small_button — no padding, inline tool ----
85 small_button(BT_SMALL, (text = "quit"))
86 text("BT_SMALL clicks = {BT_SMALL.click_count} // SmallButton has zero frame padding")
87 spacing()
88
89 // ---- Stage 3: arrow_button — directional pair ----
90 arrow_button(BT_BACK, (text = "##back", dir = ImGuiDir.Left)); same_line(BT_SL1)
91 arrow_button(BT_FWD, (text = "##fwd", dir = ImGuiDir.Right))
92 text("nav clicks: back={BT_BACK.click_count}, fwd={BT_FWD.click_count}")
93 spacing()
94
95 // ---- Stage 4: invisible_button — hit area without a glyph ----
96 text("Invisible hotspot below (120×24, no glyph):")
97 invisible_button(BT_HOT, (text = "##hotspot", size = float2(120.0f, 24.0f)))
98 text("BT_HOT clicks = {BT_HOT.click_count} // overlay on a drawlist / image / etc.")
99 spacing()
100
101 // ---- Stage 5: image_button — textured button (font atlas) ----
102 let io & = unsafe(GetIO())
103 if (io.Fonts.TexData != null) {
104 image_button(BT_IMG, (text = "##font",
105 user_texture_id = io.Fonts.TexRef,
106 size = float2(48.0f, 48.0f)))
107 text("BT_IMG clicks = {BT_IMG.click_count} // textured 48×48 of the font atlas")
108 }
109 spacing()
110
111 // ---- Stage 6: tab_item_button — must live inside a tab_bar ----
112 text("tab_item_button — leading '?' tallies, trailing '+' grows the bar:")
113 tab_bar(BT_BAR, (text = "MyBar",
114 flags = ImGuiTabBarFlags.FittingPolicyShrink)) {
115 tab_item_button(BT_HELP, (text = "?",
116 flags = ImGuiTabItemFlags.Leading |
117 ImGuiTabItemFlags.NoTooltip))
118 tab_item_button(BT_ADD, (text = "+",
119 flags = ImGuiTabItemFlags.Trailing |
120 ImGuiTabItemFlags.NoTooltip))
121 tab_item(BT_TAB_A, (text = "alpha", closable = false,
122 flags = ImGuiTabItemFlags.None)) {
123 text(BT_BODY_A, (text = "tab alpha body"))
124 }
125 tab_item(BT_TAB_B, (text = "beta", closable = false,
126 flags = ImGuiTabItemFlags.None)) {
127 text(BT_BODY_B, (text = "tab beta body"))
128 }
129 }
130 text("BT_HELP clicks = {BT_HELP.click_count}, BT_ADD clicks = {BT_ADD.click_count}")
131 }
132
133 end_of_frame()
134 Render()
135 var w, h : int
136 live_get_framebuffer_size(w, h)
137 glViewport(0, 0, w, h)
138 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
139 glClear(GL_COLOR_BUFFER_BIT)
140 live_imgui_render()
141
142 live_end_frame()
143}
144
145[export]
146def shutdown() {
147 live_imgui_shutdown()
148 live_destroy_window()
149}
150
151[export]
152def main() {
153 init()
154 while (!exit_requested()) {
155 update()
156 }
157 shutdown()
158}
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).
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.
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.
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).
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.
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.
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.
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
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: examples/tutorial/buttons.das
Features-side demo: 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.