diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index 28732b74..a062c6a0 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -396,7 +396,7 @@ DF_CoreCmdTable:// | | | {Breakpoints 0 Null Nil 0 0 0 0 0 0 CircleFilled "breakpoints" "Breakpoints" "Opens the breakpoints view." "" } {WatchPins 0 Null Nil 0 0 0 0 0 0 Pin "watch_pins" "Watch Pins" "Opens the watch pins view." "" } {ExceptionFilters 0 Null Nil 0 0 0 0 0 0 Gear "exception_filters" "Exception Filters" "Opens the exception filters view." "exceptions,filters" } - {Theme 0 Null Nil 0 0 0 0 0 0 Palette "theme" "Theme" "Opens the theme view." "theme,color,scheme,palette" } + {Settings 0 Null Nil 0 0 0 0 0 0 Gear "settings" "Settings" "Opens the settings view." "theme,color,scheme,options" } {PickFile 1 FilePath Nil 1 0 0 0 0 1 FileOutline "pick_file" "Pick File" "Opens the file browser to pick a file." "" } {PickFolder 1 FilePath Nil 0 1 0 0 0 1 FolderOpenFilled "pick_folder" "Pick Folder" "Opens the file browser to pick a folder." "" } {PickFileOrFolder 1 FilePath Nil 1 1 0 0 0 1 FileOutline "pick_file_or_folder" "Pick File/Folder" "Opens the file browser to pick a file or folder." "" } diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index 3fc0a521..7f6d400e 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -423,7 +423,7 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[220] = { str8_lit_comp("breakpoints"), str8_lit_comp("Opens the breakpoints view."), str8_lit_comp(""), str8_lit_comp("Breakpoints"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled}, { str8_lit_comp("watch_pins"), str8_lit_comp("Opens the watch pins view."), str8_lit_comp(""), str8_lit_comp("Watch Pins"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Pin}, { str8_lit_comp("exception_filters"), str8_lit_comp("Opens the exception filters view."), str8_lit_comp("exceptions,filters"), str8_lit_comp("Exception Filters"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Gear}, -{ str8_lit_comp("theme"), str8_lit_comp("Opens the theme view."), str8_lit_comp("theme,color,scheme,palette"), str8_lit_comp("Theme"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Palette}, +{ str8_lit_comp("settings"), str8_lit_comp("Opens the settings view."), str8_lit_comp("theme,color,scheme,options"), str8_lit_comp("Settings"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Gear}, { str8_lit_comp("pick_file"), str8_lit_comp("Opens the file browser to pick a file."), str8_lit_comp(""), str8_lit_comp("Pick File"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline}, { str8_lit_comp("pick_folder"), str8_lit_comp("Opens the file browser to pick a folder."), str8_lit_comp(""), str8_lit_comp("Pick Folder"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*1)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FolderOpenFilled}, { str8_lit_comp("pick_file_or_folder"), str8_lit_comp("Opens the file browser to pick a file or folder."), str8_lit_comp(""), str8_lit_comp("Pick File/Folder"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*1)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline}, diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index 462a6852..c40cf0f1 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -259,7 +259,7 @@ DF_CoreCmdKind_Disassembly, DF_CoreCmdKind_Breakpoints, DF_CoreCmdKind_WatchPins, DF_CoreCmdKind_ExceptionFilters, -DF_CoreCmdKind_Theme, +DF_CoreCmdKind_Settings, DF_CoreCmdKind_PickFile, DF_CoreCmdKind_PickFolder, DF_CoreCmdKind_PickFileOrFolder, diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 77f68220..01708506 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -5064,7 +5064,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DF_CoreCmdKind_Breakpoints, DF_CoreCmdKind_WatchPins, DF_CoreCmdKind_FilePathMap, - DF_CoreCmdKind_Theme, + DF_CoreCmdKind_Settings, DF_CoreCmdKind_ExceptionFilters, DF_CoreCmdKind_GettingStarted, }; @@ -7013,8 +7013,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) ui_spacer(ui_em(0.5f, 1.f)); UI_Font(view->spec->info.flags & DF_ViewSpecFlag_FilterIsCode ? df_font_from_slot(DF_FontSlot_Code) : df_font_from_slot(DF_FontSlot_Main)) UI_Focus(view->is_filtering ? UI_FocusKind_On : UI_FocusKind_Off) { - UI_Signal sig = df_line_edit(DF_LineEditFlag_Border| - DF_LineEditFlag_CodeContents*!!(view->spec->info.flags & DF_ViewSpecFlag_FilterIsCode), + UI_Signal sig = df_line_edit(DF_LineEditFlag_CodeContents*!!(view->spec->info.flags & DF_ViewSpecFlag_FilterIsCode), 0, 0, &view->query_cursor, @@ -7407,7 +7406,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) { D_FancyString query = { - df_font_from_slot(DF_FontSlot_Code), + view->spec->info.flags & DF_ViewSpecFlag_FilterIsCode ? df_font_from_slot(DF_FontSlot_Code) : df_font_from_slot(DF_FontSlot_Main), str8(view->query_buffer, view->query_string_size), ui_top_palette()->colors[UI_ColorCode_TextWeak], ui_top_font_size(), @@ -8196,7 +8195,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) { Vec4F32 color = df_rgba_from_theme_color(DF_ThemeColor_Focus); color.w *= b->focus_active_t; - R_Rect2DInst *inst = d_rect(pad_2f32(b->rect, 1.f), color, 0, 1.f, 1.f); + R_Rect2DInst *inst = d_rect(pad_2f32(b->rect, 0.f), color, 0, 1.f, 1.f); MemoryCopyArray(inst->corner_radii, b->corner_radii); } @@ -10989,7 +10988,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ ui_set_next_pref_height(ui_pct(1, 0)); ui_set_next_palette(ui_build_palette(ui_top_palette(), .text = color)); ui_set_next_text_alignment(UI_TextAlign_Center); - UI_Key thread_box_key = ui_key_from_stringf(top_container_box->key, "###ip_%p", thread); + UI_Key thread_box_key = ui_key_from_stringf(top_container_box->key, "###ip_%I64x_%p", line_num, thread); UI_Box *thread_box = ui_build_box_from_key(UI_BoxFlag_DisableTextTrunc| UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable)| UI_BoxFlag_DrawText, @@ -11144,7 +11143,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ ui_set_next_pref_height(ui_pct(1, 0)); ui_set_next_palette(ui_build_palette(ui_top_palette(), .text = color)); ui_set_next_text_alignment(UI_TextAlign_Center); - UI_Key thread_box_key = ui_key_from_stringf(top_container_box->key, "###ip_%p", thread); + UI_Key thread_box_key = ui_key_from_stringf(top_container_box->key, "###ip_%I64x_catchall_%p", line_num, thread); UI_Box *thread_box = ui_build_box_from_key(UI_BoxFlag_DisableTextTrunc| UI_BoxFlag_Clickable*!!(params->flags & DF_CodeSliceFlag_Clickable)| UI_BoxFlag_DrawText, diff --git a/src/df/gfx/df_gfx.mdesk b/src/df/gfx/df_gfx.mdesk index 6c6814b5..e4c0f568 100644 --- a/src/df/gfx/df_gfx.mdesk +++ b/src/df/gfx/df_gfx.mdesk @@ -240,7 +240,7 @@ DF_GfxViewTable: { Breakpoints "breakpoints" "Breakpoints" Null CircleFilled 0 0 1 0 1 0 1 1 "Displays a table of all breakpoints, containing information about each breakpoint's name, location, and hit count. Also contains per-breakpoint controls for enabling, deleting, or editing each breakpoint. For more information on breakpoints and their features, read the 'Breakpoints' section." } { WatchPins "watch_pins" "Watch Pins" Null Pin 0 0 1 0 1 1 1 1 "Displays a table of all watch pins (watched expressions, like those found in `Watch`, but instead of being within a table, being pinned to some source code location, like breakpoints). This table contains each pin's name, location, and controls for editing or deleting each pin." } { ExceptionFilters "exception_filters" "Exception Filters" Null Gear 0 0 1 0 1 0 1 1 "An interface which controls whether or not the debugger will halt attached processes upon encountering specific exception codes for the first time." } - { Theme "theme" "Theme" Null Palette 0 0 1 0 0 0 0 1 "An interface for modifying the colors used in the debugger's UI. Allows selecting a theme preset, loading a theme from a file, and modifying individual colors within a theme." } + { Settings "settings" "Settings" Null Gear 0 0 1 0 1 0 1 1 "An interface to modify general settings for the debugger's appearance and behavior." } } @enum DF_GfxViewKind: @@ -630,7 +630,7 @@ DF_SettingTable: {ThreadGlow thread_glow "Thread Glow" 1 0 1 } {BreakpointGlow breakpoint_glow "Breakpoint Glow" 1 0 1 } {OpaqueBackgrounds opaque_backgrounds "Opaque Backgrounds" 0 0 1 } - {TabWidth tab_width "Tab Width" 4 0 32 } + {TabWidth tab_width "Tab Width" 4 1 32 } } @enum DF_SettingCode: diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 8c36c7e8..0adf8139 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -153,6 +153,29 @@ df_qsort_compare_entity_lister__strength(DF_EntityListerItem *a, DF_EntityLister return result; } +internal int +df_qsort_compare_settings_item(DF_SettingsItem *a, DF_SettingsItem *b) +{ + int result = 0; + if(a->string_matches.count > b->string_matches.count) + { + result = -1; + } + else if(a->string_matches.count < b->string_matches.count) + { + result = +1; + } + else if(a->kind_string_matches.count > b->kind_string_matches.count) + { + result = -1; + } + else if(a->kind_string_matches.count < b->kind_string_matches.count) + { + result = +1; + } + return result; +} + //////////////////////////////// //~ rjf: Command Lister @@ -607,7 +630,7 @@ df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewSta { if(df_entity_from_handle(n->v.file) == file && visible_line_num_range.min <= n->v.pt.line && n->v.pt.line <= visible_line_num_range.max) { - U64 slice_line_idx = lines.first->v.pt.line-visible_line_num_range.min; + U64 slice_line_idx = n->v.pt.line-visible_line_num_range.min; df_entity_list_push(scratch.arena, &code_slice_params.line_ips[slice_line_idx], thread); } } @@ -8379,12 +8402,12 @@ DF_VIEW_UI_FUNCTION_DEF(ExceptionFilters) } //////////////////////////////// -//~ rjf: Theme @view_hook_impl +//~ rjf: Settings @view_hook_impl -DF_VIEW_SETUP_FUNCTION_DEF(Theme) {} -DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Theme) {return str8_lit("");} +DF_VIEW_SETUP_FUNCTION_DEF(Settings) {} +DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Settings) {return str8_zero();} -DF_VIEW_CMD_FUNCTION_DEF(Theme) +DF_VIEW_CMD_FUNCTION_DEF(Settings) { for(DF_CmdNode *n = cmds->first; n != 0; n = n->next) { @@ -8397,7 +8420,7 @@ DF_VIEW_CMD_FUNCTION_DEF(Theme) continue; } - //rjf: process + // rjf: process DF_CoreCmdKind core_cmd_kind = df_core_cmd_kind_from_string(cmd->spec->info.string); switch(core_cmd_kind) { @@ -8445,11 +8468,433 @@ DF_VIEW_CMD_FUNCTION_DEF(Theme) } } -DF_VIEW_UI_FUNCTION_DEF(Theme) +DF_VIEW_UI_FUNCTION_DEF(Settings) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); + String8 query = str8(view->query_buffer, view->query_string_size); + + ////////////////////////////// + //- rjf: get state + // + typedef struct DF_SettingsViewState DF_SettingsViewState; + struct DF_SettingsViewState + { + Vec2S64 cursor; + TxtPt txt_cursor; + TxtPt txt_mark; + U8 txt_buffer[1024]; + U64 txt_size; + DF_ThemeColor color_ctx_menu_color; + Vec4F32 color_ctx_menu_color_hsva; + }; + DF_SettingsViewState *sv = df_view_user_state(view, DF_SettingsViewState); + + ////////////////////////////// + //- rjf: gather all filtered settings items + // + DF_SettingsItemArray items = {0}; + { + DF_SettingsItemList items_list = {0}; + + //- rjf: gather all settings + for(EachEnumVal(DF_SettingCode, code)) + { + String8 kind_string = str8_lit("Interface"); + String8 string = df_g_setting_code_display_string_table[code]; + FuzzyMatchRangeList kind_string_matches = fuzzy_match_find(scratch.arena, query, kind_string); + FuzzyMatchRangeList string_matches = fuzzy_match_find(scratch.arena, query, string); + if(string_matches.count == string_matches.needle_part_count || + kind_string_matches.count == kind_string_matches.needle_part_count) + { + DF_SettingsItemNode *n = push_array(scratch.arena, DF_SettingsItemNode, 1); + SLLQueuePush(items_list.first, items_list.last, n); + items_list.count += 1; + n->v.kind = DF_SettingsItemKind_Setting; + n->v.kind_string = kind_string; + n->v.string = string; + n->v.kind_string_matches = kind_string_matches; + n->v.string_matches = string_matches; + n->v.icon_kind = DF_IconKind_Window; + n->v.code = code; + } + } + + //- rjf: gather all theme colors + for(EachNonZeroEnumVal(DF_ThemeColor, color)) + { + String8 kind_string = str8_lit("Theme Color"); + String8 string = df_g_theme_color_display_string_table[color]; + FuzzyMatchRangeList kind_string_matches = fuzzy_match_find(scratch.arena, query, kind_string); + FuzzyMatchRangeList string_matches = fuzzy_match_find(scratch.arena, query, string); + if(string_matches.count == string_matches.needle_part_count || + kind_string_matches.count == kind_string_matches.needle_part_count) + { + DF_SettingsItemNode *n = push_array(scratch.arena, DF_SettingsItemNode, 1); + SLLQueuePush(items_list.first, items_list.last, n); + items_list.count += 1; + n->v.kind = DF_SettingsItemKind_ThemeColor; + n->v.kind_string = kind_string; + n->v.string = string; + n->v.kind_string_matches = kind_string_matches; + n->v.string_matches = string_matches; + n->v.icon_kind = DF_IconKind_Palette; + n->v.color = color; + } + } + + //- rjf: convert to array + items.count = items_list.count; + items.v = push_array(scratch.arena, DF_SettingsItem, items.count); + { + U64 idx = 0; + for(DF_SettingsItemNode *n = items_list.first; n != 0; n = n->next, idx += 1) + { + items.v[idx] = n->v; + } + } + } + + ////////////////////////////// + //- rjf: sort filtered settings item list + // + if(query.size != 0) + { + quick_sort(items.v, items.count, sizeof(items.v[0]), df_qsort_compare_settings_item); + } + + ////////////////////////////// + //- rjf: produce per-color context menu keys + // + UI_Key *color_ctx_menu_keys = push_array(scratch.arena, UI_Key, DF_ThemeColor_COUNT); + { + for(DF_ThemeColor color = (DF_ThemeColor)(DF_ThemeColor_Null+1); + color < DF_ThemeColor_COUNT; + color = (DF_ThemeColor)(color+1)) + { + color_ctx_menu_keys[color] = ui_key_from_stringf(ui_key_zero(), "###settings_color_ctx_menu_%I64x", (U64)color); + } + } + + ////////////////////////////// + //- rjf: build color context menus + // + for(DF_ThemeColor color = (DF_ThemeColor)(DF_ThemeColor_Null+1); + color < DF_ThemeColor_COUNT; + color = (DF_ThemeColor)(color+1)) + { + DF_Palette(DF_PaletteCode_Floating) + UI_CtxMenu(color_ctx_menu_keys[color]) + UI_Padding(ui_em(1.5f, 1.f)) + UI_PrefWidth(ui_em(28.5f, 1)) UI_PrefHeight(ui_children_sum(1.f)) + { + // rjf: build title + UI_Row + { + ui_spacer(ui_em(1.5f, 1.f)); + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_label(df_g_theme_color_display_string_table[color]); + } + + ui_spacer(ui_em(1.5f, 1.f)); + + // rjf: build picker + { + ui_set_next_pref_height(ui_em(22.f, 1.f)); + UI_Row UI_Padding(ui_pct(1, 0)) + { + UI_PrefWidth(ui_em(22.f, 1.f)) UI_PrefHeight(ui_em(22.f, 1.f)) UI_Flags(UI_BoxFlag_FocusNavSkip) + { + ui_sat_val_pickerf(sv->color_ctx_menu_color_hsva.x, &sv->color_ctx_menu_color_hsva.y, &sv->color_ctx_menu_color_hsva.z, "###settings_satval_picker"); + } + + ui_spacer(ui_em(0.75f, 1.f)); + + UI_PrefWidth(ui_em(1.5f, 1.f)) UI_PrefHeight(ui_em(22.f, 1.f)) UI_Flags(UI_BoxFlag_FocusNavSkip) + ui_hue_pickerf(&sv->color_ctx_menu_color_hsva.x, sv->color_ctx_menu_color_hsva.y, sv->color_ctx_menu_color_hsva.z, "###settings_hue_picker"); + + UI_PrefWidth(ui_em(1.5f, 1.f)) UI_PrefHeight(ui_em(22.f, 1.f)) UI_Flags(UI_BoxFlag_FocusNavSkip) + ui_alpha_pickerf(&sv->color_ctx_menu_color_hsva.w, "###settings_alpha_picker"); + } + } + + ui_spacer(ui_em(1.5f, 1.f)); + + // rjf: build line edits + UI_Row + UI_WidthFill + UI_Padding(ui_em(1.5f, 1.f)) + UI_PrefHeight(ui_children_sum(1.f)) + UI_Column + UI_PrefHeight(ui_em(2.25f, 1.f)) + { + Vec4F32 hsva = sv->color_ctx_menu_color_hsva; + Vec3F32 hsv = v3f32(hsva.x, hsva.y, hsva.z); + Vec3F32 rgb = rgb_from_hsv(hsv); + Vec4F32 rgba = v4f32(rgb.x, rgb.y, rgb.z, sv->color_ctx_menu_color_hsva.w); + String8 hex_string = hex_string_from_rgba_4f32(scratch.arena, rgba); + hex_string = push_str8f(scratch.arena, "#%S", hex_string); + String8 r_string = push_str8f(scratch.arena, "%.2f", rgba.x); + String8 g_string = push_str8f(scratch.arena, "%.2f", rgba.y); + String8 b_string = push_str8f(scratch.arena, "%.2f", rgba.z); + String8 h_string = push_str8f(scratch.arena, "%.2f", hsva.x); + String8 s_string = push_str8f(scratch.arena, "%.2f", hsva.y); + String8 v_string = push_str8f(scratch.arena, "%.2f", hsva.z); + String8 a_string = push_str8f(scratch.arena, "%.2f", rgba.w); + UI_Row UI_Font(df_font_from_slot(DF_FontSlot_Code)) + { + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_em(4.5f, 1.f)) ui_labelf("Hex"); + UI_Signal sig = df_line_editf(DF_LineEditFlag_Border, 0, 0, &sv->txt_cursor, &sv->txt_mark, sv->txt_buffer, sizeof(sv->txt_buffer), &sv->txt_size, 0, hex_string, "###hex_edit"); + if(ui_committed(sig)) + { + String8 string = str8(sv->txt_buffer, sv->txt_size); + Vec4F32 new_rgba = rgba_from_hex_string_4f32(string); + Vec4F32 new_hsva = hsva_from_rgba(new_rgba); + sv->color_ctx_menu_color_hsva = new_hsva; + } + } + ui_spacer(ui_em(0.75f, 1.f)); + UI_Row + { + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_em(4.5f, 1.f)) ui_labelf("R"); + UI_Signal sig = df_line_editf(DF_LineEditFlag_Border, 0, 0, &sv->txt_cursor, &sv->txt_mark, sv->txt_buffer, sizeof(sv->txt_buffer), &sv->txt_size, 0, r_string, "###r_edit"); + if(ui_committed(sig)) + { + String8 string = str8(sv->txt_buffer, sv->txt_size); + Vec4F32 new_rgba = v4f32((F32)f64_from_str8(string), rgba.y, rgba.z, rgba.w); + Vec4F32 new_hsva = hsva_from_rgba(new_rgba); + sv->color_ctx_menu_color_hsva = new_hsva; + } + } + UI_Row + { + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_em(4.5f, 1.f)) ui_labelf("G"); + UI_Signal sig = df_line_editf(DF_LineEditFlag_Border, 0, 0, &sv->txt_cursor, &sv->txt_mark, sv->txt_buffer, sizeof(sv->txt_buffer), &sv->txt_size, 0, g_string, "###g_edit"); + if(ui_committed(sig)) + { + String8 string = str8(sv->txt_buffer, sv->txt_size); + Vec4F32 new_rgba = v4f32(rgba.x, (F32)f64_from_str8(string), rgba.z, rgba.w); + Vec4F32 new_hsva = hsva_from_rgba(new_rgba); + sv->color_ctx_menu_color_hsva = new_hsva; + } + } + UI_Row + { + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_em(4.5f, 1.f)) ui_labelf("B"); + UI_Signal sig = df_line_editf(DF_LineEditFlag_Border, 0, 0, &sv->txt_cursor, &sv->txt_mark, sv->txt_buffer, sizeof(sv->txt_buffer), &sv->txt_size, 0, b_string, "###b_edit"); + if(ui_committed(sig)) + { + String8 string = str8(sv->txt_buffer, sv->txt_size); + Vec4F32 new_rgba = v4f32(rgba.x, rgba.y, (F32)f64_from_str8(string), rgba.w); + Vec4F32 new_hsva = hsva_from_rgba(new_rgba); + sv->color_ctx_menu_color_hsva = new_hsva; + } + } + ui_spacer(ui_em(0.75f, 1.f)); + UI_Row + { + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_em(4.5f, 1.f)) ui_labelf("H"); + UI_Signal sig = df_line_editf(DF_LineEditFlag_Border, 0, 0, &sv->txt_cursor, &sv->txt_mark, sv->txt_buffer, sizeof(sv->txt_buffer), &sv->txt_size, 0, h_string, "###h_edit"); + if(ui_committed(sig)) + { + String8 string = str8(sv->txt_buffer, sv->txt_size); + Vec4F32 new_hsva = v4f32((F32)f64_from_str8(string), hsva.y, hsva.z, hsva.w); + sv->color_ctx_menu_color_hsva = new_hsva; + } + } + UI_Row + { + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_em(4.5f, 1.f)) ui_labelf("S"); + UI_Signal sig = df_line_editf(DF_LineEditFlag_Border, 0, 0, &sv->txt_cursor, &sv->txt_mark, sv->txt_buffer, sizeof(sv->txt_buffer), &sv->txt_size, 0, s_string, "###s_edit"); + if(ui_committed(sig)) + { + String8 string = str8(sv->txt_buffer, sv->txt_size); + Vec4F32 new_hsva = v4f32(hsva.x, (F32)f64_from_str8(string), hsva.z, hsva.w); + sv->color_ctx_menu_color_hsva = new_hsva; + } + } + UI_Row + { + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_em(4.5f, 1.f)) ui_labelf("V"); + UI_Signal sig = df_line_editf(DF_LineEditFlag_Border, 0, 0, &sv->txt_cursor, &sv->txt_mark, sv->txt_buffer, sizeof(sv->txt_buffer), &sv->txt_size, 0, v_string, "###v_edit"); + if(ui_committed(sig)) + { + String8 string = str8(sv->txt_buffer, sv->txt_size); + Vec4F32 new_hsva = v4f32(hsva.x, hsva.y, (F32)f64_from_str8(string), hsva.w); + sv->color_ctx_menu_color_hsva = new_hsva; + } + } + ui_spacer(ui_em(0.75f, 1.f)); + UI_Row + { + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_em(4.5f, 1.f)) ui_labelf("A"); + UI_Signal sig = df_line_editf(DF_LineEditFlag_Border, 0, 0, &sv->txt_cursor, &sv->txt_mark, sv->txt_buffer, sizeof(sv->txt_buffer), &sv->txt_size, 0, a_string, "###a_edit"); + if(ui_committed(sig)) + { + String8 string = str8(sv->txt_buffer, sv->txt_size); + Vec4F32 new_hsva = v4f32(hsva.x, hsva.y, hsva.z, (F32)f64_from_str8(string)); + sv->color_ctx_menu_color_hsva = new_hsva; + } + } + } + + // rjf: commit state to theme + Vec4F32 hsva = sv->color_ctx_menu_color_hsva; + Vec3F32 hsv = v3f32(hsva.x, hsva.y, hsva.z); + Vec3F32 rgb = rgb_from_hsv(hsv); + Vec4F32 rgba = v4f32(rgb.x, rgb.y, rgb.z, sv->color_ctx_menu_color_hsva.w); + df_gfx_state->cfg_theme_target.colors[sv->color_ctx_menu_color] = rgba; + } + } + + ////////////////////////////// + //- rjf: build items list + // + Rng1S64 visible_row_range = {0}; + UI_ScrollListParams scroll_list_params = {0}; + { + Vec2F32 rect_dim = dim_2f32(rect); + scroll_list_params.flags = UI_ScrollListFlag_All; + scroll_list_params.row_height_px = row_height_px; + scroll_list_params.dim_px = v2f32(rect_dim.x, rect_dim.y); + scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, items.count)); + scroll_list_params.item_range = r1s64(0, items.count); + scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; + } + UI_ScrollListSignal scroll_list_sig = {0}; + UI_Focus(UI_FocusKind_On) + UI_ScrollList(&scroll_list_params, &view->scroll_pos.y, &sv->cursor, 0, &visible_row_range, &scroll_list_sig) + UI_Focus(UI_FocusKind_Null) + { + for(S64 row_num = visible_row_range.min; row_num <= visible_row_range.max && row_num < items.count; row_num += 1) + { + //- rjf: unpack item + DF_SettingsItem *item = &items.v[row_num]; + Vec4F32 rgba = ui_top_palette()->text_weak; + OS_Cursor cursor = OS_Cursor_HandPoint; + Rng1S32 s32_range = {0}; + B32 is_toggler = 0; + B32 is_toggled = 0; + B32 is_slider = 0; + S32 slider_s32_val = 0; + F32 slider_pct = 0.f; + switch(item->kind) + { + case DF_SettingsItemKind_ThemeColor: + { + rgba = df_rgba_from_theme_color(item->color); + }break; + case DF_SettingsItemKind_Setting: + { + s32_range = df_g_setting_code_s32_range_table[item->code]; + if(s32_range.min != 0 || s32_range.max != 1) + { + cursor = OS_Cursor_LeftRight; + is_slider = 1; + slider_s32_val = df_setting_val_from_code(item->code).s32; + slider_pct = (F32)(slider_s32_val - s32_range.min) / dim_1s32(s32_range); + } + else + { + is_toggler = 1; + is_toggled = !!df_setting_val_from_code(item->code).s32; + } + }break; + } + + //- rjf: build item widget + UI_Box *item_box = &ui_g_nil_box; + UI_Focus(row_num+1 == sv->cursor.y ? UI_FocusKind_On : UI_FocusKind_Off) + { + ui_set_next_hover_cursor(cursor); + item_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| + UI_BoxFlag_DrawBackground| + UI_BoxFlag_DrawBorder| + UI_BoxFlag_DrawHotEffects| + UI_BoxFlag_DrawActiveEffects, + "###option_%S", item->string); + UI_Parent(item_box) + { + ui_spacer(ui_em(1.f, 1.f)); + UI_PrefWidth(ui_em(2.5f, 1.f)) + UI_Font(df_font_from_slot(DF_FontSlot_Icons)) + UI_RunFlags(F_RunFlag_Smooth) + UI_Palette(ui_build_palette(ui_top_palette(), .text = rgba)) + ui_label(df_g_icon_kind_text_table[item->icon_kind]); + UI_PrefWidth(ui_text_dim(10, 1)) + { + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_DrawTextWeak, "%S", item->kind_string); + ui_box_equip_fuzzy_match_ranges(box, &item->kind_string_matches); + } + UI_PrefWidth(ui_text_dim(10, 1)) + { + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "%S", item->string); + ui_box_equip_fuzzy_match_ranges(box, &item->string_matches); + } + if(is_slider) UI_PrefWidth(ui_text_dim(10, 1)) + { + UI_Font(df_font_from_slot(DF_FontSlot_Code)) + UI_RunFlags(F_RunFlag_Smooth) + UI_Flags(UI_BoxFlag_DrawTextWeak) + ui_labelf("(%i)", slider_s32_val); + UI_PrefWidth(ui_pct(slider_pct, 1.f)) UI_HeightFill UI_FixedX(0) UI_FixedY(0) + UI_Palette(ui_build_palette(ui_top_palette(), .background = df_rgba_from_theme_color(DF_ThemeColor_HighlightOverlay))) + ui_build_box_from_key(UI_BoxFlag_DrawBackground, ui_key_zero()); + } + if(is_toggler) + { + ui_spacer(ui_pct(1, 0)); + UI_PrefWidth(ui_em(2.5f, 1.f)) + UI_Font(df_font_from_slot(DF_FontSlot_Icons)) + UI_RunFlags(F_RunFlag_Smooth) + UI_Flags(UI_BoxFlag_DrawTextWeak) + ui_label(df_g_icon_kind_text_table[is_toggled ? DF_IconKind_CheckFilled : DF_IconKind_CheckHollow]); + } + } + } + + //- rjf: interact + UI_Signal sig = ui_signal_from_box(item_box); + if(item->kind == DF_SettingsItemKind_ThemeColor && ui_clicked(sig)) + { + Vec3F32 rgb = v3f32(rgba.x, rgba.y, rgba.z); + Vec3F32 hsv = hsv_from_rgb(rgb); + Vec4F32 hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w); + ui_ctx_menu_open(color_ctx_menu_keys[item->color], item_box->key, v2f32(0, dim_2f32(item_box->rect).y)); + sv->color_ctx_menu_color = item->color; + sv->color_ctx_menu_color_hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w); + DF_CmdParams p = df_cmd_params_from_panel(ws, panel); + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); + } + if(item->kind == DF_SettingsItemKind_Setting && is_toggler && ui_clicked(sig)) + { + df_gfx_state->cfg_setting_vals[DF_CfgSrc_User][item->code].s32 ^= 1; + df_gfx_state->cfg_setting_vals[DF_CfgSrc_User][item->code].set = 1; + } + if(item->kind == DF_SettingsItemKind_Setting && is_slider && ui_dragging(sig)) + { + if(ui_pressed(sig)) + { + ui_store_drag_struct(&slider_s32_val); + } + S32 pre_drag_val = *ui_get_drag_struct(S32); + Vec2F32 delta = ui_drag_delta(); + S32 pst_drag_val = pre_drag_val + (S32)(delta.x/(ui_top_font_size()*2.f)); + pst_drag_val = clamp_1s32(s32_range, pst_drag_val); + df_gfx_state->cfg_setting_vals[DF_CfgSrc_User][item->code].s32 = pst_drag_val; + df_gfx_state->cfg_setting_vals[DF_CfgSrc_User][item->code].set = 1; + } + } + } + + scratch_end(scratch); + ProfEnd(); + + //~ TODO(rjf): OLD vvvvvvvvvvvvvvvvvvvvvvvvvv +#if 0 + ProfBeginFunction(); + Temp scratch = scratch_begin(0, 0); + F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); //- rjf: get state typedef struct DF_ThemeViewState DF_ThemeViewState; @@ -8775,4 +9220,5 @@ DF_VIEW_UI_FUNCTION_DEF(Theme) scratch_end(scratch); ProfEnd(); +#endif } diff --git a/src/df/gfx/df_views.h b/src/df/gfx/df_views.h index 69f13aae..38db46d6 100644 --- a/src/df/gfx/df_views.h +++ b/src/df/gfx/df_views.h @@ -434,6 +434,51 @@ struct DF_MemoryViewState B32 contain_cursor; }; +//////////////////////////////// +//~ rjf: Settings @view_types + +typedef enum DF_SettingsItemKind +{ + DF_SettingsItemKind_Setting, + DF_SettingsItemKind_ThemeColor, +} +DF_SettingsItemKind; + +typedef struct DF_SettingsItem DF_SettingsItem; +struct DF_SettingsItem +{ + DF_SettingsItemKind kind; + String8 kind_string; + String8 string; + FuzzyMatchRangeList kind_string_matches; + FuzzyMatchRangeList string_matches; + DF_IconKind icon_kind; + DF_SettingCode code; + DF_ThemeColor color; +}; + +typedef struct DF_SettingsItemNode DF_SettingsItemNode; +struct DF_SettingsItemNode +{ + DF_SettingsItemNode *next; + DF_SettingsItem v; +}; + +typedef struct DF_SettingsItemList DF_SettingsItemList; +struct DF_SettingsItemList +{ + DF_SettingsItemNode *first; + DF_SettingsItemNode *last; + U64 count; +}; + +typedef struct DF_SettingsItemArray DF_SettingsItemArray; +struct DF_SettingsItemArray +{ + DF_SettingsItem *v; + U64 count; +}; + //////////////////////////////// //~ rjf: Quick Sort Comparisons @@ -445,6 +490,7 @@ internal int df_qsort_compare_file_info__size(DF_FileInfo *a, DF_FileInfo *b); internal int df_qsort_compare_process_info(DF_ProcessInfo *a, DF_ProcessInfo *b); internal int df_qsort_compare_cmd_lister__strength(DF_CmdListerItem *a, DF_CmdListerItem *b); internal int df_qsort_compare_entity_lister__strength(DF_EntityListerItem *a, DF_EntityListerItem *b); +internal int df_qsort_compare_settings_item(DF_SettingsItem *a, DF_SettingsItem *b); //////////////////////////////// //~ rjf: Command Lister diff --git a/src/df/gfx/generated/df_gfx.meta.c b/src/df/gfx/generated/df_gfx.meta.c index de598c95..306ec7bc 100644 --- a/src/df/gfx/generated/df_gfx.meta.c +++ b/src/df/gfx/generated/df_gfx.meta.c @@ -163,7 +163,7 @@ DF_ViewSpecInfo df_g_gfx_view_kind_spec_info_table[31] = {(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_ProjectSpecific|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("breakpoints"), str8_lit_comp("Breakpoints"), DF_NameKind_Null, DF_IconKind_CircleFilled, DF_VIEW_SETUP_FUNCTION_NAME(Breakpoints), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Breakpoints), DF_VIEW_CMD_FUNCTION_NAME(Breakpoints), DF_VIEW_UI_FUNCTION_NAME(Breakpoints)}, {(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_ProjectSpecific|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|1*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("watch_pins"), str8_lit_comp("Watch Pins"), DF_NameKind_Null, DF_IconKind_Pin, DF_VIEW_SETUP_FUNCTION_NAME(WatchPins), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(WatchPins), DF_VIEW_CMD_FUNCTION_NAME(WatchPins), DF_VIEW_UI_FUNCTION_NAME(WatchPins)}, {(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_ProjectSpecific|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("exception_filters"), str8_lit_comp("Exception Filters"), DF_NameKind_Null, DF_IconKind_Gear, DF_VIEW_SETUP_FUNCTION_NAME(ExceptionFilters), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(ExceptionFilters), DF_VIEW_CMD_FUNCTION_NAME(ExceptionFilters), DF_VIEW_UI_FUNCTION_NAME(ExceptionFilters)}, -{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_ProjectSpecific|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|0*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|0*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("theme"), str8_lit_comp("Theme"), DF_NameKind_Null, DF_IconKind_Palette, DF_VIEW_SETUP_FUNCTION_NAME(Theme), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Theme), DF_VIEW_CMD_FUNCTION_NAME(Theme), DF_VIEW_UI_FUNCTION_NAME(Theme)}, +{(0|0*DF_ViewSpecFlag_ParameterizedByEntity|0*DF_ViewSpecFlag_ProjectSpecific|1*DF_ViewSpecFlag_CanSerialize|0*DF_ViewSpecFlag_CanSerializeEntityPath|1*DF_ViewSpecFlag_CanFilter|0*DF_ViewSpecFlag_FilterIsCode|1*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("settings"), str8_lit_comp("Settings"), DF_NameKind_Null, DF_IconKind_Gear, DF_VIEW_SETUP_FUNCTION_NAME(Settings), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(Settings), DF_VIEW_CMD_FUNCTION_NAME(Settings), DF_VIEW_UI_FUNCTION_NAME(Settings)}, }; DF_CmdParamSlot df_g_cmd_param_slot_2_view_spec_src_map[7] = @@ -1266,7 +1266,7 @@ Rng1S32 df_g_setting_code_s32_range_table[13] = {0, 1}, {0, 1}, {0, 1}, -{0, 32}, +{1, 32}, }; C_LINKAGE_END diff --git a/src/df/gfx/generated/df_gfx.meta.h b/src/df/gfx/generated/df_gfx.meta.h index e9b4dd89..592a8b9d 100644 --- a/src/df/gfx/generated/df_gfx.meta.h +++ b/src/df/gfx/generated/df_gfx.meta.h @@ -38,7 +38,7 @@ DF_GfxViewKind_Memory, DF_GfxViewKind_Breakpoints, DF_GfxViewKind_WatchPins, DF_GfxViewKind_ExceptionFilters, -DF_GfxViewKind_Theme, +DF_GfxViewKind_Settings, DF_GfxViewKind_COUNT, } DF_GfxViewKind; @@ -184,7 +184,7 @@ DF_VIEW_SETUP_FUNCTION_DEF(Memory); DF_VIEW_SETUP_FUNCTION_DEF(Breakpoints); DF_VIEW_SETUP_FUNCTION_DEF(WatchPins); DF_VIEW_SETUP_FUNCTION_DEF(ExceptionFilters); -DF_VIEW_SETUP_FUNCTION_DEF(Theme); +DF_VIEW_SETUP_FUNCTION_DEF(Settings); DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Null); DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Empty); DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(GettingStarted); @@ -215,7 +215,7 @@ DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Memory); DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Breakpoints); DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(WatchPins); DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(ExceptionFilters); -DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Theme); +DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Settings); DF_VIEW_CMD_FUNCTION_DEF(Null); DF_VIEW_CMD_FUNCTION_DEF(Empty); DF_VIEW_CMD_FUNCTION_DEF(GettingStarted); @@ -246,7 +246,7 @@ DF_VIEW_CMD_FUNCTION_DEF(Memory); DF_VIEW_CMD_FUNCTION_DEF(Breakpoints); DF_VIEW_CMD_FUNCTION_DEF(WatchPins); DF_VIEW_CMD_FUNCTION_DEF(ExceptionFilters); -DF_VIEW_CMD_FUNCTION_DEF(Theme); +DF_VIEW_CMD_FUNCTION_DEF(Settings); DF_VIEW_UI_FUNCTION_DEF(Null); DF_VIEW_UI_FUNCTION_DEF(Empty); DF_VIEW_UI_FUNCTION_DEF(GettingStarted); @@ -277,7 +277,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory); DF_VIEW_UI_FUNCTION_DEF(Breakpoints); DF_VIEW_UI_FUNCTION_DEF(WatchPins); DF_VIEW_UI_FUNCTION_DEF(ExceptionFilters); -DF_VIEW_UI_FUNCTION_DEF(Theme); +DF_VIEW_UI_FUNCTION_DEF(Settings); DF_GFX_VIEW_RULE_VIZ_ROW_PROD_FUNCTION_DEF(list); DF_GFX_VIEW_RULE_VIZ_ROW_PROD_FUNCTION_DEF(only);