fix ui widgets

This commit is contained in:
2026-02-25 16:40:14 -05:00
parent 12dae774e4
commit 68235b57ce
6 changed files with 759 additions and 27 deletions

View File

@@ -75,6 +75,32 @@ static void init_text_configs() {
g_text_config_dim.wrapMode = CLAY_TEXT_WRAP_NONE;
}
////////////////////////////////
// App state — all mutable state the frame function needs
struct AppState {
PlatformWindow *window;
Renderer *renderer;
MidiEngine *midi;
UI_Context *ui;
S32 last_w, last_h;
B32 show_browser;
B32 show_props;
B32 show_log;
B32 show_midi_devices;
LARGE_INTEGER freq;
LARGE_INTEGER last_time;
// Demo widget state
B32 demo_checkbox_a;
B32 demo_checkbox_b;
int32_t demo_radio_sel;
int32_t demo_dropdown_sel;
char demo_text_a[128];
char demo_text_b[128];
int32_t demo_button_count;
};
////////////////////////////////
// Panel builders
@@ -118,7 +144,7 @@ static void build_browser_panel(B32 show) {
}
}
static void build_main_panel() {
static void build_main_panel(AppState *app) {
CLAY(CLAY_ID("MainPanel"),
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
@@ -131,12 +157,104 @@ static void build_main_panel() {
CLAY(CLAY_ID("MainContent"),
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() },
.padding = { 8, 8, 6, 6 },
.childGap = 4,
.padding = { 16, 16, 12, 12 },
.childGap = 12,
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}
) {
CLAY_TEXT(CLAY_STRING("Main content area"), &g_text_config_normal);
// Section: Buttons
ui_label("LblButtons", "Buttons");
CLAY(CLAY_ID("ButtonRow"),
.layout = {
.sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() },
.childGap = 8,
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}
) {
if (ui_button("BtnHello", "Click Me")) {
app->demo_button_count++;
}
if (ui_button("BtnReset", "Reset")) {
app->demo_button_count = 0;
}
}
// Show click count
static char btn_count_buf[64];
snprintf(btn_count_buf, sizeof(btn_count_buf), "Button clicked %d times", app->demo_button_count);
ui_label("LblBtnCount", btn_count_buf);
// Separator
CLAY(CLAY_ID("Sep1"),
.layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(1) } },
.backgroundColor = g_theme.border
) {}
// Section: Checkboxes
ui_label("LblCheckboxes", "Checkboxes");
ui_checkbox("ChkA", "Enable feature A", &app->demo_checkbox_a);
ui_checkbox("ChkB", "Enable feature B", &app->demo_checkbox_b);
CLAY(CLAY_ID("Sep2"),
.layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(1) } },
.backgroundColor = g_theme.border
) {}
// Section: Radio buttons
ui_label("LblRadio", "Output Format");
static const char *radio_options[] = { "WAV", "AIFF", "FLAC" };
ui_radio_group("RadioFmt", radio_options, 3, &app->demo_radio_sel);
CLAY(CLAY_ID("Sep3"),
.layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(1) } },
.backgroundColor = g_theme.border
) {}
// Section: Text inputs
ui_label("LblText", "Text Inputs");
CLAY(CLAY_ID("TextRow"),
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
.childGap = 8,
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}
) {
CLAY(CLAY_ID("TextCol1"),
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
.childGap = 4,
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}
) {
ui_label("LblName", "Name:");
ui_text_input("TxtName", app->demo_text_a, sizeof(app->demo_text_a));
}
CLAY(CLAY_ID("TextCol2"),
.layout = {
.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() },
.childGap = 4,
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}
) {
ui_label("LblPath", "Output Path:");
ui_text_input("TxtPath", app->demo_text_b, sizeof(app->demo_text_b));
}
}
CLAY(CLAY_ID("Sep4"),
.layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(1) } },
.backgroundColor = g_theme.border
) {}
// Section: Dropdown
ui_label("LblDropdown", "Sample Rate");
CLAY(CLAY_ID("DropdownWrapper"),
.layout = {
.sizing = { .width = CLAY_SIZING_FIXED(200), .height = CLAY_SIZING_FIT() },
}
) {
static const char *rate_options[] = { "44100 Hz", "48000 Hz", "88200 Hz", "96000 Hz", "192000 Hz" };
ui_dropdown("DropRate", rate_options, 5, &app->demo_dropdown_sel);
}
}
}
}
@@ -249,23 +367,6 @@ static void build_log_panel(B32 show) {
}
}
////////////////////////////////
// App state — all mutable state the frame function needs
struct AppState {
PlatformWindow *window;
Renderer *renderer;
MidiEngine *midi;
UI_Context *ui;
S32 last_w, last_h;
B32 show_browser;
B32 show_props;
B32 show_log;
B32 show_midi_devices;
LARGE_INTEGER freq;
LARGE_INTEGER last_time;
};
////////////////////////////////
// Build the full UI layout for one frame
@@ -284,7 +385,7 @@ static void build_ui(AppState *app) {
}
) {
build_browser_panel(app->show_browser);
build_main_panel();
build_main_panel(app);
if (app->show_props || app->show_midi_devices) {
CLAY(CLAY_ID("RightColumn"),
@@ -330,6 +431,8 @@ static void do_frame(AppState *app) {
// Gather input
input_gather(platform_get_native_handle(app->window));
PlatformInputEvents input_events = platform_get_input_events(app->window);
ui_widgets_begin_frame(input_events, g_input.mouse_down, g_input.was_mouse_down);
// Build UI with Clay
ui_begin_frame(app->ui, (F32)w, (F32)h, g_input.mouse, g_input.mouse_down,
@@ -382,6 +485,7 @@ int main(int argc, char **argv) {
init_text_configs();
setup_menus(window);
ui_widgets_init();
AppState app = {};
app.window = window;
@@ -394,6 +498,9 @@ int main(int argc, char **argv) {
app.show_props = 1;
app.show_log = 1;
app.show_midi_devices = 1;
app.demo_dropdown_sel = 1; // default to 48000 Hz
snprintf(app.demo_text_a, sizeof(app.demo_text_a), "My Instrument");
snprintf(app.demo_text_b, sizeof(app.demo_text_b), "C:\\Samples\\output");
QueryPerformanceFrequency(&app.freq);
QueryPerformanceCounter(&app.last_time);