From 96f43eda44c7e67ed2ff485744c48cbe2fde8ed7 Mon Sep 17 00:00:00 2001 From: Max Amundsen Date: Thu, 5 Mar 2026 09:55:24 -0500 Subject: [PATCH] add preference menu --- src/main.cpp | 210 +++++++++++++++++++++++++++----------------------- src/menus.cpp | 12 ++- 2 files changed, 122 insertions(+), 100 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 816c07c..c78823d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,6 +110,9 @@ struct AppState { // Corner radius selection S32 radius_sel; + // Settings dialog tab + S32 settings_tab; // 0=Audio, 1=Midi, 2=Keyboard Shortcuts, 3=Appearance + // Knob demo state F32 demo_knob_unsigned; F32 demo_knob_signed; @@ -453,9 +456,6 @@ static void build_main_panel(AppState *app) { .layoutDirection = CLAY_LEFT_TO_RIGHT, } ) { - if (ui_button("BtnSettings", "Settings")) { - app->show_settings_window = 1; - } if (ui_button("BtnAbout", "About")) { app->show_about_window = 1; } @@ -882,107 +882,122 @@ static const F32 radius_values[] = { 0.0f, 4.0f, 6.0f, 10.0f }; static void settings_window_content(void *user_data) { AppState *app = (AppState *)user_data; - ui_label("SettingsLblTheme", "Theme"); - static const char *theme_options[] = { "Dark", "Light" }; - CLAY(CLAY_ID("SettingsThemeWrap"), - .layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(180)), .height = CLAY_SIZING_FIT() } } - ) { - ui_dropdown("SettingsTheme", theme_options, 2, &app->settings_theme_sel); - } + static const char *settings_tabs[] = { "Audio", "MIDI", "Keyboard Shortcuts", "Appearance" }; + ui_tab_bar("SettingsTabs", settings_tabs, 4, &app->settings_tab); - ui_label("SettingsLblAccent", "Accent Color"); - static const char *accent_options[] = { "Blue", "Turquoise", "Orange", "Purple", "Pink", "Red", "Green" }; - CLAY(CLAY_ID("SettingsAccentWrap"), - .layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(180)), .height = CLAY_SIZING_FIT() } } - ) { - ui_dropdown("SettingsAccent", accent_options, 7, &app->accent_sel); - } - - ui_label("SettingsLblRadius", "Corner Radius"); - static const char *radius_options[] = { "None", "Small", "Medium", "Large" }; - // radius_values defined at file scope (used by theme change handler too) - CLAY(CLAY_ID("SettingsRadiusWrap"), - .layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(180)), .height = CLAY_SIZING_FIT() } } - ) { - if (ui_dropdown("SettingsRadius", radius_options, 4, &app->radius_sel)) { - g_theme.corner_radius = radius_values[app->radius_sel]; - } - } - - ui_checkbox("SettingsVsync", "V-Sync", &app->settings_vsync); - ui_checkbox("SettingsAutosave", "Autosave", &app->settings_autosave); - - // Separator - CLAY(CLAY_ID("SettingsSep1"), - .layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(1) }, - .padding = { 0, 0, uip(6), uip(6) } }, - .backgroundColor = g_theme.border - ) {} - - // Audio device dropdown - ui_label("SettingsLblAudio", "Audio Device"); - - static const char *audio_options[AUDIO_MAX_DEVICES + 1]; - S32 audio_count = audio_get_device_count(app->audio); - audio_options[0] = "None"; - for (S32 i = 0; i < audio_count && i < AUDIO_MAX_DEVICES; i++) { - AudioDeviceInfo *dev = audio_get_device(app->audio, i); - audio_options[i + 1] = dev ? dev->name : "???"; - } - - CLAY(CLAY_ID("SettingsAudioWrap"), - .layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(220)), .height = CLAY_SIZING_FIT() } } - ) { - ui_dropdown("SettingsAudio", audio_options, audio_count + 1, &app->audio_device_sel); - } - - // Handle device selection change - if (app->audio_device_sel != app->audio_device_prev) { - audio_close_device(app->audio); - if (app->audio_device_sel > 0) { - audio_open_device(app->audio, app->audio_device_sel - 1); - } - app->audio_device_prev = app->audio_device_sel; - } - - // Test tone button + status - CLAY(CLAY_ID("SettingsAudioBtnRow"), + // Tab content area with some top padding + CLAY(CLAY_ID("SettingsTabContent"), .layout = { - .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() }, - .childGap = uip(8), - .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }, - .layoutDirection = CLAY_LEFT_TO_RIGHT, + .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT() }, + .padding = { 0, 0, uip(8), 0 }, + .childGap = uip(6), + .layoutDirection = CLAY_TOP_TO_BOTTOM, } ) { - B32 device_open = (app->audio_device_sel > 0); - B32 tone_playing = audio_is_test_tone_playing(app->audio); + if (app->settings_tab == 0) { + // === Audio tab === + ui_label("SettingsLblAudio", "Audio Device"); - if (device_open && !tone_playing) { - if (ui_button("BtnTestTone", "Play Test Tone")) { - audio_play_test_tone(app->audio); + static const char *audio_options[AUDIO_MAX_DEVICES + 1]; + S32 audio_count = audio_get_device_count(app->audio); + audio_options[0] = "None"; + for (S32 i = 0; i < audio_count && i < AUDIO_MAX_DEVICES; i++) { + AudioDeviceInfo *dev = audio_get_device(app->audio, i); + audio_options[i + 1] = dev ? dev->name : "???"; } - } else { - // Disabled button appearance - Clay_ElementId btn_eid = CLAY_ID("BtnTestToneDisabled"); - CLAY(btn_eid, - .layout = { - .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIXED(uis(28)) }, - .padding = { uip(12), uip(12), 0, 0 }, - .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }, - }, - .backgroundColor = g_theme.disabled_bg, - .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS) + + CLAY(CLAY_ID("SettingsAudioWrap"), + .layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(260)), .height = CLAY_SIZING_FIT() } } ) { - static Clay_TextElementConfig disabled_text = {}; - disabled_text.textColor = g_theme.disabled_text; - disabled_text.fontSize = FONT_SIZE_NORMAL; - disabled_text.wrapMode = CLAY_TEXT_WRAP_NONE; - CLAY_TEXT(CLAY_STRING("Play Test Tone"), &disabled_text); + ui_dropdown("SettingsAudio", audio_options, audio_count + 1, &app->audio_device_sel); } - } - if (tone_playing) { - ui_label("SettingsLblPlaying", "Playing..."); + if (app->audio_device_sel != app->audio_device_prev) { + audio_close_device(app->audio); + if (app->audio_device_sel > 0) { + audio_open_device(app->audio, app->audio_device_sel - 1); + } + app->audio_device_prev = app->audio_device_sel; + } + + CLAY(CLAY_ID("SettingsAudioBtnRow"), + .layout = { + .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIT() }, + .childGap = uip(8), + .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }, + .layoutDirection = CLAY_LEFT_TO_RIGHT, + } + ) { + B32 device_open = (app->audio_device_sel > 0); + B32 tone_playing = audio_is_test_tone_playing(app->audio); + + if (device_open && !tone_playing) { + if (ui_button("BtnTestTone", "Play Test Tone")) { + audio_play_test_tone(app->audio); + } + } else { + Clay_ElementId btn_eid = CLAY_ID("BtnTestToneDisabled"); + CLAY(btn_eid, + .layout = { + .sizing = { .width = CLAY_SIZING_FIT(), .height = CLAY_SIZING_FIXED(uis(28)) }, + .padding = { uip(12), uip(12), 0, 0 }, + .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }, + }, + .backgroundColor = g_theme.disabled_bg, + .cornerRadius = CLAY_CORNER_RADIUS(CORNER_RADIUS) + ) { + static Clay_TextElementConfig disabled_text = {}; + disabled_text.textColor = g_theme.disabled_text; + disabled_text.fontSize = FONT_SIZE_NORMAL; + disabled_text.wrapMode = CLAY_TEXT_WRAP_NONE; + CLAY_TEXT(CLAY_STRING("Play Test Tone"), &disabled_text); + } + } + + if (tone_playing) { + ui_label("SettingsLblPlaying", "Playing..."); + } + } + + ui_checkbox("SettingsVsync", "V-Sync", &app->settings_vsync); + + } else if (app->settings_tab == 1) { + // === MIDI tab === + ui_label("SettingsLblMidi", "MIDI settings will go here."); + + } else if (app->settings_tab == 2) { + // === Keyboard Shortcuts tab === + ui_label("SettingsLblKeys", "Keyboard shortcut settings will go here."); + + } else if (app->settings_tab == 3) { + // === Appearance tab === + ui_label("SettingsLblTheme", "Theme"); + static const char *theme_options[] = { "Dark", "Light" }; + CLAY(CLAY_ID("SettingsThemeWrap"), + .layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(220)), .height = CLAY_SIZING_FIT() } } + ) { + ui_dropdown("SettingsTheme", theme_options, 2, &app->settings_theme_sel); + } + + ui_label("SettingsLblAccent", "Accent Color"); + static const char *accent_options[] = { "Blue", "Turquoise", "Orange", "Purple", "Pink", "Red", "Green" }; + CLAY(CLAY_ID("SettingsAccentWrap"), + .layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(220)), .height = CLAY_SIZING_FIT() } } + ) { + ui_dropdown("SettingsAccent", accent_options, 7, &app->accent_sel); + } + + ui_label("SettingsLblRadius", "Corner Radius"); + static const char *radius_options[] = { "None", "Small", "Medium", "Large" }; + CLAY(CLAY_ID("SettingsRadiusWrap"), + .layout = { .sizing = { .width = CLAY_SIZING_FIXED(uis(220)), .height = CLAY_SIZING_FIT() } } + ) { + if (ui_dropdown("SettingsRadius", radius_options, 4, &app->radius_sel)) { + g_theme.corner_radius = radius_values[app->radius_sel]; + } + } + + ui_checkbox("SettingsAutosave", "Autosave", &app->settings_autosave); } } } @@ -1868,8 +1883,8 @@ static void build_ui(AppState *app) { } // Draggable windows (rendered as floating elements above normal UI) - ui_window("WinSettings", "Settings", &app->show_settings_window, - Vec2F32{100, 100}, Vec2F32{280, 0}, + ui_window("WinSettings", "Preferences", &app->show_settings_window, + Vec2F32{100, 100}, Vec2F32{480, 0}, settings_window_content, app); ui_window("WinAbout", "About", &app->show_about_window, @@ -2097,6 +2112,7 @@ int main(int argc, char **argv) { case MENU_VIEW_PROPERTIES:app.show_props = !app.show_props; break; case MENU_VIEW_LOG: app.show_log = !app.show_log; break; case MENU_VIEW_MIDI_DEVICES: app.show_midi_devices = !app.show_midi_devices; break; + case MENU_PREFERENCES_EDIT: app.show_settings_window = 1; break; default: break; } diff --git a/src/menus.cpp b/src/menus.cpp index b59f272..0c7e53e 100644 --- a/src/menus.cpp +++ b/src/menus.cpp @@ -14,6 +14,7 @@ enum MenuCmd { MENU_VIEW_LOG, MENU_VIEW_DEMO, MENU_VIEW_MIDI_DEVICES, + MENU_PREFERENCES_EDIT, }; static void setup_menus(PlatformWindow *window) { @@ -40,10 +41,15 @@ static void setup_menus(PlatformWindow *window) { { "MIDI Devices", MENU_VIEW_MIDI_DEVICES }, }; + PlatformMenuItem prefs_items[] = { + { "Edit Preferences", MENU_PREFERENCES_EDIT }, + }; + PlatformMenu menus[] = { - { "File", file_items, sizeof(file_items) / sizeof(file_items[0]) }, - { "Import", import_items, sizeof(import_items) / sizeof(import_items[0]) }, - { "View", view_items, sizeof(view_items) / sizeof(view_items[0]) }, + { "File", file_items, sizeof(file_items) / sizeof(file_items[0]) }, + { "Import", import_items, sizeof(import_items) / sizeof(import_items[0]) }, + { "View", view_items, sizeof(view_items) / sizeof(view_items[0]) }, + { "Preferences", prefs_items, sizeof(prefs_items) / sizeof(prefs_items[0]) }, }; platform_set_menu(window, menus, sizeof(menus) / sizeof(menus[0]));