add preference menu

This commit is contained in:
2026-03-05 09:55:24 -05:00
parent 9b3afcfb46
commit 96f43eda44
2 changed files with 122 additions and 100 deletions

View File

@@ -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;
}

View File

@@ -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]));