#pragma once // ui_widgets.h - Immediate-mode widgets built on top of Clay. // // Each widget function takes a unique string ID, the value to display/edit, // and returns whether the value was changed (or the widget was activated). // The caller owns all data — the widget layer only stores transient UI state // like which text field is focused or which dropdown is open. #include "ui/ui_core.h" #include "ui/ui_icons.h" #include "platform/platform.h" //////////////////////////////// // Widget state (global, managed by widget layer) #define UI_WIDGET_MAX_DROPDOWN_ITEMS 32 #define UI_WIDGET_MAX_TEXT_INPUTS 16 #define UI_WIDGET_MAX_WINDOWS 16 struct UI_ModalState { B32 active; uint32_t id; // Hash of the modal's string ID S32 result; // Button index pressed, -1 = pending }; struct UI_WindowSlot { uint32_t id; // Hash of the window's string ID (0 = unused) Vec2F32 position; Vec2F32 size; B32 open; int16_t z_order; }; struct UI_DragState { uint32_t dragging_id; // Window ID currently being dragged (0 = none) Vec2F32 drag_anchor; // Mouse position when drag started Vec2F32 pos_anchor; // Window position when drag started }; struct UI_WidgetState { // Text input focus uint32_t focused_id; // Clay element ID hash of the focused text input (0 = none) int32_t cursor_pos; // Cursor position in focused text input F32 cursor_blink; // Blink timer (seconds) // Text selection (sel_start == sel_end means no selection) int32_t sel_start; // Selection anchor (where selection began) int32_t sel_end; // Selection extent (moves with cursor) // Tab cycling: registered text input IDs in order of declaration uint32_t text_input_ids[UI_WIDGET_MAX_TEXT_INPUTS]; int32_t text_input_count; B32 tab_pressed; // True on the frame Tab was pressed // Dropdown uint32_t open_dropdown_id; // Clay element ID hash of the open dropdown (0 = none) // Input for this frame PlatformInput input; // Click detection B32 mouse_clicked; // true on the frame mouse transitions from up->down // Modal state UI_ModalState modal; // Window state UI_WindowSlot windows[UI_WIDGET_MAX_WINDOWS]; S32 window_count; int16_t next_z; UI_DragState drag; }; extern UI_WidgetState g_wstate; // Call once at startup void ui_widgets_init(); // Call each frame before building widgets. Pass in the frame's input. void ui_widgets_begin_frame(PlatformInput input); // Call after changing theme to force text config refresh void ui_widgets_theme_changed(); // Reset per-frame text input display buffer allocator (called by begin_frame, but // can also be called manually if needed) void ui_text_input_reset_display_bufs(); //////////////////////////////// // Widgets // All IDs must be unique string literals (passed to CLAY_ID internally). // Icon element (rendered via icon atlas) void ui_icon(UI_IconID icon, F32 size, Clay_Color color); // Simple label void ui_label(const char *id, const char *text); // Clickable button. Returns true on the frame it was clicked. B32 ui_button(const char *id, const char *text); // Checkbox. Toggles *value on click. Returns true if value changed. B32 ui_checkbox(const char *id, const char *label, B32 *value); // Radio button group. Sets *selected to the clicked index. Returns true if changed. // options is an array of label strings, count is the number of options. B32 ui_radio_group(const char *id, const char **options, S32 count, S32 *selected); // Single-line text input. Edits buf in-place (null-terminated, max buf_size-1 chars). // Returns true if the text changed this frame. B32 ui_text_input(const char *id, char *buf, S32 buf_size); // Dropdown / combo box. Sets *selected to chosen index. Returns true if changed. // options is an array of label strings, count is the number of options. B32 ui_dropdown(const char *id, const char **options, S32 count, S32 *selected); // Modal dialog. Returns button index pressed (0-based), -1 if pending, -2 if Escape dismissed. // Call every frame while active — it draws the overlay and dialog box. S32 ui_modal(const char *id, const char *title, const char *message, const char **buttons, S32 button_count); B32 ui_modal_is_active(); // Tab bar. Renders a row of tabs with active/inactive states. // Returns the currently selected index. Clicking an inactive tab updates *selected. S32 ui_tab_bar(const char *id, const char **labels, S32 count, S32 *selected); // Draggable floating window. content_fn is called inside the window body each frame. // *open is set to 0 when the close button is clicked. Returns true while window is open. typedef void (*UI_WindowContentFn)(void *user_data); B32 ui_window(const char *id, const char *title, B32 *open, Vec2F32 initial_pos, Vec2F32 initial_size, UI_WindowContentFn content_fn, void *user_data);