Skip to content

Button

Source: src/widgets/button.odin
FlashBang API: flashbang.Button, flashbang.ButtonTextured (alias), types ButtonConfig, ButtonState.

This file also defines ImmediateContext, set_immediate_context, theme/image/layout helpers, and global context accessors—see Immediate mode for the full frame contract.

What it does

button(ctx, config) -> ButtonState draws a themed rectangular surface with centered label text. It:

  1. Optionally applies apply_layout_override(config.id, …) so a layout backend can supply x,y,w,h.
  2. Adds origin_x / origin_y from the context (child coordinates inside containers).
  3. Computes hover (check_hover) and active (hover && mouse down).
  4. Computes clicked via check_click(config.was_active, …) — release while still over the widget after having been active.
  5. Maps hover/active to WidgetVisualState (NORMAL / HOVERED / PRESSED).
  6. Calls style.resolve_surface(theme, vis_state, extruded = true) for a raised control, then apply_color_override from optional Maybe colors on the config.
  7. emit_surface for the chrome, then measures text and emits a TEXT_RUN.
  8. Updates last_widget_w / last_widget_h and store_widget_dims when id is set.

ButtonConfig

Field Role
id Optional. Enables dimension lookup and layout-backend rect override when non-empty.
text Label string.
font_id, font_size Passed to text backend for measure/draw.
x, y, w, h Layout rectangle (logical units).
was_active You must pass previous frame’s ButtonState.active.
fill_color, border_color, text_color Optional Maybe(style.Color); nil uses theme.
padding_x, padding_y Fields exist on ButtonConfig; the current button procedure does not reference them (hit test and draw use the full w×h rect). Treat as reserved for future layout or set to zero unless you extend the widget locally.

ButtonState

Field Meaning
clicked True on the frame the click completes (release over widget).
hovered Pointer inside rect this frame.
active Pointer down inside rect this frame — store for was_active next frame.

Usage pattern

// persistent somewhere:
was_active: bool

state := flashbang.Button(ctx, flashbang.ButtonConfig{
    id = "my_btn",
    text = "OK",
    font_id = font,
    font_size = 14,
    x = 10, y = 10, w = 80, h = 28,
    was_active = was_active,
})
was_active = state.active
if state.clicked {
    // handle action
}

Theming

Uses resolve_surface with extruded = true. Custom look: supply a Theme with resolve and/or geometry set (src/style/theme.odin). Per-widget tint: use Maybe color fields on the config.

  • flashbang.ButtonTextured is currently an alias for button with the same config (name kept for API symmetry).