From d9d102cb565fd103b00eb42e60f7e9203170934e Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 22 Apr 2025 13:53:52 -0700 Subject: [PATCH] expand cell capabilities to have meta data (expr name/description/etc.), as well as value editor, as well as fancy value editing widgets, all in one cell --- src/draw/draw.c | 35 ++- src/raddbg/generated/raddbg.meta.c | 8 +- src/raddbg/generated/raddbg.meta.h | 4 +- src/raddbg/raddbg.mdesk | 2 - src/raddbg/raddbg_core.c | 51 ++++- src/raddbg/raddbg_core.h | 6 +- src/raddbg/raddbg_eval.c | 6 + src/raddbg/raddbg_views.c | 45 ++-- src/raddbg/raddbg_widgets.c | 353 ++++++++++++++++------------- src/raddbg/raddbg_widgets.h | 4 +- src/ui/ui_core.h | 3 + 11 files changed, 313 insertions(+), 204 deletions(-) diff --git a/src/draw/draw.c b/src/draw/draw.c index d77f41af..39c12fa4 100644 --- a/src/draw/draw.c +++ b/src/draw/draw.c @@ -119,16 +119,19 @@ internal String8 dr_string_from_fstrs(Arena *arena, DR_FStrList *list) { String8 result = {0}; - result.size = list->total_size; - result.str = push_array_no_zero(arena, U8, result.size); - U64 idx = 0; - for(DR_FStrNode *n = list->first; n != 0; n = n->next) { - if(!fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font)) + Temp scratch = scratch_begin(&arena, 1); + String8List parts = {0}; + for(DR_FStrNode *n = list->first; n != 0; n = n->next) { - MemoryCopy(result.str+idx, n->v.string.str, n->v.string.size); - idx += n->v.string.size; + if(!fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font)) + { + str8_list_push(scratch.arena, &parts, n->v.string); + } } + result = str8_list_join(arena, &parts, 0); + result = str8_skip_chop_whitespace(result); + scratch_end(scratch); } return result; } @@ -137,7 +140,23 @@ internal FuzzyMatchRangeList dr_fuzzy_match_find_from_fstrs(Arena *arena, DR_FStrList *fstrs, String8 needle) { Temp scratch = scratch_begin(&arena, 1); - String8 fstrs_string = dr_string_from_fstrs(scratch.arena, fstrs); + String8 fstrs_string = {0}; + fstrs_string.size = fstrs->total_size; + fstrs_string.str = push_array(arena, U8, fstrs_string.size); + { + // TODO(rjf): the fact that we only increment on non-icon portions is super weird? + // we are only doing that because of the rendering of the fuzzy matches, so maybe + // once that is straightened out, we can fix the code here too... + U64 off = 0; + for(DR_FStrNode *n = fstrs->first; n != 0; n = n->next) + { + if(!fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font)) + { + MemoryCopy(fstrs_string.str + off, n->v.string.str, n->v.string.size); + off += n->v.string.size; + } + } + } FuzzyMatchRangeList ranges = fuzzy_match_find(arena, needle, fstrs_string); scratch_end(scratch); return ranges; diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index a6e368d0..2f074e43 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -4,7 +4,7 @@ //- GENERATED CODE C_LINKAGE_BEGIN -RD_VocabInfo rd_vocab_info_table[315] = +RD_VocabInfo rd_vocab_info_table[313] = { {str8_lit_comp("auto_view_rule"), str8_lit_comp("auto_view_rules"), str8_lit_comp("Auto View Rule"), str8_lit_comp("Auto View Rules"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, @@ -253,8 +253,6 @@ RD_VocabInfo rd_vocab_info_table[315] = {str8_lit_comp("goto_address"), str8_lit_comp(""), str8_lit_comp("Go To Address"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("center_cursor"), str8_lit_comp(""), str8_lit_comp("Center Cursor"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("contain_cursor"), str8_lit_comp(""), str8_lit_comp("Contain Cursor"), str8_lit_comp(""), RD_IconKind_Null}, -{str8_lit_comp("find_text_forward"), str8_lit_comp(""), str8_lit_comp("Find Text (Forward)"), str8_lit_comp(""), RD_IconKind_Find}, -{str8_lit_comp("find_text_backward"), str8_lit_comp(""), str8_lit_comp("Find Text (Backwards)"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("find_next"), str8_lit_comp(""), str8_lit_comp("Find Next"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("find_prev"), str8_lit_comp(""), str8_lit_comp("Find Previous"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("find_thread"), str8_lit_comp(""), str8_lit_comp("Find Thread"), str8_lit_comp(""), RD_IconKind_Find}, @@ -394,7 +392,7 @@ Rng1U64 rd_reg_slot_range_table[42] = {OffsetOf(RD_Regs, os_event), OffsetOf(RD_Regs, os_event) + sizeof(OS_Event *)}, }; -RD_CmdKindInfo rd_cmd_kind_info_table[211] = +RD_CmdKindInfo rd_cmd_kind_info_table[209] = { {0}, { str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), CTRL_EntityKind_Null}}, @@ -539,8 +537,6 @@ RD_CmdKindInfo rd_cmd_kind_info_table[211] = { str8_lit_comp("goto_address"), str8_lit_comp("Jumps to an address in the current memory or disassembly view."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_Vaddr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("center_cursor"), str8_lit_comp("Snaps the current code view to center the cursor."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("contain_cursor"), str8_lit_comp("Snaps the current code view to contain the cursor."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, -{ str8_lit_comp("find_text_forward"), str8_lit_comp("Searches the current code file forward (from the cursor) for a string."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*1)|(RD_QueryFlag_SelectOldInput*1)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, -{ str8_lit_comp("find_text_backward"), str8_lit_comp("Searches the current code file backwards (from the cursor) for a string."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*1)|(RD_QueryFlag_SelectOldInput*1)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("find_next"), str8_lit_comp("Searches the current code file forward (from the cursor) for the last searched string."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*1)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("find_prev"), str8_lit_comp("Searches the current code file backwards (from the cursor) for the last searched string."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*1)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("find_thread"), str8_lit_comp("Jumps to the passed thread in either source code, disassembly, or both if they're already open."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Thread, str8_lit_comp("query:threads"), str8_lit_comp(""), CTRL_EntityKind_Thread}}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index c0be4d39..25631e29 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -198,8 +198,6 @@ RD_CmdKind_GoToLine, RD_CmdKind_GoToAddress, RD_CmdKind_CenterCursor, RD_CmdKind_ContainCursor, -RD_CmdKind_FindTextForward, -RD_CmdKind_FindTextBackward, RD_CmdKind_FindNext, RD_CmdKind_FindPrev, RD_CmdKind_FindThread, @@ -640,7 +638,7 @@ RD_Query query; .os_event = rd_regs()->os_event,\ C_LINKAGE_BEGIN -extern RD_VocabInfo rd_vocab_info_table[315]; +extern RD_VocabInfo rd_vocab_info_table[313]; extern RD_NameSchemaInfo rd_name_schema_info_table[21]; extern Rng1U64 rd_reg_slot_range_table[42]; extern String8 rd_binding_version_remap_old_name_table[8]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index eadc49c2..d617ff7a 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -682,8 +682,6 @@ RD_CmdTable: // | | | | {GoToAddress 1 1 "" Vaddr null Nil Null 0 0 0 0 1 0 1 Null "goto_address" "Go To Address" "Jumps to an address in the current memory or disassembly view." "" "" } {CenterCursor 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Null "center_cursor" "Center Cursor" "Snaps the current code view to center the cursor." "" "" } {ContainCursor 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 Null "contain_cursor" "Contain Cursor" "Snaps the current code view to contain the cursor." "" "" } - {FindTextForward 1 1 "" String null Nil Null 0 0 1 1 1 0 1 Find "find_text_forward" "Find Text (Forward)" "Searches the current code file forward (from the cursor) for a string." "" "" } - {FindTextBackward 1 1 "" String null Nil Null 0 0 1 1 1 0 1 Find "find_text_backward" "Find Text (Backwards)" "Searches the current code file backwards (from the cursor) for a string." "" "" } {FindNext 1 1 "" Null null Nil Null 0 0 1 0 0 0 0 Find "find_next" "Find Next" "Searches the current code file forward (from the cursor) for the last searched string." "" "" } {FindPrev 1 1 "" Null null Nil Null 0 0 1 0 0 0 0 Find "find_prev" "Find Previous" "Searches the current code file backwards (from the cursor) for the last searched string." "" "" } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index c5fefee4..ce3deb35 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -1226,6 +1226,42 @@ rd_setting_from_name(String8 name) return result; } +internal B32 +rd_setting_b32_from_name(String8 name) +{ + Temp scratch = scratch_begin(0, 0); + String8 value = rd_setting_from_name(name); + String8 expr = push_str8f(scratch.arena, "(bool)(%S)", value); + E_Eval eval = e_eval_from_string(scratch.arena, expr); + B32 result = !!e_value_eval_from_eval(eval).value.u64; + scratch_end(scratch); + return result; +} + +internal U64 +rd_setting_u64_from_name(String8 name) +{ + Temp scratch = scratch_begin(0, 0); + String8 value = rd_setting_from_name(name); + String8 expr = push_str8f(scratch.arena, "(uint64)(%S)", value); + E_Eval eval = e_eval_from_string(scratch.arena, expr); + U64 result = e_value_eval_from_eval(eval).value.u64; + scratch_end(scratch); + return result; +} + +internal F32 +rd_setting_f32_from_name(String8 name) +{ + Temp scratch = scratch_begin(0, 0); + String8 value = rd_setting_from_name(name); + String8 expr = push_str8f(scratch.arena, "(float32)(%S)", value); + E_Eval eval = e_eval_from_string(scratch.arena, expr); + F32 result = e_value_eval_from_eval(eval).value.f32; + scratch_end(scratch); + return result; +} + internal RD_Cfg * rd_immediate_cfg_from_key(String8 string) { @@ -3114,11 +3150,11 @@ rd_view_ui(Rng2F32 rect) String8 string = cell->edit_string; if(string.size == 0) { - string = dr_string_from_fstrs(scratch.arena, &cell_info.expr_fstrs); + string = dr_string_from_fstrs(scratch.arena, &cell_info.eval_fstrs); } if(string.size == 0) { - string = dr_string_from_fstrs(scratch.arena, &cell_info.eval_fstrs); + string = dr_string_from_fstrs(scratch.arena, &cell_info.expr_fstrs); } string.size = Min(string.size, sizeof(ewv->dummy_text_edit_state.input_buffer)); RD_WatchPt pt = {row->block->key, row->key, rd_id_from_watch_cell(cell)}; @@ -4118,6 +4154,8 @@ rd_view_ui(Rng2F32 rect) F32 cell_x_px = 0; for(RD_WatchCell *cell = row_info->cells.first; cell != 0; cell = cell->next, cell_x += 1) { + if(row_depth > 0) { ui_push_tagf("weak"); } + //////////// //- rjf: unpack cell info // @@ -4350,12 +4388,9 @@ rd_view_ui(Rng2F32 rect) cell_params.edit_buffer_size = sizeof(cell_edit_state->input_buffer); cell_params.edit_string_size_out = &cell_edit_state->input_size; cell_params.expanded_out = &next_row_expanded; - cell_params.pre_edit_value = dr_string_from_fstrs(scratch.arena, &cell_info.expr_fstrs); - cell_params.expr_fstrs = cell_info.expr_fstrs; - cell_params.eval_fstrs = cell_info.eval_fstrs; cell_params.search_needle = rd_view_query_input(); - - // rjf: apply description + cell_params.meta_fstrs = cell_info.expr_fstrs; + cell_params.value_fstrs = cell_info.eval_fstrs; if(row_height_px > ui_top_font_size()*3.5f) { cell_params.description = cell_info.description; @@ -4683,6 +4718,8 @@ rd_view_ui(Rng2F32 rect) //- rjf: bump x pixel coordinate // cell_x_px = next_cell_x_px; + + if(row_depth > 0) { ui_pop_tag(); } } } diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 64a35c7c..168f9ab3 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -872,9 +872,9 @@ internal D_Target rd_target_from_cfg(Arena *arena, RD_Cfg *cfg); internal MD_NodePtrList rd_schemas_from_name(String8 name); internal String8 rd_setting_from_name(String8 name); -#define rd_setting_b32_from_name(name) (str8_match(rd_setting_from_name(name), str8_lit("1"), 0)) -#define rd_setting_u64_from_name(name) (u64_from_str8(rd_setting_from_name(name), 10)) -#define rd_setting_f32_from_name(name) ((F32)f64_from_str8(rd_setting_from_name(name))) +internal B32 rd_setting_b32_from_name(String8 name); +internal U64 rd_setting_u64_from_name(String8 name); +internal F32 rd_setting_f32_from_name(String8 name); internal RD_Cfg *rd_immediate_cfg_from_key(String8 string); internal RD_Cfg *rd_immediate_cfg_from_keyf(char *fmt, ...); diff --git a/src/raddbg/raddbg_eval.c b/src/raddbg/raddbg_eval.c index 79067747..c27c17b2 100644 --- a/src/raddbg/raddbg_eval.c +++ b/src/raddbg/raddbg_eval.c @@ -413,6 +413,12 @@ E_TYPE_ACCESS_FUNCTION_DEF(schema) { expr_is_simple = 1; } + if(expr->kind == E_ExprKind_LeafIdentifier && + (str8_match(expr->string, str8_lit("true"), 0) || + str8_match(expr->string, str8_lit("false"), 0))) + { + expr_is_simple = 1; + } if(!expr_is_simple && expr != &e_expr_nil) { child_type_key = e_type_key_cons_meta_expr(child_type_key, child->first->string); diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index e3a5a61a..292a3232 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -1129,7 +1129,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) if(type->kind == E_TypeKind_Set) { String8 file_path = e_string_from_id(row->eval.value.u64); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button|RD_WatchCellFlag_IsNonCode, .pct = 1.f); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button|RD_WatchCellFlag_IsNonCode, .pct = 1.f); if(str8_match(type->name, str8_lit("file"), 0)) { info.can_expand = 0; @@ -1167,7 +1167,12 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) else if(rd_cfg_child_from_string(rd_cfg_from_id(rd_regs()->view), str8_lit("lister")) != &rd_nil_cfg) { info.can_expand = 0; - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_Button|RD_WatchCellFlag_Indented, .pct = 1.f); + RD_WatchCellFlags extra_flags = 0; + if(row->eval.space.kind == RD_EvalSpaceKind_CtrlEntity) + { + extra_flags |= RD_WatchCellFlag_NoEval; + } + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, .flags = extra_flags|RD_WatchCellFlag_Expr|RD_WatchCellFlag_Button|RD_WatchCellFlag_Indented, .pct = 1.f); } //////////////////////////// @@ -1176,7 +1181,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) else if(is_top_level && evalled_cfg != &rd_nil_cfg) { RD_Cfg *cfg = evalled_cfg; - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_Button|RD_WatchCellFlag_Indented, .pct = 1.f); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Button|RD_WatchCellFlag_Indented, .pct = 1.f); MD_NodePtrList schemas = rd_schemas_from_name(cfg->string); for(MD_NodePtrNode *n = schemas.first; n != 0; n = n->next) { @@ -1248,7 +1253,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) CTRL_Entity *entity = evalled_entity; rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, - .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button, + .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button, .pct = 1.f); if(entity->kind == CTRL_EntityKind_Machine || entity->kind == CTRL_EntityKind_Process || @@ -1278,7 +1283,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) // else if(row->eval.space.kind == RD_EvalSpaceKind_MetaQuery) { - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string,.flags = RD_WatchCellFlag_Indented, .pct = 1.f); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented, .pct = 1.f); } //////////////////////////// @@ -1291,13 +1296,13 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, - .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_Indented, .pct = 1.f); + .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented, .pct = 1.f); } else { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .edit_string = row->edit_string, - .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button|RD_WatchCellFlag_ActivateWithSingleClick, + .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button|RD_WatchCellFlag_ActivateWithSingleClick, .pct = 1.f); } } @@ -1569,6 +1574,7 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla else { //- rjf: build left-hand-side strings + DR_FStrList expr_fstrs = {0}; if(cell->flags & RD_WatchCellFlag_Expr) { // rjf: funnel-through this cell's string, if it has one @@ -1677,19 +1683,17 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla // rjf: use expression string / params to generate fancy strings if(is_non_code) { - UI_TagF("weak") - { - DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), font_size, 0, 0}; - dr_fstrs_push_new(arena, &result.expr_fstrs, ¶ms, expr_string); - } + DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), font_size, 0, 0}; + dr_fstrs_push_new(arena, &expr_fstrs, ¶ms, expr_string); } else { - result.expr_fstrs = rd_fstrs_from_code_string(arena, 1, 0, ui_color_from_name(str8_lit("text")), expr_string); + expr_fstrs = rd_fstrs_from_code_string(arena, 1, 0, ui_color_from_name(str8_lit("text")), expr_string); } } //- rjf: evaluation -> need to form value string + DR_FStrList eval_fstrs = {0}; if(!(cell->flags & RD_WatchCellFlag_NoEval)) { // rjf: determine string generation parameters based on evaluation @@ -1726,15 +1730,26 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla String8 string = rd_value_string_from_eval(arena, rd_view_query_input(), &string_params, font, font_size, max_size_px, cell->eval); if(is_code) { - result.eval_fstrs = rd_fstrs_from_code_string(arena, 1, 0, ui_color_from_name(str8_lit("text")), string); + eval_fstrs = rd_fstrs_from_code_string(arena, 1, 0, ui_color_from_name(str8_lit("text")), string); } else UI_TagF("weak") { DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), font_size, 0, 0}; - dr_fstrs_push_new(arena, &result.eval_fstrs, ¶ms, string); + dr_fstrs_push_new(arena, &eval_fstrs, ¶ms, string); result.flags |= RD_WatchCellFlag_IsNonCode; } } + + //- rjf: if we have only the expression, then use the expression as the value + if(cell->flags & RD_WatchCellFlag_NoEval) + { + result.eval_fstrs = expr_fstrs; + } + else + { + result.expr_fstrs = expr_fstrs; + result.eval_fstrs = eval_fstrs; + } } }break; diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index e208376d..f916f247 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -3148,6 +3148,7 @@ internal UI_Signal rd_cell(RD_CellParams *params, String8 string) { ProfBeginFunction(); + Temp scratch = scratch_begin(0, 0); ////////////////////////////// //- rjf: unpack visual metrics @@ -3171,6 +3172,140 @@ rd_cell(RD_CellParams *params, String8 string) B32 is_focus_hot_disabled = (!is_focus_hot && ui_top_focus_hot() == UI_FocusKind_On); B32 is_focus_active_disabled = (!is_focus_active && ui_top_focus_active() == UI_FocusKind_On); + ////////////////////////////// + //- rjf: determine which sub-cell components we'll build + // + // (the base line edit textual label / editor is always built, but this can be enriched + // with extra widgets & metadata) + // + B32 build_toggle_switch = !!(params->flags & RD_CellFlag_ToggleSwitch && !is_focus_active); + B32 build_slider = !!(params->flags & RD_CellFlag_Slider && !is_focus_active); + B32 build_lhs_name_desc = (params->meta_fstrs.node_count != 0 || params->description.size != 0); + DR_FStrList lhs_name_fstrs = params->meta_fstrs; + DR_FStrList value_name_fstrs = params->value_fstrs; + + ////////////////////////////// + //- rjf: determine autocompletion string + // + String8 autocomplete_hint_string = {0}; + { + for(UI_Event *evt = 0; ui_next_event(&evt);) + { + if(evt->kind == UI_EventKind_AutocompleteHint) + { + autocomplete_hint_string = evt->string; + } + } + } + + ////////////////////////////// + //- rjf: compute editable fancy strings + // + DR_FStrList fstrs = {0}; + { + //- rjf: (not editing) + if(!is_focus_active && !is_focus_active_disabled && value_name_fstrs.total_size != 0) + { + fstrs = value_name_fstrs; + } + else if(!is_focus_active && !is_focus_active_disabled && params->flags & RD_CellFlag_CodeContents && params->pre_edit_value.size != 0) + { + String8 display_string = params->pre_edit_value; + fstrs = rd_fstrs_from_code_string(scratch.arena, 1, 0, ui_color_from_name(str8_lit("text")), display_string); + } + else if(!is_focus_active && !is_focus_active_disabled) + { + String8 display_string = params->pre_edit_value; + if(params->pre_edit_value.size == 0) + { + display_string = ui_display_part_from_key_string(string); + } + UI_TagF("weak") + { + DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; + dr_fstrs_push_new(scratch.arena, &fstrs, ¶ms, display_string); + } + } + + //- rjf: (editing) + else if((is_focus_active || is_focus_active_disabled) && params->flags & RD_CellFlag_CodeContents) + { + String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); + DR_FStrList code_fstrs = rd_fstrs_from_code_string(scratch.arena, 1.f, 0, ui_color_from_name(str8_lit("text")), edit_string); + if(autocomplete_hint_string.size != 0) + { + String8 query_word = rd_lister_query_word_from_input_string_off(edit_string, params->cursor->column-1); + String8 autocomplete_append_string = str8_skip(autocomplete_hint_string, query_word.size); + U64 off = 0; + U64 cursor_off = params->cursor->column-1; + DR_FStrNode *prev_n = 0; + for(DR_FStrNode *n = code_fstrs.first; n != 0; n = n->next) + { + if(off <= cursor_off && cursor_off <= off+n->v.string.size) + { + prev_n = n; + break; + } + off += n->v.string.size; + } + { + DR_FStrNode *autocomp_fstr_n = push_array(scratch.arena, DR_FStrNode, 1); + DR_FStr *fstr = &autocomp_fstr_n->v; + fstr->string = autocomplete_append_string; + fstr->params.font = ui_top_font(); + fstr->params.color = ui_color_from_name(str8_lit("text")); + fstr->params.color.w *= 0.5f; + fstr->params.size = ui_top_font_size(); + autocomp_fstr_n->next = prev_n ? prev_n->next : 0; + if(prev_n != 0) + { + prev_n->next = autocomp_fstr_n; + } + if(prev_n == 0) + { + code_fstrs.first = code_fstrs.last = autocomp_fstr_n; + } + if(prev_n != 0 && prev_n->next == 0) + { + code_fstrs.last = autocomp_fstr_n; + } + code_fstrs.node_count += 1; + code_fstrs.total_size += autocomplete_hint_string.size; + if(prev_n != 0 && cursor_off - off < prev_n->v.string.size) + { + String8 full_string = prev_n->v.string; + U64 chop_amt = full_string.size - (cursor_off - off); + prev_n->v.string = str8_chop(full_string, chop_amt); + code_fstrs.total_size -= chop_amt; + if(chop_amt != 0) + { + String8 post_cursor = str8_skip(full_string, cursor_off - off); + DR_FStrNode *post_fstr_n = push_array(scratch.arena, DR_FStrNode, 1); + DR_FStr *post_fstr = &post_fstr_n->v; + MemoryCopyStruct(post_fstr, &prev_n->v); + post_fstr->string = post_cursor; + if(autocomp_fstr_n->next == 0) + { + code_fstrs.last = post_fstr_n; + } + post_fstr_n->next = autocomp_fstr_n->next; + autocomp_fstr_n->next = post_fstr_n; + code_fstrs.node_count += 1; + code_fstrs.total_size += post_cursor.size; + } + } + } + } + fstrs = code_fstrs; + } + else if((is_focus_active || is_focus_active_disabled) && !(params->flags & RD_CellFlag_CodeContents)) + { + String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); + DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; + dr_fstrs_push_new(scratch.arena, &fstrs, ¶ms, edit_string); + } + } + ////////////////////////////// //- rjf: build top-level box // @@ -3235,29 +3370,78 @@ rd_cell(RD_CellParams *params, String8 string) //- rjf: build left-hand-side container box // UI_Box *lhs_box = &ui_nil_box; - UI_Parent(box) UI_WidthFill UI_ChildLayoutAxis(Axis2_Y) + if(build_lhs_name_desc) { - lhs_box = ui_build_box_from_stringf(0, "lhs_box"); - UI_Parent(lhs_box) + UI_Parent(box) UI_WidthFill UI_ChildLayoutAxis(Axis2_Y) { - ui_spacer(ui_em(3.f, 0.f)); + lhs_box = ui_build_box_from_stringf(0, "lhs_box"); } } + ////////////////////////////// + //- rjf: build line edit container box + // + UI_Box *edit_box = &ui_nil_box; + UI_Parent(box) if(fstrs.node_count != 0 || (!is_focus_active && !is_focus_active_disabled)) + { + UI_Size edit_box_size = ui_pct(1, 0); + if(build_lhs_name_desc) + { + edit_box_size = ui_px(dr_dim_from_fstrs(&fstrs).x + 10, 1.f); + ui_set_next_text_alignment(UI_TextAlign_Center); + } + UI_PrefWidth(edit_box_size) + edit_box = ui_build_box_from_stringf(0, "edit_box"); + } + ////////////////////////////// //- rjf: build scrollable container box // UI_Box *scrollable_box = &ui_nil_box; - UI_Parent(lhs_box) UI_WidthFill UI_HeightFill + if(edit_box != &ui_nil_box) { - scrollable_box = ui_build_box_from_stringf(is_focus_active*(UI_BoxFlag_AllowOverflowX), "scroll_box_%p", params->edit_buffer); + UI_Parent(edit_box) UI_WidthFill UI_HeightFill + { + scrollable_box = ui_build_box_from_stringf(is_focus_active*(UI_BoxFlag_AllowOverflowX), "scroll_box_%p", params->edit_buffer); + } + } + + ////////////////////////////// + //- rjf: build left-hand-side name/desc box + // + if(build_lhs_name_desc) UI_Parent(lhs_box) UI_Padding(ui_em(3.f, 0.f)) UI_WidthFill UI_HeightFill + { + FuzzyMatchRangeList fuzzy_matches = {0}; + if(params->search_needle.size != 0) + { + fuzzy_matches = dr_fuzzy_match_find_from_fstrs(scratch.arena, &lhs_name_fstrs, params->search_needle); + } + UI_Row + { + if(ui_top_text_alignment() == UI_TextAlign_Left && (params->flags & (RD_CellFlag_Expander|RD_CellFlag_ExpanderSpace|RD_CellFlag_ExpanderPlaceholder)) == 0) + { + ui_spacer(ui_em(0.5f, 1.f)); + } + UI_Box *name_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); + ui_box_equip_display_fstrs(name_box, &lhs_name_fstrs); + ui_box_equip_fuzzy_match_ranges(name_box, &fuzzy_matches); + } + if(params->description.size != 0) RD_Font(RD_FontSlot_Main) UI_FontSize(ui_top_font_size()*0.85f) + { + UI_Row + { + ui_spacer(ui_em(0.5f, 1.f)); + UI_Box *desc_box = ui_label(params->description).box; + FuzzyMatchRangeList desc_fuzzy_matches = fuzzy_match_find(scratch.arena, params->search_needle, params->description); + ui_box_equip_fuzzy_match_ranges(desc_box, &desc_fuzzy_matches); + } + } } ////////////////////////////// //- rjf: build toggle-switch // - if(params->flags & RD_CellFlag_ToggleSwitch && !is_focus_active) - UI_Parent(box) + if(build_toggle_switch) UI_Parent(box) { B32 is_toggled = !!params->toggled_out[0]; F32 toggle_t = ui_anim(ui_key_from_stringf(key, "toggled"), (F32)is_toggled, .initial = (F32)is_toggled); @@ -3307,8 +3491,7 @@ rd_cell(RD_CellParams *params, String8 string) ////////////////////////////// //- rjf: build slider // - if(params->flags & RD_CellFlag_Slider && !is_focus_active) - UI_Parent(box) + if(build_slider) UI_Parent(box) { F32 height_px = ceil_f32(ui_top_font_size() * 1.75f); F32 padding_px = ceil_f32((ui_top_px_height() - height_px) / 2.f); @@ -3438,20 +3621,6 @@ rd_cell(RD_CellParams *params, String8 string) sig.f |= UI_SignalFlag_Commit; } - ////////////////////////////// - //- rjf: determine autocompletion string - // - String8 autocomplete_hint_string = {0}; - { - for(UI_Event *evt = 0; ui_next_event(&evt);) - { - if(evt->kind == UI_EventKind_AutocompleteHint) - { - autocomplete_hint_string = evt->string; - } - } - } - ////////////////////////////// //- rjf: take navigation actions for editing // @@ -3521,128 +3690,13 @@ rd_cell(RD_CellParams *params, String8 string) // TxtPt mouse_pt = {0}; F32 cursor_off = 0; - UI_Parent(scrollable_box) + if(scrollable_box != &ui_nil_box) UI_Parent(scrollable_box) { - Temp scratch = scratch_begin(0, 0); - - //- rjf: compute fancy strings - DR_FStrList fstrs = {0}; - { - //- rjf: (not editing) - if(!is_focus_active && !is_focus_active_disabled && params->expr_fstrs.total_size != 0) - { - fstrs = params->expr_fstrs; - } - else if(!is_focus_active && !is_focus_active_disabled && params->eval_fstrs.total_size != 0) - { - fstrs = params->eval_fstrs; - } - else if(!is_focus_active && !is_focus_active_disabled && params->flags & RD_CellFlag_CodeContents && params->pre_edit_value.size != 0) - { - String8 display_string = params->pre_edit_value; - fstrs = rd_fstrs_from_code_string(scratch.arena, 1, 0, ui_color_from_name(str8_lit("text")), display_string); - } - else if(!is_focus_active && !is_focus_active_disabled) - { - String8 display_string = params->pre_edit_value; - if(params->pre_edit_value.size == 0) - { - display_string = ui_display_part_from_key_string(string); - } - UI_TagF("weak") - { - DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; - dr_fstrs_push_new(scratch.arena, &fstrs, ¶ms, display_string); - } - } - - //- rjf: (editing) - else if((is_focus_active || is_focus_active_disabled) && params->flags & RD_CellFlag_CodeContents) - { - String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); - DR_FStrList code_fstrs = rd_fstrs_from_code_string(scratch.arena, 1.f, 0, ui_color_from_name(str8_lit("text")), edit_string); - if(autocomplete_hint_string.size != 0) - { - String8 query_word = rd_lister_query_word_from_input_string_off(edit_string, params->cursor->column-1); - String8 autocomplete_append_string = str8_skip(autocomplete_hint_string, query_word.size); - U64 off = 0; - U64 cursor_off = params->cursor->column-1; - DR_FStrNode *prev_n = 0; - for(DR_FStrNode *n = code_fstrs.first; n != 0; n = n->next) - { - if(off <= cursor_off && cursor_off <= off+n->v.string.size) - { - prev_n = n; - break; - } - off += n->v.string.size; - } - { - DR_FStrNode *autocomp_fstr_n = push_array(scratch.arena, DR_FStrNode, 1); - DR_FStr *fstr = &autocomp_fstr_n->v; - fstr->string = autocomplete_append_string; - fstr->params.font = ui_top_font(); - fstr->params.color = ui_color_from_name(str8_lit("text")); - fstr->params.color.w *= 0.5f; - fstr->params.size = ui_top_font_size(); - autocomp_fstr_n->next = prev_n ? prev_n->next : 0; - if(prev_n != 0) - { - prev_n->next = autocomp_fstr_n; - } - if(prev_n == 0) - { - code_fstrs.first = code_fstrs.last = autocomp_fstr_n; - } - if(prev_n != 0 && prev_n->next == 0) - { - code_fstrs.last = autocomp_fstr_n; - } - code_fstrs.node_count += 1; - code_fstrs.total_size += autocomplete_hint_string.size; - if(prev_n != 0 && cursor_off - off < prev_n->v.string.size) - { - String8 full_string = prev_n->v.string; - U64 chop_amt = full_string.size - (cursor_off - off); - prev_n->v.string = str8_chop(full_string, chop_amt); - code_fstrs.total_size -= chop_amt; - if(chop_amt != 0) - { - String8 post_cursor = str8_skip(full_string, cursor_off - off); - DR_FStrNode *post_fstr_n = push_array(scratch.arena, DR_FStrNode, 1); - DR_FStr *post_fstr = &post_fstr_n->v; - MemoryCopyStruct(post_fstr, &prev_n->v); - post_fstr->string = post_cursor; - if(autocomp_fstr_n->next == 0) - { - code_fstrs.last = post_fstr_n; - } - post_fstr_n->next = autocomp_fstr_n->next; - autocomp_fstr_n->next = post_fstr_n; - code_fstrs.node_count += 1; - code_fstrs.total_size += post_cursor.size; - } - } - } - } - fstrs = code_fstrs; - } - else if((is_focus_active || is_focus_active_disabled) && !(params->flags & RD_CellFlag_CodeContents)) - { - String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); - DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; - dr_fstrs_push_new(scratch.arena, &fstrs, ¶ms, edit_string); - } - } - - //- rjf: compute fuzzy match ranges FuzzyMatchRangeList fuzzy_matches = {0}; if(params->search_needle.size != 0) { fuzzy_matches = dr_fuzzy_match_find_from_fstrs(scratch.arena, &fstrs, params->search_needle); } - - //- rjf: build textual content if(ui_top_text_alignment() == UI_TextAlign_Left && (params->flags & (RD_CellFlag_Expander|RD_CellFlag_ExpanderSpace|RD_CellFlag_ExpanderPlaceholder)) == 0) { ui_spacer(ui_em(0.5f, 1.f)); @@ -3674,24 +3728,6 @@ rd_cell(RD_CellParams *params, String8 string) mouse_pt = txt_pt(1, 1+mouse_pt_off); cursor_off = fnt_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), str8_prefix(edit_string, params->cursor->column-1)).x; } - - scratch_end(scratch); - } - - ////////////////////////////// - //- rjf: build description - // - if(params->description.size != 0) UI_Parent(lhs_box) UI_HeightFill RD_Font(RD_FontSlot_Main) UI_FontSize(ui_top_font_size()*0.85f) - { - UI_Row - { - ui_spacer(ui_em(0.5f, 1.f)); - ui_label(params->description); - } - } - UI_Parent(lhs_box) - { - ui_spacer(ui_em(3.f, 0.f)); } ////////////////////////////// @@ -3741,6 +3777,7 @@ rd_cell(RD_CellParams *params, String8 string) if(is_auto_focus_active) { ui_pop_focus_active(); } ProfEnd(); + scratch_end(scratch); return sig; } diff --git a/src/raddbg/raddbg_widgets.h b/src/raddbg/raddbg_widgets.h index c657689c..293f115e 100644 --- a/src/raddbg/raddbg_widgets.h +++ b/src/raddbg/raddbg_widgets.h @@ -42,8 +42,8 @@ struct RD_CellParams RD_CellFlags flags; S32 depth; String8 pre_edit_value; - DR_FStrList expr_fstrs; - DR_FStrList eval_fstrs; + DR_FStrList meta_fstrs; + DR_FStrList value_fstrs; String8 search_needle; String8 description; diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 49c14597..33edb2e6 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -944,6 +944,9 @@ internal F32 ui_anim_(UI_Key key, UI_AnimParams *params); //////////////////////////////// //~ rjf: Stacks +internal void ui__push_tags_key_from_appended_string(String8 string); +internal void ui__pop_tags_key(void); + //- rjf: base internal UI_Box * ui_top_parent(void); internal Axis2 ui_top_child_layout_axis(void);