add preference menu
This commit is contained in:
210
src/main.cpp
210
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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]));
|
||||
|
||||
Reference in New Issue
Block a user