/* SPDX-License-Identifier: GPL-3.0-or-later * * ft2-nuklear - UI init and refresh * * Layout zones use window-relative proportions derived from the * original 632x400 pixel layout in ft2_gui.c / ft2_pattern_ed.c. * Every fraction is computed once from integer pixel values so the * math is trivially auditable against the original source. */ #define NK_IMPLEMENTATION #define NK_PUGL_CAIRO_IMPLEMENTATION #include "common.h" #include #include #include #include #include #include #include #define app_ptr ((struct ft2_app *)data) /* ------------------------------------------------------------------ */ /* Proportional zone descriptor */ /* */ /* Each zone is expressed as (frac_x, frac_y, frac_w, frac_h) where */ /* fractions are of the *base* 632x400 layout. The actual pixel */ /* rect for a given window size WxH is: */ /* */ /* x = frac_x * W y = frac_y * H */ /* w = frac_w * W h = frac_h * H */ /* */ /* All fractions are trivially derivable from the integer pixel */ /* coords in the original source - see comments below. */ /* ------------------------------------------------------------------ */ typedef struct { float x, y, w, h; } zone_rect; /* ------------------------------------------------------------------ */ /* Zone fractions (precomputed from base 632x400 pixel coords) */ /* */ /* Each zone is commented with its original pixel rectangle so the */ /* fractions can be audited: frac = px / 632 (or / 400 for y/h). */ /* ------------------------------------------------------------------ */ /* * Top-left block: x=0..291, y=0..173 * * Position Editor : 0, 0, 112, 77 -> (0.0, 0.0, 112/632, 77/400) * Logo : 112, 0, 179, 32 -> (112/632, 0.0, 179/632, 32/400) * BPM/Spd/Add : 112, 32, 94, 45 -> (112/632, 32/400, 94/632, 45/400) * Ptn/Ln : 206, 32, 85, 45 -> (206/632, 32/400, 85/632, 45/400) * Status Bar : 0, 77, 291, 15 -> (0.0, 77/400, 291/632, 15/400) * Scopes : 0, 92, 291, 81 -> (0.0, 92/400, 291/632, 81/400) * * Right-menu column: x=291..421 * * Left Menu : 291, 0, 65, 173 -> (291/632, 0.0, 65/632, 173/400) * Right Menu : 356, 0, 65, 173 -> (356/632, 0.0, 65/632, 173/400) * * Instrument switcher: x=421..632 * * Inst Switcher : 421, 0, 211, 173 -> (421/632, 0.0, 211/632, 173/400) * * Bottom: * * Pattern Editor : 0, 173, 632, 210 -> (0.0, 173/400, 1.0, 210/400) * Chan Scroll : 0, 383, 632, 17 -> (0.0, 383/400, 1.0, 17/400) */ static zone_rect zone_pos_ed(float ww, float wh) { zone_rect r = { 0.0f, 0.0f, (112.0f/632.0f)*ww, (77.0f/400.0f)*wh }; return r; } static zone_rect zone_logo(float ww, float wh) { zone_rect r = { (112.0f/632.0f)*ww, 0.0f, (179.0f/632.0f)*ww, (32.0f/400.0f)*wh }; return r; } static zone_rect zone_bpm_spd(float ww, float wh) { zone_rect r = { (112.0f/632.0f)*ww, (32.0f/400.0f)*wh, (94.0f/632.0f)*ww, (45.0f/400.0f)*wh }; return r; } static zone_rect zone_ptn_ln(float ww, float wh) { zone_rect r = { (206.0f/632.0f)*ww, (32.0f/400.0f)*wh, (85.0f/632.0f)*ww, (45.0f/400.0f)*wh }; return r; } static zone_rect zone_status_bar(float ww, float wh) { zone_rect r = { 0.0f, (77.0f/400.0f)*wh, (291.0f/632.0f)*ww, (15.0f/400.0f)*wh }; return r; } static zone_rect zone_scopes(float ww, float wh) { zone_rect r = { 0.0f, (92.0f/400.0f)*wh, (291.0f/632.0f)*ww, (81.0f/400.0f)*wh }; return r; } static zone_rect zone_left_menu(float ww, float wh) { zone_rect r = { (291.0f/632.0f)*ww, 0.0f, (65.0f/632.0f)*ww, (173.0f/400.0f)*wh }; return r; } static zone_rect zone_right_menu(float ww, float wh) { zone_rect r = { (356.0f/632.0f)*ww, 0.0f, (65.0f/632.0f)*ww, (173.0f/400.0f)*wh }; return r; } static zone_rect zone_inst_switcher(float ww, float wh) { zone_rect r = { (421.0f/632.0f)*ww, 0.0f, (211.0f/632.0f)*ww, (173.0f/400.0f)*wh }; return r; } static zone_rect zone_pattern_editor(float ww, float wh) { zone_rect r = { 0.0f, (173.0f/400.0f)*wh, ww, (210.0f/400.0f)*wh }; return r; } static zone_rect zone_chan_scroll(float ww, float wh) { zone_rect r = { 0.0f, (383.0f/400.0f)*wh, ww, (17.0f/400.0f)*wh }; return r; } /* ------------------------------------------------------------------ */ /* Stub zone (bordered rectangle with label) */ /* ------------------------------------------------------------------ */ static void draw_zone(struct nk_context *ctx, const char *name, zone_rect r, int ci) { (void)ci; nk_layout_space_push(ctx, nk_rect(r.x, r.y, r.w, r.h)); if (nk_group_begin(ctx, name, NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BORDER)) { nk_layout_row_dynamic(ctx, r.h, 1); nk_label(ctx, name, NK_TEXT_CENTERED); nk_group_end(ctx); } } /* ------------------------------------------------------------------ */ /* Helper: zero out spacing/padding so buttons fill zone width */ /* ------------------------------------------------------------------ */ static void zero_group_spacing(struct nk_context *ctx) { ctx->style.window.spacing = nk_vec2(0, 0); ctx->style.window.padding = nk_vec2(0, 0); ctx->style.window.group_padding = nk_vec2(0, 0); } /* * Status bar - original ft2_gui.c line 1073/1078: * "Global volume" on the left, "Time" on the right. * 291x15 px base. */ static void draw_status_bar(struct nk_context *ctx, zone_rect r) { nk_layout_space_push(ctx, nk_rect(r.x, r.y, r.w, r.h)); if (nk_group_begin(ctx, "StatusBar", NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BORDER)) { struct nk_vec2 save_sp = ctx->style.window.spacing; struct nk_vec2 save_pd = ctx->style.window.padding; struct nk_vec2 save_gp = ctx->style.window.group_padding; zero_group_spacing(ctx); nk_layout_row_template_begin(ctx, r.h); nk_layout_row_template_push_dynamic(ctx); nk_layout_row_template_push_dynamic(ctx); nk_layout_row_template_end(ctx); nk_label(ctx, "Global volume: 64", NK_TEXT_LEFT); nk_label(ctx, "Time: 00:00:00", NK_TEXT_RIGHT); ctx->style.window.spacing = save_sp; ctx->style.window.padding = save_pd; ctx->style.window.group_padding = save_gp; nk_group_end(ctx); } } /* * Left menu - original ft2_pushbuttons.c lines 91-101: * 11 buttons at x=294, y=2..155, w=59 h=16 each (last row: Add+Sub side by side). * Labels: About, Nibbles, Zap, Trim, Extend, Transps., I.E.Ext., S.E.Ext., Adv. Edit, Add, Sub * * 10 rows, last row has Add/Sub at 50/50 split. */ static void draw_left_menu(struct nk_context *ctx, zone_rect r) { nk_layout_space_push(ctx, nk_rect(r.x, r.y, r.w, r.h)); if (nk_group_begin(ctx, "LeftMenu", NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BORDER)) { const char *labels[] = { "About", "Nibbles", "Zap", "Trim", "Extend", "Transps.", "I.E.Ext.", "S.E.Ext.", "Adv. Edit", NULL /* last row is Add/Sub */ }; const int num_full = 9; /* rows 0..8: single buttons */ const float bh = r.h / 10.0f; /* 10 rows, last row has Add/Sub split */ struct nk_vec2 save_sp = ctx->style.window.spacing; struct nk_vec2 save_pd = ctx->style.window.padding; struct nk_vec2 save_gp = ctx->style.window.group_padding; zero_group_spacing(ctx); for (int i = 0; i < num_full; i++) { nk_layout_row_dynamic(ctx, bh, 1); nk_button_label(ctx, labels[i]); } /* Last row: Add + Sub side by side */ nk_layout_row_dynamic(ctx, bh, 2); nk_button_label(ctx, "Add"); nk_button_label(ctx, "Sub"); ctx->style.window.spacing = save_sp; ctx->style.window.padding = save_pd; ctx->style.window.group_padding = save_gp; nk_group_end(ctx); } } /* * Right menu - original ft2_pushbuttons.c lines 102-111: * 10 buttons at x=359, y=2..155, w=59 h=16 each. * Labels: Play sng., Play ptn., Stop, Rec. sng., Rec. ptn., * Disk op., Instr. Ed., Smp. Ed., Config, Help */ static void draw_right_menu(struct nk_context *ctx, zone_rect r) { nk_layout_space_push(ctx, nk_rect(r.x, r.y, r.w, r.h)); if (nk_group_begin(ctx, "RightMenu", NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BORDER)) { const char *labels[] = { "Play sng.", "Play ptn.", "Stop", "Rec. sng.", "Rec. ptn.", "Disk op.", "Instr. Ed.", "Smp. Ed.", "Config", "Help" }; const int num = 10; const float bh = r.h / (float)num; struct nk_vec2 save_sp = ctx->style.window.spacing; struct nk_vec2 save_pd = ctx->style.window.padding; struct nk_vec2 save_gp = ctx->style.window.group_padding; zero_group_spacing(ctx); nk_layout_row_dynamic(ctx, bh, 1); for (int i = 0; i < num; i++) { if (nk_button_label(ctx, labels[i]) && i == 8) g_app.screen = SCREEN_CONFIG; } ctx->style.window.spacing = save_sp; ctx->style.window.padding = save_pd; ctx->style.window.group_padding = save_gp; nk_group_end(ctx); } } /* ------------------------------------------------------------------ */ /* Unified theming subsystem */ /* */ /* 23 themes: 12 FT2 VGA palettes + 11 LADI Mixer themes. */ /* FT2 palettes use 6-bit VGA RGB converted to 8-bit via P6_TO_P8. */ /* LADI themes are verbatim 8-bit RGBA from ladi-mixer/themes.c. */ /* ------------------------------------------------------------------ */ #define THEME_FT2_ARCTIC 0 #define THEME_FT2_AURORA_BOREALIS 1 #define THEME_FT2_BLUES 2 #define THEME_FT2_GOLD 3 #define THEME_FT2_HEAVY_METAL 4 #define THEME_FT2_JUNGLE 5 #define THEME_FT2_LITHE_DARK 6 #define THEME_FT2_ROSE 7 #define THEME_FT2_DARK_MODE 8 /* default */ #define THEME_FT2_VIOLENT 9 #define THEME_FT2_WHY_COLORS 10 #define THEME_FT2_USER_DEFINED 11 #define THEME_LADI_DARK_ORANGE 12 #define THEME_LADI_BLACK 13 #define THEME_LADI_WHITE 14 #define THEME_LADI_RED 15 #define THEME_LADI_BLUE 16 #define THEME_LADI_DARK 17 #define THEME_LADI_DRACULA 18 #define THEME_LADI_CATPPUCCIN_LATTE 19 #define THEME_LADI_CATPPUCCIN_FRAPPE 20 #define THEME_LADI_CATPPUCCIN_MACCHIATO 21 #define THEME_LADI_CATPPUCCIN_MOCHA 22 #define TOTAL_THEME_COUNT 23 #define THEME_DEFAULT THEME_FT2_DARK_MODE /* 6-bit VGA -> 8-bit: ((x)*255+31)/63 (rounded) */ #define P6_TO_P8(x) (nk_byte)(((x) * 255 + 31) / 63) #define FT2_COLOR(r, g, b) \ nk_rgba(P6_TO_P8(r), P6_TO_P8(g), P6_TO_P8(b), 255) /* FT2 palette color indices (from ft2_palette.h) */ enum { FT2_BCKGRND, FT2_PATTEXT, FT2_BLCKMRK, FT2_BLCKTXT, FT2_DESKTOP, FT2_FORGRND, FT2_BUTTONS, FT2_BTNTEXT, FT2_DSKTOP2, FT2_DSKTOP1, FT2_BUTTON2, FT2_BUTTON1 }; /* 12 FT2 palettes: 12 colors x RGB, 6-bit VGA (from ft2_tables.c) */ static const nk_byte ft2_palettes[12][12][3] = { /* 0 Arctic */ {{0,0,0},{30,38,63},{0,0,17},{63,63,63}, {27,36,40},{63,63,63},{40,40,40},{0,0,0}, {10,13,14},{49,63,63},{15,15,15},{63,63,63}}, /* 1 Aurora Borealis */ {{0,0,0},{21,40,63},{0,0,17},{63,63,63}, {6,39,35},{63,63,63},{40,40,40},{0,0,0}, {2,14,13},{11,63,63},{16,16,16},{63,63,63}}, /* 2 Blues */ {{0,0,0},{39,52,63},{8,8,13},{57,57,63}, {10,21,33},{63,63,63},{37,37,45},{0,0,0}, {4,8,13},{18,37,58},{13,13,16},{63,63,63}}, /* 3 Gold */ {{0,0,0},{47,47,47},{9,9,9},{63,63,63}, {37,29,7},{63,63,63},{40,40,40},{0,0,0}, {11,9,2},{63,58,14},{15,15,15},{63,63,63}}, /* 4 Heavy Metal */ {{0,0,0},{46,45,46},{13,9,9},{63,63,63}, {22,19,22},{63,63,63},{36,32,34},{0,0,0}, {8,7,8},{39,34,39},{13,12,12},{63,58,62}}, /* 5 Jungle */ {{0,0,0},{19,49,54},{0,11,7},{52,63,61}, {9,31,21},{63,63,63},{40,40,40},{0,0,0}, {4,13,9},{15,50,34},{15,15,15},{63,63,63}}, /* 6 LiTHe Dark */ {{0,0,0},{27,37,53},{0,0,20},{63,63,63}, {7,12,21},{63,63,63},{38,39,39},{0,0,0}, {2,4,7},{14,23,41},{13,13,13},{63,63,63}}, /* 7 Rose */ {{0,0,0},{63,54,62},{18,3,3},{63,63,63}, {36,19,25},{63,63,63},{40,40,40},{0,0,0}, {11,6,8},{63,38,50},{15,15,15},{63,63,63}}, /* 8 Dark Mode (default) */ {{0,0,0},{31,36,42},{6,6,9},{47,50,54}, {11,12,13},{55,55,56},{32,32,33},{0,0,0}, {3,4,4},{22,24,26},{15,15,15},{50,50,52}}, /* 9 Violent */ {{0,0,0},{50,46,63},{15,0,16},{59,58,63}, {34,21,41},{63,63,63},{40,40,40},{0,0,0}, {13,8,15},{61,37,63},{15,15,15},{63,63,63}}, /* 10 Why Colors */ {{0,0,0},{63,63,32},{10,10,10},{63,63,63}, {18,29,32},{63,63,63},{39,39,39},{0,0,0}, {6,10,11},{34,54,60},{15,15,15},{63,63,63}}, /* 11 User Defined */ {{0,0,0},{36,47,63},{9,9,16},{63,63,63}, {19,24,38},{63,63,63},{39,39,39},{0,0,0}, {8,10,15},{32,41,63},{15,15,15},{63,63,63}} }; /* 11 LADI Mixer themes: direct 8-bit RGBA (from ladi-mixer/themes.c) */ static const struct nk_color ladi_themes[11][NK_COLOR_COUNT] = { /* 12 Dark Orange */ { [NK_COLOR_TEXT] = {210,210,210,255}, [NK_COLOR_WINDOW] = { 20, 20, 20,255}, [NK_COLOR_HEADER] = { 30, 30, 30,255}, [NK_COLOR_BORDER] = { 80, 80, 80,255}, [NK_COLOR_BUTTON] = { 50, 50, 50,255}, [NK_COLOR_BUTTON_HOVER] = { 70, 70, 70,255}, [NK_COLOR_BUTTON_ACTIVE] = {200,100, 0,255}, [NK_COLOR_TOGGLE] = { 40, 40, 40,255}, [NK_COLOR_TOGGLE_HOVER] = { 60, 60, 60,255}, [NK_COLOR_TOGGLE_CURSOR] = {200,100, 0,255}, [NK_COLOR_SELECT] = { 40, 40, 40,255}, [NK_COLOR_SELECT_ACTIVE] = {200,100, 0,255}, [NK_COLOR_SLIDER] = { 40, 40, 40,255}, [NK_COLOR_SLIDER_CURSOR] = {200,100, 0,245}, [NK_COLOR_SLIDER_CURSOR_HOVER] = {220,120, 0,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = {240,140, 0,255}, [NK_COLOR_PROPERTY] = { 40, 40, 40,255}, [NK_COLOR_EDIT] = { 40, 40, 40,225}, [NK_COLOR_EDIT_CURSOR] = {210,210,210,255}, [NK_COLOR_COMBO] = { 40, 40, 40,255}, [NK_COLOR_CHART] = { 40, 40, 40,255}, [NK_COLOR_CHART_COLOR] = {200,100, 0,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {255, 0, 0,255}, [NK_COLOR_SCROLLBAR] = { 30, 30, 30,255}, [NK_COLOR_SCROLLBAR_CURSOR] = {200,100, 0,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = {220,120, 0,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = {240,140, 0,255}, [NK_COLOR_TAB_HEADER] = { 30, 30, 30,255}, [NK_COLOR_KNOB] = { 40, 40, 40,255}, [NK_COLOR_KNOB_CURSOR] = {200,100, 0,245}, [NK_COLOR_KNOB_CURSOR_HOVER] = {220,120, 0,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = {240,140, 0,255}, }, /* 13 Black */ { [NK_COLOR_TEXT] = {210,210,210,255}, [NK_COLOR_WINDOW] = { 57, 67, 71,215}, [NK_COLOR_HEADER] = { 51, 51, 56,220}, [NK_COLOR_BORDER] = { 46, 46, 46,255}, [NK_COLOR_BUTTON] = { 48, 83,111,255}, [NK_COLOR_BUTTON_HOVER] = { 58, 93,121,255}, [NK_COLOR_BUTTON_ACTIVE] = { 63, 98,126,255}, [NK_COLOR_TOGGLE] = { 50, 58, 61,255}, [NK_COLOR_TOGGLE_HOVER] = { 45, 53, 56,255}, [NK_COLOR_TOGGLE_CURSOR] = { 48, 83,111,255}, [NK_COLOR_SELECT] = { 57, 67, 61,255}, [NK_COLOR_SELECT_ACTIVE] = { 48, 83,111,255}, [NK_COLOR_SLIDER] = { 50, 58, 61,255}, [NK_COLOR_SLIDER_CURSOR] = { 48, 83,111,245}, [NK_COLOR_SLIDER_CURSOR_HOVER] = { 53, 88,116,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = { 58, 93,121,255}, [NK_COLOR_PROPERTY] = { 50, 58, 61,255}, [NK_COLOR_EDIT] = { 50, 58, 61,225}, [NK_COLOR_EDIT_CURSOR] = {210,210,210,255}, [NK_COLOR_COMBO] = { 50, 58, 61,255}, [NK_COLOR_CHART] = { 50, 58, 61,255}, [NK_COLOR_CHART_COLOR] = { 48, 83,111,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {255, 0, 0,255}, [NK_COLOR_SCROLLBAR] = { 50, 58, 61,255}, [NK_COLOR_SCROLLBAR_CURSOR] = { 48, 83,111,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = { 53, 88,116,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = { 58, 93,121,255}, [NK_COLOR_TAB_HEADER] = { 48, 83,111,255}, [NK_COLOR_KNOB] = { 50, 58, 61,255}, [NK_COLOR_KNOB_CURSOR] = { 48, 83,111,245}, [NK_COLOR_KNOB_CURSOR_HOVER] = { 53, 88,116,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = { 58, 93,121,255}, }, /* 14 White */ { [NK_COLOR_TEXT] = { 70, 70, 70,255}, [NK_COLOR_WINDOW] = {175,175,175,255}, [NK_COLOR_HEADER] = {175,175,175,255}, [NK_COLOR_BORDER] = { 0, 0, 0,255}, [NK_COLOR_BUTTON] = {185,185,185,255}, [NK_COLOR_BUTTON_HOVER] = {170,170,170,255}, [NK_COLOR_BUTTON_ACTIVE] = {160,160,160,255}, [NK_COLOR_TOGGLE] = {150,150,150,255}, [NK_COLOR_TOGGLE_HOVER] = {120,120,120,255}, [NK_COLOR_TOGGLE_CURSOR] = {175,175,175,255}, [NK_COLOR_SELECT] = {190,190,190,255}, [NK_COLOR_SELECT_ACTIVE] = {175,175,175,255}, [NK_COLOR_SLIDER] = {190,190,190,255}, [NK_COLOR_SLIDER_CURSOR] = { 80, 80, 80,255}, [NK_COLOR_SLIDER_CURSOR_HOVER] = { 70, 70, 70,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = { 60, 60, 60,255}, [NK_COLOR_PROPERTY] = {175,175,175,255}, [NK_COLOR_EDIT] = {150,150,150,255}, [NK_COLOR_EDIT_CURSOR] = { 0, 0, 0,255}, [NK_COLOR_COMBO] = {175,175,175,255}, [NK_COLOR_CHART] = {160,160,160,255}, [NK_COLOR_CHART_COLOR] = { 45, 45, 45,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {255, 0, 0,255}, [NK_COLOR_SCROLLBAR] = {180,180,180,255}, [NK_COLOR_SCROLLBAR_CURSOR] = {140,140,140,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = {150,150,150,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = {160,160,160,255}, [NK_COLOR_TAB_HEADER] = {180,180,180,255}, [NK_COLOR_KNOB] = {190,190,190,255}, [NK_COLOR_KNOB_CURSOR] = { 80, 80, 80,255}, [NK_COLOR_KNOB_CURSOR_HOVER] = { 70, 70, 70,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = { 60, 60, 60,255}, }, /* 15 Red */ { [NK_COLOR_TEXT] = {190,190,190,255}, [NK_COLOR_WINDOW] = { 30, 33, 40,215}, [NK_COLOR_HEADER] = {181, 45, 69,220}, [NK_COLOR_BORDER] = { 51, 55, 67,255}, [NK_COLOR_BUTTON] = {181, 45, 69,255}, [NK_COLOR_BUTTON_HOVER] = {190, 50, 70,255}, [NK_COLOR_BUTTON_ACTIVE] = {195, 55, 75,255}, [NK_COLOR_TOGGLE] = { 51, 55, 67,255}, [NK_COLOR_TOGGLE_HOVER] = { 45, 60, 60,255}, [NK_COLOR_TOGGLE_CURSOR] = {181, 45, 69,255}, [NK_COLOR_SELECT] = { 51, 55, 67,255}, [NK_COLOR_SELECT_ACTIVE] = {181, 45, 69,255}, [NK_COLOR_SLIDER] = { 51, 55, 67,255}, [NK_COLOR_SLIDER_CURSOR] = {181, 45, 69,255}, [NK_COLOR_SLIDER_CURSOR_HOVER] = {186, 50, 74,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = {191, 55, 79,255}, [NK_COLOR_PROPERTY] = { 51, 55, 67,255}, [NK_COLOR_EDIT] = { 51, 55, 67,225}, [NK_COLOR_EDIT_CURSOR] = {190,190,190,255}, [NK_COLOR_COMBO] = { 51, 55, 67,255}, [NK_COLOR_CHART] = { 51, 55, 67,255}, [NK_COLOR_CHART_COLOR] = {170, 40, 60,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {255, 0, 0,255}, [NK_COLOR_SCROLLBAR] = { 30, 33, 40,255}, [NK_COLOR_SCROLLBAR_CURSOR] = { 64, 84, 95,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = { 70, 90,100,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = { 75, 95,105,255}, [NK_COLOR_TAB_HEADER] = {181, 45, 69,220}, [NK_COLOR_KNOB] = { 51, 55, 67,255}, [NK_COLOR_KNOB_CURSOR] = {181, 45, 69,255}, [NK_COLOR_KNOB_CURSOR_HOVER] = {186, 50, 74,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = {191, 55, 79,255}, }, /* 16 Blue */ { [NK_COLOR_TEXT] = { 20, 20, 20,255}, [NK_COLOR_WINDOW] = {202,212,214,215}, [NK_COLOR_HEADER] = {137,182,224,220}, [NK_COLOR_BORDER] = {140,159,173,255}, [NK_COLOR_BUTTON] = {137,182,224,255}, [NK_COLOR_BUTTON_HOVER] = {142,187,229,255}, [NK_COLOR_BUTTON_ACTIVE] = {147,192,234,255}, [NK_COLOR_TOGGLE] = {177,210,210,255}, [NK_COLOR_TOGGLE_HOVER] = {182,215,215,255}, [NK_COLOR_TOGGLE_CURSOR] = {137,182,224,255}, [NK_COLOR_SELECT] = {177,210,210,255}, [NK_COLOR_SELECT_ACTIVE] = {137,182,224,255}, [NK_COLOR_SLIDER] = {177,210,210,255}, [NK_COLOR_SLIDER_CURSOR] = {137,182,224,245}, [NK_COLOR_SLIDER_CURSOR_HOVER] = {142,188,229,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = {147,193,234,255}, [NK_COLOR_PROPERTY] = {210,210,210,255}, [NK_COLOR_EDIT] = {210,210,210,225}, [NK_COLOR_EDIT_CURSOR] = { 20, 20, 20,255}, [NK_COLOR_COMBO] = {210,210,210,255}, [NK_COLOR_CHART] = {210,210,210,255}, [NK_COLOR_CHART_COLOR] = {137,182,224,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {255, 0, 0,255}, [NK_COLOR_SCROLLBAR] = {190,200,200,255}, [NK_COLOR_SCROLLBAR_CURSOR] = { 64, 84, 95,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = { 70, 90,100,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = { 75, 95,105,255}, [NK_COLOR_TAB_HEADER] = {156,193,220,255}, [NK_COLOR_KNOB] = {177,210,210,255}, [NK_COLOR_KNOB_CURSOR] = {137,182,224,245}, [NK_COLOR_KNOB_CURSOR_HOVER] = {142,188,229,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = {147,193,234,255}, }, /* 17 Dark */ { [NK_COLOR_TEXT] = {210,210,210,255}, [NK_COLOR_WINDOW] = { 57, 67, 71,215}, [NK_COLOR_HEADER] = { 51, 51, 56,220}, [NK_COLOR_BORDER] = { 46, 46, 46,255}, [NK_COLOR_BUTTON] = { 48, 83,111,255}, [NK_COLOR_BUTTON_HOVER] = { 58, 93,121,255}, [NK_COLOR_BUTTON_ACTIVE] = { 63, 98,126,255}, [NK_COLOR_TOGGLE] = { 50, 58, 61,255}, [NK_COLOR_TOGGLE_HOVER] = { 45, 53, 56,255}, [NK_COLOR_TOGGLE_CURSOR] = { 48, 83,111,255}, [NK_COLOR_SELECT] = { 57, 67, 61,255}, [NK_COLOR_SELECT_ACTIVE] = { 48, 83,111,255}, [NK_COLOR_SLIDER] = { 50, 58, 61,255}, [NK_COLOR_SLIDER_CURSOR] = { 48, 83,111,245}, [NK_COLOR_SLIDER_CURSOR_HOVER] = { 53, 88,116,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = { 58, 93,121,255}, [NK_COLOR_PROPERTY] = { 50, 58, 61,255}, [NK_COLOR_EDIT] = { 50, 58, 61,225}, [NK_COLOR_EDIT_CURSOR] = {210,210,210,255}, [NK_COLOR_COMBO] = { 50, 58, 61,255}, [NK_COLOR_CHART] = { 50, 58, 61,255}, [NK_COLOR_CHART_COLOR] = { 48, 83,111,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {255, 0, 0,255}, [NK_COLOR_SCROLLBAR] = { 50, 58, 61,255}, [NK_COLOR_SCROLLBAR_CURSOR] = { 48, 83,111,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = { 53, 88,116,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = { 58, 93,121,255}, [NK_COLOR_TAB_HEADER] = { 48, 83,111,255}, [NK_COLOR_KNOB] = { 50, 58, 61,255}, [NK_COLOR_KNOB_CURSOR] = { 48, 83,111,245}, [NK_COLOR_KNOB_CURSOR_HOVER] = { 53, 88,116,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = { 58, 93,121,255}, }, /* 18 Dracula */ { [NK_COLOR_TEXT] = {248,248,242,255}, [NK_COLOR_WINDOW] = { 40, 42, 54,255}, [NK_COLOR_HEADER] = { 68, 71, 90,255}, [NK_COLOR_BORDER] = { 68, 71, 90,255}, [NK_COLOR_BUTTON] = { 68, 71, 90,255}, [NK_COLOR_BUTTON_HOVER] = { 98,114,164,255}, [NK_COLOR_BUTTON_ACTIVE] = {189,147,249,255}, [NK_COLOR_TOGGLE] = { 68, 71, 90,255}, [NK_COLOR_TOGGLE_HOVER] = { 98,114,164,255}, [NK_COLOR_TOGGLE_CURSOR] = {255,121,198,255}, [NK_COLOR_SELECT] = { 68, 71, 90,255}, [NK_COLOR_SELECT_ACTIVE] = { 98,114,164,255}, [NK_COLOR_SLIDER] = { 40, 42, 54,255}, [NK_COLOR_SLIDER_CURSOR] = { 68, 71, 90,255}, [NK_COLOR_SLIDER_CURSOR_HOVER] = { 98,114,164,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = { 98,114,164,255}, [NK_COLOR_PROPERTY] = { 68, 71, 90,255}, [NK_COLOR_EDIT] = { 68, 71, 90,255}, [NK_COLOR_EDIT_CURSOR] = {248,248,242,255}, [NK_COLOR_COMBO] = { 68, 71, 90,255}, [NK_COLOR_CHART] = { 68, 71, 90,255}, [NK_COLOR_CHART_COLOR] = { 98,114,164,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {189,147,249,255}, [NK_COLOR_SCROLLBAR] = { 40, 42, 54,255}, [NK_COLOR_SCROLLBAR_CURSOR] = { 68, 71, 90,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = { 98,114,164,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = {189,147,249,255}, [NK_COLOR_TAB_HEADER] = { 68, 71, 90,255}, [NK_COLOR_KNOB] = { 40, 42, 54,255}, [NK_COLOR_KNOB_CURSOR] = { 68, 71, 90,255}, [NK_COLOR_KNOB_CURSOR_HOVER] = { 98,114,164,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = { 98,114,164,255}, }, /* 19 Catppuccin Latte */ { [NK_COLOR_TEXT] = { 76, 79,105,255}, [NK_COLOR_WINDOW] = {239,241,245,255}, [NK_COLOR_HEADER] = {230,233,239,255}, [NK_COLOR_BORDER] = {230,233,239,255}, [NK_COLOR_BUTTON] = {204,208,218,255}, [NK_COLOR_BUTTON_HOVER] = {124,127,147, 55}, [NK_COLOR_BUTTON_ACTIVE] = {156,160,176,255}, [NK_COLOR_TOGGLE] = {172,176,190,255}, [NK_COLOR_TOGGLE_HOVER] = {124,127,147, 55}, [NK_COLOR_TOGGLE_CURSOR] = {223,142, 29,255}, [NK_COLOR_SELECT] = {204,208,218,255}, [NK_COLOR_SELECT_ACTIVE] = {156,160,176,255}, [NK_COLOR_SLIDER] = {188,192,204,255}, [NK_COLOR_SLIDER_CURSOR] = { 23,146,153,255}, [NK_COLOR_SLIDER_CURSOR_HOVER] = { 23,146,153,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = { 23,146,153,255}, [NK_COLOR_PROPERTY] = {204,208,218,255}, [NK_COLOR_EDIT] = {204,208,218,255}, [NK_COLOR_EDIT_CURSOR] = {136, 57,239,255}, [NK_COLOR_COMBO] = {204,208,218,255}, [NK_COLOR_CHART] = {204,208,218,255}, [NK_COLOR_CHART_COLOR] = { 23,146,153,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {136, 57,239,255}, [NK_COLOR_SCROLLBAR] = {204,208,218,255}, [NK_COLOR_SCROLLBAR_CURSOR] = {156,160,176,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = {136, 57,239,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = {136, 57,239,255}, [NK_COLOR_TAB_HEADER] = {204,208,218,255}, [NK_COLOR_KNOB] = {188,192,204,255}, [NK_COLOR_KNOB_CURSOR] = {234,118,203,255}, [NK_COLOR_KNOB_CURSOR_HOVER] = {234,118,203,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = {234,118,203,255}, }, /* 20 Catppuccin Frappe */ { [NK_COLOR_TEXT] = {198,208,245,255}, [NK_COLOR_WINDOW] = { 48, 52, 70,255}, [NK_COLOR_HEADER] = { 41, 44, 60,255}, [NK_COLOR_BORDER] = { 41, 44, 60,255}, [NK_COLOR_BUTTON] = { 65, 69, 89,255}, [NK_COLOR_BUTTON_HOVER] = {131,139,167,255}, [NK_COLOR_BUTTON_ACTIVE] = {115,121,148,255}, [NK_COLOR_TOGGLE] = { 98,104,128,255}, [NK_COLOR_TOGGLE_HOVER] = {148,156,187,255}, [NK_COLOR_TOGGLE_CURSOR] = {244,184,228,255}, [NK_COLOR_SELECT] = { 65, 69, 89,255}, [NK_COLOR_SELECT_ACTIVE] = {115,121,148,255}, [NK_COLOR_SLIDER] = { 81, 87,109,255}, [NK_COLOR_SLIDER_CURSOR] = {166,209,137,255}, [NK_COLOR_SLIDER_CURSOR_HOVER] = {166,209,137,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = {166,209,137,255}, [NK_COLOR_PROPERTY] = { 65, 69, 89,255}, [NK_COLOR_EDIT] = { 65, 69, 89,255}, [NK_COLOR_EDIT_CURSOR] = {244,184,228,255}, [NK_COLOR_COMBO] = { 65, 69, 89,255}, [NK_COLOR_CHART] = { 65, 69, 89,255}, [NK_COLOR_CHART_COLOR] = {186,187,241,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {244,184,228,255}, [NK_COLOR_SCROLLBAR] = { 65, 69, 89,255}, [NK_COLOR_SCROLLBAR_CURSOR] = {115,121,148,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = {186,187,241,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = {186,187,241,255}, [NK_COLOR_TAB_HEADER] = { 65, 69, 89,255}, [NK_COLOR_KNOB] = { 81, 87,109,255}, [NK_COLOR_KNOB_CURSOR] = {244,184,228,255}, [NK_COLOR_KNOB_CURSOR_HOVER] = {244,184,228,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = {244,184,228,255}, }, /* 21 Catppuccin Macchiato */ { [NK_COLOR_TEXT] = {202,211,245,255}, [NK_COLOR_WINDOW] = { 36, 39, 58,255}, [NK_COLOR_HEADER] = { 30, 32, 48,255}, [NK_COLOR_BORDER] = { 30, 32, 48,255}, [NK_COLOR_BUTTON] = { 54, 58, 79,255}, [NK_COLOR_BUTTON_HOVER] = {128,135,162,255}, [NK_COLOR_BUTTON_ACTIVE] = {110,115,141,255}, [NK_COLOR_TOGGLE] = { 91, 96,120,255}, [NK_COLOR_TOGGLE_HOVER] = {147,154,183,255}, [NK_COLOR_TOGGLE_CURSOR] = {238,212,159,255}, [NK_COLOR_SELECT] = { 54, 58, 79,255}, [NK_COLOR_SELECT_ACTIVE] = {110,115,141,255}, [NK_COLOR_SLIDER] = { 73, 77,100,255}, [NK_COLOR_SLIDER_CURSOR] = {166,218,149,255}, [NK_COLOR_SLIDER_CURSOR_HOVER] = {166,218,149,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = {166,218,149,255}, [NK_COLOR_PROPERTY] = { 54, 58, 79,255}, [NK_COLOR_EDIT] = { 54, 58, 79,255}, [NK_COLOR_EDIT_CURSOR] = {245,189,230,255}, [NK_COLOR_COMBO] = { 54, 58, 79,255}, [NK_COLOR_CHART] = { 54, 58, 79,255}, [NK_COLOR_CHART_COLOR] = {183,189,248,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {238,212,159,255}, [NK_COLOR_SCROLLBAR] = { 54, 58, 79,255}, [NK_COLOR_SCROLLBAR_CURSOR] = {110,115,141,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = {183,189,248,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = {183,189,248,255}, [NK_COLOR_TAB_HEADER] = { 54, 58, 79,255}, [NK_COLOR_KNOB] = { 73, 77,100,255}, [NK_COLOR_KNOB_CURSOR] = {245,189,230,255}, [NK_COLOR_KNOB_CURSOR_HOVER] = {245,189,230,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = {245,189,230,255}, }, /* 22 Catppuccin Mocha */ { [NK_COLOR_TEXT] = {205,214,244,255}, [NK_COLOR_WINDOW] = { 30, 30, 46,255}, [NK_COLOR_HEADER] = { 24, 24, 37,255}, [NK_COLOR_BORDER] = { 24, 24, 37,255}, [NK_COLOR_BUTTON] = { 49, 50, 68,255}, [NK_COLOR_BUTTON_HOVER] = {127,132,156,255}, [NK_COLOR_BUTTON_ACTIVE] = {108,112,134,255}, [NK_COLOR_TOGGLE] = { 88, 91,112,255}, [NK_COLOR_TOGGLE_HOVER] = {147,153,178,255}, [NK_COLOR_TOGGLE_CURSOR] = {180,190,254,255}, [NK_COLOR_SELECT] = { 49, 50, 68,255}, [NK_COLOR_SELECT_ACTIVE] = {108,112,134,255}, [NK_COLOR_SLIDER] = { 69, 71, 90,255}, [NK_COLOR_SLIDER_CURSOR] = {166,227,161,255}, [NK_COLOR_SLIDER_CURSOR_HOVER] = {166,227,161,255}, [NK_COLOR_SLIDER_CURSOR_ACTIVE] = {166,227,161,255}, [NK_COLOR_PROPERTY] = { 49, 50, 68,255}, [NK_COLOR_EDIT] = { 49, 50, 68,255}, [NK_COLOR_EDIT_CURSOR] = {180,190,254,255}, [NK_COLOR_COMBO] = { 49, 50, 68,255}, [NK_COLOR_CHART] = { 49, 50, 68,255}, [NK_COLOR_CHART_COLOR] = {180,190,254,255}, [NK_COLOR_CHART_COLOR_HIGHLIGHT] = {245,194,231,255}, [NK_COLOR_SCROLLBAR] = { 49, 50, 68,255}, [NK_COLOR_SCROLLBAR_CURSOR] = {108,112,134,255}, [NK_COLOR_SCROLLBAR_CURSOR_HOVER] = {180,190,254,255}, [NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = {245,194,231,255}, [NK_COLOR_TAB_HEADER] = { 49, 50, 68,255}, [NK_COLOR_KNOB] = { 69, 71, 90,255}, [NK_COLOR_KNOB_CURSOR] = {245,194,231,255}, [NK_COLOR_KNOB_CURSOR_HOVER] = {245,194,231,255}, [NK_COLOR_KNOB_CURSOR_ACTIVE] = {245,194,231,255}, } }; static const char * const theme_names[TOTAL_THEME_COUNT] = { "FT2 Arctic", "FT2 Aurora Borealis", "FT2 Blues", "FT2 Gold", "FT2 Heavy Metal", "FT2 Jungle", "FT2 LiTHe Dark", "FT2 Rose", "FT2 Dark Mode", "FT2 Violent", "FT2 Why Colors", "FT2 User Defined", "Dark Orange", "Black", "White", "Red", "Blue", "Dark", "Dracula", "Catppuccin Latte", "Catppuccin Frappe", "Catppuccin Macchiato", "Catppuccin Mocha" }; static void apply_theme(struct nk_context *ctx, int theme_idx) { if (theme_idx < 0 || theme_idx >= TOTAL_THEME_COUNT) theme_idx = THEME_DEFAULT; if (theme_idx < 12) { /* FT2 palette: convert 6-bit VGA to NK_COLOR table */ const nk_byte (*p)[3] = ft2_palettes[theme_idx]; struct nk_color t[NK_COLOR_COUNT]; t[NK_COLOR_TEXT] = FT2_COLOR(p[FT2_FORGRND][0], p[FT2_FORGRND][1], p[FT2_FORGRND][2]); t[NK_COLOR_WINDOW] = FT2_COLOR(p[FT2_DESKTOP][0], p[FT2_DESKTOP][1], p[FT2_DESKTOP][2]); t[NK_COLOR_HEADER] = FT2_COLOR(p[FT2_DESKTOP][0], p[FT2_DESKTOP][1], p[FT2_DESKTOP][2]); t[NK_COLOR_BORDER] = FT2_COLOR(p[FT2_DSKTOP2][0], p[FT2_DSKTOP2][1], p[FT2_DSKTOP2][2]); t[NK_COLOR_BUTTON] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_BUTTON_HOVER] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_BUTTON_ACTIVE] = FT2_COLOR(p[FT2_BUTTON2][0], p[FT2_BUTTON2][1], p[FT2_BUTTON2][2]); t[NK_COLOR_TOGGLE] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_TOGGLE_HOVER] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_TOGGLE_CURSOR] = FT2_COLOR(p[FT2_BTNTEXT][0], p[FT2_BTNTEXT][1], p[FT2_BTNTEXT][2]); t[NK_COLOR_SELECT] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_SELECT_ACTIVE] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_SLIDER] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_SLIDER_CURSOR] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_SLIDER_CURSOR_HOVER] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_SLIDER_CURSOR_ACTIVE] = FT2_COLOR(p[FT2_BUTTON2][0], p[FT2_BUTTON2][1], p[FT2_BUTTON2][2]); t[NK_COLOR_PROPERTY] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_EDIT] = FT2_COLOR(p[FT2_BCKGRND][0], p[FT2_BCKGRND][1], p[FT2_BCKGRND][2]); t[NK_COLOR_EDIT_CURSOR] = FT2_COLOR(p[FT2_FORGRND][0], p[FT2_FORGRND][1], p[FT2_FORGRND][2]); t[NK_COLOR_COMBO] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_CHART] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_CHART_COLOR] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_CHART_COLOR_HIGHLIGHT] = FT2_COLOR(p[FT2_BUTTON2][0], p[FT2_BUTTON2][1], p[FT2_BUTTON2][2]); t[NK_COLOR_SCROLLBAR] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_SCROLLBAR_CURSOR] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = FT2_COLOR(p[FT2_BUTTON2][0], p[FT2_BUTTON2][1], p[FT2_BUTTON2][2]); t[NK_COLOR_TAB_HEADER] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_KNOB] = FT2_COLOR(p[FT2_BUTTONS][0], p[FT2_BUTTONS][1], p[FT2_BUTTONS][2]); t[NK_COLOR_KNOB_CURSOR] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_KNOB_CURSOR_HOVER] = FT2_COLOR(p[FT2_BUTTON1][0], p[FT2_BUTTON1][1], p[FT2_BUTTON1][2]); t[NK_COLOR_KNOB_CURSOR_ACTIVE] = FT2_COLOR(p[FT2_BUTTON2][0], p[FT2_BUTTON2][1], p[FT2_BUTTON2][2]); nk_style_from_table(ctx, t); /* FT2 button text uses BTNTEXT, not global TEXT */ { struct nk_color bt = FT2_COLOR(p[FT2_BTNTEXT][0], p[FT2_BTNTEXT][1], p[FT2_BTNTEXT][2]); ctx->style.button.text_normal = bt; ctx->style.button.text_hover = bt; ctx->style.button.text_active = bt; } } else { /* LADI Mixer theme: pre-built 8-bit RGBA table */ nk_style_from_table(ctx, ladi_themes[theme_idx - 12]); } } /* * Config screen - full-window placeholder with Back button. * Clicking Back returns to SCREEN_NORMAL. */ static void draw_config_screen(struct nk_context *ctx, struct nk_rect wbounds) { nk_layout_row_dynamic(ctx, wbounds.h, 1); if (nk_group_begin(ctx, "ConfigScreen", NK_WINDOW_NO_SCROLLBAR)) { nk_layout_row_dynamic(ctx, 30, 1); nk_label(ctx, "Config screen", NK_TEXT_CENTERED); /* Theme selector */ nk_layout_row_dynamic(ctx, 30, 2); nk_label(ctx, "Theme:", NK_TEXT_LEFT); int sel = nk_combo( ctx, theme_names, TOTAL_THEME_COUNT, g_app.theme, 25, nk_vec2(200, 25 * TOTAL_THEME_COUNT)); if (sel != g_app.theme) { g_app.theme = sel; apply_theme(ctx, sel); } nk_layout_row_dynamic(ctx, 30, 1); if (nk_button_label(ctx, "Back")) g_app.screen = SCREEN_NORMAL; nk_group_end(ctx); } } /* ------------------------------------------------------------------ */ /* Main refresh callback */ /* ------------------------------------------------------------------ */ static void on_nk_pugl_refresh( struct nk_context *ctx, struct nk_rect *wbounds_ptr, void *data) { static bool theme_applied = false; (void)data; if (!theme_applied) { g_app.theme = THEME_DEFAULT; apply_theme(ctx, g_app.theme); theme_applied = true; } struct nk_vec2 old_spacing = ctx->style.window.spacing; struct nk_vec2 old_padding = ctx->style.window.padding; struct nk_vec2 old_group_padding = ctx->style.window.group_padding; ctx->style.window.spacing = nk_vec2(0, 0); ctx->style.window.padding = nk_vec2(0, 0); ctx->style.window.group_padding = nk_vec2(0, 0); if (nk_begin(ctx, "ft2main", *wbounds_ptr, NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BACKGROUND)) { if (g_app.screen == SCREEN_CONFIG) { draw_config_screen(ctx, *wbounds_ptr); } else { const float ww = wbounds_ptr->w; const float wh = wbounds_ptr->h; nk_layout_space_begin(ctx, NK_STATIC, wh, 11); /* === TOP-LEFT === */ draw_zone(ctx, "Position Editor", zone_pos_ed(ww, wh), 0); draw_zone(ctx, "Logo", zone_logo(ww, wh), 1); draw_zone(ctx, "BPM/Spd/Add", zone_bpm_spd(ww, wh), 2); draw_zone(ctx, "Ptn/Ln/Expd/Srnk", zone_ptn_ln(ww, wh), 3); draw_status_bar(ctx, zone_status_bar(ww, wh)); draw_zone(ctx, "Scopes", zone_scopes(ww, wh), 4); draw_left_menu(ctx, zone_left_menu(ww, wh)); draw_right_menu(ctx, zone_right_menu(ww, wh)); /* === INSTRUMENT SWITCHER === */ draw_zone(ctx, "Inst Switcher", zone_inst_switcher(ww, wh), 5); /* === BOTTOM === */ draw_zone(ctx, "Pattern Editor", zone_pattern_editor(ww, wh), 6); draw_zone(ctx, "Chan Scroll", zone_chan_scroll(ww, wh), 7); nk_layout_space_end(ctx); } } nk_end(ctx); ctx->style.window.spacing = old_spacing; ctx->style.window.padding = old_padding; ctx->style.window.group_padding = old_group_padding; } #undef app_ptr static bool init_DPI_and_scale_factor96(struct ft2_app *app_ptr) { double dpi = 96.0; int w, h, w_mm, h_mm; double xdpi, ydpi; int screen; Display *display = XOpenDisplay(NULL); if (display == NULL) return false; screen = DefaultScreen(display); w = DisplayWidth(display, screen); w_mm = DisplayWidthMM(display, screen); h = DisplayHeight(display, screen); h_mm = DisplayHeightMM(display, screen); if (w_mm > 0 && h_mm > 0) { xdpi = (w * 25.4) / w_mm; ydpi = (h * 25.4) / h_mm; dpi = (xdpi + ydpi) / 2; } else { xdpi = dpi; ydpi = dpi; } /* Check Xft.dpi resource override */ const char *const rms = XResourceManagerString(display); if (rms) { XrmDatabase db = XrmGetStringDatabase(rms); if (db) { XrmValue value = {0U, NULL}; char *type = NULL; if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value)) { if (!type || !strcmp(type, "String")) { char *end = NULL; const double xftDpi = strtod(value.addr, &end); if (xftDpi > 0.0 && xftDpi < 1e6) { dpi = xftDpi; xdpi = dpi; ydpi = dpi; } } } XrmDestroyDatabase(db); } } XCloseDisplay(display); app_ptr->scale = dpi / 96.0; app_ptr->xdpi = xdpi; app_ptr->ydpi = ydpi; return true; } bool ui_init(struct ft2_app *app_ptr) { if (!init_DPI_and_scale_factor96(app_ptr)) return false; nk_pugl_config_t *cfg_ptr = &app_ptr->cfg; memset(cfg_ptr, 0, sizeof(*cfg_ptr)); /* FT2 native resolution is 640x480, scale by DPI */ cfg_ptr->width = (nk_uint)(640 * app_ptr->scale); cfg_ptr->height = (nk_uint)(480 * app_ptr->scale); cfg_ptr->min.width = 640; cfg_ptr->min.height = 480; cfg_ptr->resizable = nk_true; cfg_ptr->class = "ft2-nuklear"; cfg_ptr->title = "ft2-nuklear"; cfg_ptr->parent = 0; cfg_ptr->data = app_ptr; cfg_ptr->refresh_cb = on_nk_pugl_refresh; cfg_ptr->fontname = NULL; /* use default */ cfg_ptr->fontsize = round(12.0 * app_ptr->ydpi / 72.0); app_ptr->win_ptr = nk_pugl_init(cfg_ptr); if (!app_ptr->win_ptr) { fprintf(stderr, "Cannot initialize nk_pugl_cairo\n"); return false; } fprintf(stderr, "ft2-nuklear: scale=%.2f ydpi=%.1f fontsize=%.1f window=%ux%u\n", app_ptr->scale, app_ptr->ydpi, cfg_ptr->fontsize, cfg_ptr->width, cfg_ptr->height); nk_pugl_show(app_ptr->win_ptr, nk_true); return true; } void ui_deinit(struct ft2_app *app_ptr) { nk_pugl_show(app_ptr->win_ptr, nk_false); nk_pugl_shutdown(app_ptr->win_ptr); }