begin work on lister-flavored watch windows; begin on using that for the query ui

This commit is contained in:
Ryan Fleury
2025-02-19 08:37:34 -08:00
parent 73351b7550
commit 9805f8cd20
7 changed files with 711 additions and 581 deletions
+3 -3
View File
@@ -169,7 +169,7 @@ E_LOOKUP_RANGE_FUNCTION_DEF(folder)
if(0 <= idx && idx < accel->folders.count)
{
String8 folder_name = accel->folders.v[idx - 0];
String8 folder_path = push_str8f(scratch.arena, "%S/%S", accel->folder_path, folder_name);
String8 folder_path = push_str8f(scratch.arena, "%S%s%S", accel->folder_path, accel->folder_path.size != 0 ? "/" : "", folder_name);
expr = e_push_expr(arena, E_ExprKind_LeafValue, 0);
expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("folder"));
expr->space = e_space_make(E_SpaceKind_FileSystem);
@@ -179,7 +179,7 @@ E_LOOKUP_RANGE_FUNCTION_DEF(folder)
else if(accel->folders.count <= idx && idx < accel->folders.count + accel->files.count)
{
String8 file_name = accel->files.v[idx - accel->folders.count];
String8 file_path = push_str8f(scratch.arena, "%S/%S", accel->folder_path, file_name);
String8 file_path = push_str8f(scratch.arena, "%S%s%S", accel->folder_path, accel->folder_path.size != 0 ? "/" : "", file_name);
expr = e_push_expr(arena, E_ExprKind_LeafValue, 0);
expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("file"));
expr->space = e_space_make(E_SpaceKind_FileSystem);
@@ -2253,7 +2253,7 @@ E_IRGEN_FUNCTION_DEF(default)
Temp scratch = scratch_begin(&arena, 1);
String8 file_path = path_normalized_from_string(scratch.arena, expr->string);
FileProperties props = os_properties_from_file_path(file_path);
if(props.flags & FilePropertyFlag_IsFolder)
if(props.flags & FilePropertyFlag_IsFolder || props.modified == 0)
{
E_Space space = e_space_make(E_SpaceKind_FileSystem);
result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(file_path)));
+21
View File
@@ -547,6 +547,27 @@ os_properties_from_file_path(String8 path)
os_w32_dense_time_from_file_time(&props.modified, &find_data.ftLastWriteTime);
props.flags = os_w32_file_property_flags_from_dwFileAttributes(find_data.dwFileAttributes);
}
else
{
Temp scratch = scratch_begin(0, 0);
WCHAR buffer[512] = {0};
DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer);
U64 last_slash_pos = str8_find_needle(path, 0, str8_lit("/"), StringMatchFlag_SlashInsensitive);
String8 path_trimmed = str8_prefix(path, last_slash_pos);
for(U64 off = 0; off < (U64)length;)
{
String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off);
off += next_drive_string_16.size+1;
String8 next_drive_string = str8_from_16(scratch.arena, next_drive_string_16);
next_drive_string = str8_chop_last_slash(next_drive_string);
if(str8_match(path_trimmed, next_drive_string, StringMatchFlag_CaseInsensitive))
{
props.flags |= FilePropertyFlag_IsFolder;
break;
}
}
scratch_end(scratch);
}
FindClose(handle);
scratch_end(scratch);
return props;
+99 -560
View File
@@ -2090,362 +2090,7 @@ rd_target_from_cfg(Arena *arena, RD_Cfg *cfg)
return target;
}
internal DR_FStrList
rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg)
{
DR_FStrList result = {0};
{
Temp scratch = scratch_begin(&arena, 1);
//- rjf: unpack config
B32 is_disabled = rd_disabled_from_cfg(cfg);
RD_Location loc = rd_location_from_cfg(cfg);
D_Target target = rd_target_from_cfg(scratch.arena, cfg);
String8 label_string = rd_label_from_cfg(cfg);
String8 expr_string = rd_expr_from_cfg(cfg);
String8 collection_name = {0};
String8 file_path = {0};
Vec4F32 rgba = rd_color_from_cfg(cfg);
if(rgba.w == 0)
{
rgba = ui_color_from_name(str8_lit("text"));
}
Vec4F32 rgba_secondary = rgba;
UI_TagF("weak")
{
rgba_secondary = ui_color_from_name(str8_lit("text"));
}
RD_IconKind icon_kind = rd_icon_kind_from_code_name(cfg->string);
B32 is_from_command_line = 0;
{
RD_Cfg *cmd_line_root = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("command_line"));
for(RD_Cfg *p = cfg->parent; p != &rd_nil_cfg; p = p->parent)
{
if(p == cmd_line_root)
{
is_from_command_line = 1;
break;
}
}
}
B32 is_within_window = 0;
{
for(RD_Cfg *p = cfg->parent; p != &rd_nil_cfg; p = p->parent)
{
if(str8_match(p->string, str8_lit("window"), 0))
{
is_within_window = 1;
break;
}
}
}
if(expr_string.size != 0)
{
String8 query_name = rd_query_from_eval_string(arena, expr_string);
if(query_name.size != 0 && !str8_match(query_name, str8_lit("watches"), 0))
{
String8 query_code_name = query_name;
String8 query_display_name = rd_display_from_code_name(query_code_name);
collection_name = query_display_name;
if(query_display_name.size == 0)
{
query_code_name = rd_singular_from_code_name_plural(query_name);
collection_name = rd_display_plural_from_code_name(query_code_name);
}
RD_IconKind query_icon_kind = rd_icon_kind_from_code_name(query_code_name);
if(query_icon_kind != RD_IconKind_Null)
{
icon_kind = query_icon_kind;
}
}
else
{
file_path = rd_file_path_from_eval_string(arena, expr_string);
if(file_path.size != 0)
{
icon_kind = RD_IconKind_FileOutline;
}
}
}
//- rjf: set up color/size for all parts of the title
//
// the "running" part implies that it changes as things are added -
// so if a primary title is pushed, we can make the rest of the title
// more faded/smaller, but only after a primary title is pushed,
// which could be caused by many different potential parts of a cfg.
//
DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), rgba, ui_top_font_size()};
B32 running_is_secondary = 0;
#define start_secondary() if(!running_is_secondary){running_is_secondary = 1; params.color = rgba_secondary; params.size = ui_top_font_size()*0.95f;}
//- rjf: push icon
if(icon_kind != RD_IconKind_Null)
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rgba_secondary);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push warning icon for command-line entities
if(is_from_command_line)
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[RD_IconKind_Info], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rgba_secondary);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push view title, if from window, and no file path
if(is_within_window && file_path.size == 0 && collection_name.size == 0)
{
String8 view_display_name = rd_display_from_code_name(cfg->string);
if(view_display_name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, view_display_name);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
}
//- rjf: push label
if(label_string.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, label_string, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: push collection name
if(collection_name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, collection_name);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: query is file path - do specific file name strings
else if(file_path.size != 0)
{
// rjf: compute disambiguated file name
String8List qualifiers = {0};
String8 file_name = str8_skip_last_slash(file_path);
if(rd_state->ambiguous_path_slots_count != 0)
{
U64 hash = d_hash_from_string__case_insensitive(file_name);
U64 slot_idx = hash%rd_state->ambiguous_path_slots_count;
RD_AmbiguousPathNode *node = 0;
{
for(RD_AmbiguousPathNode *n = rd_state->ambiguous_path_slots[slot_idx];
n != 0;
n = n->next)
{
if(str8_match(n->name, file_name, StringMatchFlag_CaseInsensitive))
{
node = n;
break;
}
}
}
if(node != 0 && node->paths.node_count > 1)
{
// rjf: get all colliding paths
String8Array collisions = str8_array_from_list(scratch.arena, &node->paths);
// rjf: get all reversed path parts for each collision
String8List *collision_parts_reversed = push_array(scratch.arena, String8List, collisions.count);
for EachIndex(idx, collisions.count)
{
String8List parts = str8_split_path(scratch.arena, collisions.v[idx]);
for(String8Node *n = parts.first; n != 0; n = n->next)
{
str8_list_push_front(scratch.arena, &collision_parts_reversed[idx], n->string);
}
}
// rjf: get the search path & its reversed parts
String8List parts = str8_split_path(scratch.arena, file_path);
String8List parts_reversed = {0};
for(String8Node *n = parts.first; n != 0; n = n->next)
{
str8_list_push_front(scratch.arena, &parts_reversed, n->string);
}
// rjf: iterate all collision part reversed lists, in lock-step with
// search path; disqualify until we only have one path remaining; gather
// qualifiers
{
U64 num_collisions_left = collisions.count;
String8Node **collision_nodes = push_array(scratch.arena, String8Node *, collisions.count);
for EachIndex(idx, collisions.count)
{
collision_nodes[idx] = collision_parts_reversed[idx].first;
}
for(String8Node *n = parts_reversed.first; num_collisions_left > 1 && n != 0; n = n->next)
{
B32 part_is_qualifier = 0;
for EachIndex(idx, collisions.count)
{
if(collision_nodes[idx] != 0 && !str8_match(collision_nodes[idx]->string, n->string, StringMatchFlag_CaseInsensitive))
{
collision_nodes[idx] = 0;
num_collisions_left -= 1;
part_is_qualifier = 1;
}
else if(collision_nodes[idx] != 0)
{
collision_nodes[idx] = collision_nodes[idx]->next;
}
}
if(part_is_qualifier)
{
str8_list_push_front(scratch.arena, &qualifiers, n->string);
}
}
}
}
}
// rjf: push qualifiers
for(String8Node *n = qualifiers.first; n != 0; n = n->next)
{
String8 string = push_str8f(arena, "<%S> ", n->string);
dr_fstrs_push_new(arena, &result, &params, string, .color = ui_top_palette()->text_weak);
}
// rjf: push file name
dr_fstrs_push_new(arena, &result, &params, push_str8_copy(arena, str8_skip_last_slash(file_path)));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: cfg has expression attached -> use that
else if(expr_string.size != 0 && !str8_match(cfg->string, str8_lit("watch"), 0))
{
dr_fstrs_push_new(arena, &result, &params, expr_string, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: push text location
if(loc.file_path.size != 0)
{
String8 location_string = push_str8f(arena, "%S:%I64d:%I64d", str8_skip_last_slash(loc.file_path), loc.pt.line, loc.pt.column);
dr_fstrs_push_new(arena, &result, &params, location_string);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: push target executable name
if(target.exe.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, str8_skip_last_slash(target.exe));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: push target arguments
if(target.args.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, target.args);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push conditions
{
String8 condition = rd_cfg_child_from_string(cfg, str8_lit("condition"))->first->string;
if(condition.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit("if "), .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code));
RD_Font(RD_FontSlot_Code)
{
DR_FStrList fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, params.color, condition);
dr_fstrs_concat_in_place(&result, &fstrs);
}
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
}
//- rjf: push disabled marker
if(is_disabled)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit("(Disabled)"));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push hit count
{
String8 hit_count_value_string = rd_cfg_child_from_string(cfg, str8_lit("hit_count"))->first->string;
U64 hit_count = 0;
if(try_u64_from_str8_c_rules(hit_count_value_string, &hit_count))
{
String8 hit_count_text = push_str8f(arena, "(%I64u hit%s)", hit_count, hit_count == 1 ? "" : "s");
dr_fstrs_push_new(arena, &result, &params, hit_count_text);
}
}
//- rjf: special case: auto view rule
if(str8_match(cfg->string, str8_lit("auto_view_rule"), 0))
{
String8 src_string = rd_cfg_child_from_string(cfg, str8_lit("source"))->first->string;
String8 dst_string = rd_cfg_child_from_string(cfg, str8_lit("dest"))->first->string;
Vec4F32 src_color = rgba;
Vec4F32 dst_color = rgba;
DR_FStrList src_fstrs = {0};
DR_FStrList dst_fstrs = {0};
if(src_string.size == 0)
{
src_string = str8_lit("(type)");
src_color = ui_top_palette()->text_weak;
dr_fstrs_push_new(arena, &src_fstrs, &params, src_string, .color = src_color);
}
else RD_Font(RD_FontSlot_Code)
{
src_fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, src_color, src_string);
}
if(dst_string.size == 0)
{
dst_string = str8_lit("(view rule)");
dst_color = ui_top_palette()->text_weak;
dr_fstrs_push_new(arena, &dst_fstrs, &params, dst_string, .color = dst_color);
}
else RD_Font(RD_FontSlot_Code)
{
dst_fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, dst_color, dst_string);
}
dr_fstrs_concat_in_place(&result, &src_fstrs);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[RD_IconKind_RightArrow], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_top_palette()->text_weak);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_concat_in_place(&result, &dst_fstrs);
}
//- rjf: special case: file path maps
if(str8_match(cfg->string, str8_lit("file_path_map"), 0))
{
String8 src_string = rd_cfg_child_from_string(cfg, str8_lit("source"))->first->string;
String8 dst_string = rd_cfg_child_from_string(cfg, str8_lit("dest"))->first->string;
Vec4F32 src_color = rgba;
Vec4F32 dst_color = rgba;
if(src_string.size == 0)
{
src_string = str8_lit("(source path)");
src_color = ui_top_palette()->text_weak;
}
if(dst_string.size == 0)
{
dst_string = str8_lit("(destination path)");
dst_color = ui_top_palette()->text_weak;
}
dr_fstrs_push_new(arena, &result, &params, src_string, .color = src_color);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[RD_IconKind_RightArrow], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_top_palette()->text_weak);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, dst_string, .color = dst_color);
}
#undef start_secondary
scratch_end(scratch);
}
return result;
}
internal MD_Node *
rd_schema_from_name(Arena *arena, String8 name)
@@ -2733,145 +2378,6 @@ rd_name_from_ctrl_entity(Arena *arena, CTRL_Entity *entity)
return string;
}
internal DR_FStrList
rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_extras)
{
DR_FStrList result = {0};
//- rjf: unpack entity info
F32 extras_size = ui_top_font_size()*0.95f;
Vec4F32 color = rd_color_from_ctrl_entity(entity);
if(color.w == 0)
{
color = ui_top_palette()->text;
}
Vec4F32 secondary_color = ui_top_palette()->text_weak;
String8 name = rd_name_from_ctrl_entity(arena, entity);
RD_IconKind icon_kind = RD_IconKind_Null;
B32 name_is_code = 0;
switch(entity->kind)
{
default:{}break;
case CTRL_EntityKind_Machine: {icon_kind = RD_IconKind_Machine;}break;
case CTRL_EntityKind_Process: {icon_kind = RD_IconKind_Threads;}break;
case CTRL_EntityKind_Thread: {icon_kind = RD_IconKind_Thread; name_is_code = 1;}break;
case CTRL_EntityKind_Module: {icon_kind = RD_IconKind_Module;}break;
}
//- rjf: set up drawing params
DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Code), rd_raster_flags_from_slot(RD_FontSlot_Code), color, ui_top_font_size()};
//- rjf: push icon
if(icon_kind != RD_IconKind_Null)
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = secondary_color);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push frozen icon, if frozen
if((entity->kind == CTRL_EntityKind_Machine ||
entity->kind == CTRL_EntityKind_Process ||
entity->kind == CTRL_EntityKind_Thread) &&
ctrl_entity_tree_is_frozen(entity))
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[RD_IconKind_Locked], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_top_palette()->background_bad);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push containing process prefix
if(entity->kind == CTRL_EntityKind_Thread ||
entity->kind == CTRL_EntityKind_Module)
{
CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process);
if(processes.count > 1)
{
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process);
String8 process_name = rd_name_from_ctrl_entity(arena, process);
Vec4F32 process_color = rd_color_from_ctrl_entity(process);
if(process_color.w == 0)
{
process_color = color;
}
if(process_name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, process_name, .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = process_color);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, push_str8f(arena, "(PID: %I64u)", process->id), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = secondary_color, .size = ui_top_font_size()*0.9f);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" / "), .color = secondary_color);
}
}
}
//- rjf: push name
dr_fstrs_push_new(arena, &result, &params, name,
.font = rd_font_from_slot(name_is_code ? RD_FontSlot_Code : RD_FontSlot_Main),
.raster_flags = rd_raster_flags_from_slot(name_is_code ? RD_FontSlot_Code : RD_FontSlot_Main),
.color = color);
//- rjf: push PID
if(entity->kind == CTRL_EntityKind_Process)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, push_str8f(arena, " (PID: %I64u)", entity->id), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = secondary_color, .size = ui_top_font_size()*0.85f);
}
//- rjf: threads get callstack extras
if(entity->kind == CTRL_EntityKind_Thread && include_extras)
{
Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol"));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
DI_Scope *di_scope = di_scope_open();
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process);
Arch arch = entity->arch;
CTRL_Unwind unwind = d_query_cached_unwind_from_thread(entity);
for(U64 idx = 0, limit = 6; idx < unwind.frames.count && idx < limit; idx += 1)
{
CTRL_UnwindFrame *f = &unwind.frames.v[unwind.frames.count - 1 - idx];
U64 rip_vaddr = regs_rip_from_arch_block(arch, f->regs);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
if(rdi != &di_rdi_parsed_nil)
{
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, rip_voff);
String8 name = {0};
name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size);
name = push_str8_copy(arena, name);
if(name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, name, .size = extras_size, .color = symbol_color);
if(idx+1 < unwind.frames.count)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit(" > "), .color = secondary_color, .size = extras_size);
if(idx+1 == limit)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit("..."), .color = secondary_color, .size = extras_size);
}
}
}
}
}
di_scope_close(di_scope);
}
//- rjf: modules get debug info status extras
if(entity->kind == CTRL_EntityKind_Module && include_extras)
{
DI_Scope *di_scope = di_scope_open();
DI_Key dbgi_key = ctrl_dbgi_key_from_module(entity);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
if(rdi->raw_data_size == 0)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, str8_lit("(Symbols not found)"), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .size = extras_size, .color = secondary_color);
}
di_scope_close(di_scope);
}
return result;
}
////////////////////////////////
//~ rjf: Evaluation Spaces
@@ -4503,8 +4009,9 @@ rd_window_frame(void)
RD_PanelTree panel_tree = rd_panel_tree_from_cfg(scratch.arena, window);
B32 window_is_focused = (os_window_is_focused(ws->os) || ws->window_temporarily_focused_ipc);
B32 popup_is_open = (rd_state->popup_active);
B32 query_is_open = (ws->top_query_lister != 0);
B32 query_is_open = (rd_cfg_child_from_string(window, str8_lit("query")) != &rd_nil_cfg);
B32 hover_eval_is_open = (!popup_is_open &&
!query_is_open &&
ws->hover_eval_string.size != 0 &&
ws->hover_eval_first_frame_idx+20 < ws->hover_eval_last_frame_idx &&
rd_state->frame_index-ws->hover_eval_last_frame_idx < 20);
@@ -5173,8 +4680,10 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
}
////////////////////////////
//- rjf: do query lister stack controls
//- rjf: build listers
//
#if 0 // TODO(rjf): @cfg
//- rjf: do query lister stack controls
if(ws->top_query_lister != 0)
{
if(ui_slot_press(UI_EventActionSlot_Cancel))
@@ -5192,10 +4701,6 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
scratch_end(scratch);
}
}
////////////////////////////
//- rjf: build listers
//
for(ListerTask *task = first_lister_task; task != 0; task = task->next)
{
DI_Scope *di_scope = di_scope_open();
@@ -5490,6 +4995,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
di_scope_close(di_scope);
}
#endif
#if 0 // TODO(rjf): @cfg_lister
////////////////////////////
@@ -6115,6 +5621,92 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
}
}
////////////////////////////
//- rjf: build query
//
{
RD_Cfg *query = rd_cfg_child_from_string(window, str8_lit("query"));
if(query != &rd_nil_cfg)
{
//- rjf: unpack query parameters
RD_Cfg *root = query;
RD_Cfg *view = rd_cfg_child_from_string_or_alloc(root, str8_lit("watch"));
rd_cfg_new(view, str8_lit("lister"));
RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(view, str8_lit("expression"));
String8 query_expression = str8_lit("query:procedures");
rd_cfg_new_replace(expr, query_expression);
E_Eval query_eval = e_eval_from_string(scratch.arena, query_expression);
F32 row_height_px = floor_f32(ui_top_font_size()*2.5f);
//- rjf: build
RD_RegsScope(.view = view->id)
{
Vec2F32 content_rect_center = center_2f32(content_rect);
Vec2F32 content_rect_dim = dim_2f32(content_rect);
EV_BlockTree predicted_block_tree = ev_block_tree_from_exprs(scratch.arena, rd_view_eval_view(), str8_zero(), query_eval.exprs);
F32 query_open_t = ui_anim(ui_key_from_string(ui_key_zero(), str8_lit("query_open_t")), 1.f);
F32 query_width_px = floor_f32(dim_2f32(content_rect).x * 0.35f);
F32 max_query_height_px = content_rect_dim.y*0.8f;
F32 query_height_px = max_query_height_px;
Rng2F32 query_rect = r2f32p(content_rect_center.x - query_width_px/2,
content_rect_center.y - max_query_height_px/2.f,
content_rect_center.x + query_width_px/2,
content_rect_center.y - max_query_height_px/2.f + query_height_px*query_open_t);
RD_Font(RD_FontSlot_Code)
UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Main))
UI_TagF("floating")
UI_Focus(UI_FocusKind_On)
UI_PrefHeight(ui_px(row_height_px, 1.f))
{
//- rjf: build top-level container
UI_Box *container = &ui_nil_box;
UI_Rect(query_rect)
UI_Squish(0.25f-0.25f*query_open_t)
UI_Transparency(1.f-query_open_t)
UI_ChildLayoutAxis(Axis2_Y)
{
container = ui_build_box_from_string(UI_BoxFlag_Clickable|
UI_BoxFlag_DrawBorder|
UI_BoxFlag_DrawBackground|
UI_BoxFlag_DrawBackgroundBlur|
UI_BoxFlag_DisableFocusOverlay|
UI_BoxFlag_DrawDropShadow,
str8_lit("query_container"));
}
//- rjf: fill container
UI_Parent(container) UI_Focus(UI_FocusKind_Null)
{
ui_set_next_pref_width(ui_pct(1, 0));
ui_set_next_pref_height(ui_pct(1, 0));
ui_set_next_child_layout_axis(Axis2_Y);
UI_Box *view_contents_container = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clip, "###view_contents_container");
UI_Parent(view_contents_container) UI_WidthFill
{
rd_view_ui(view_contents_container->rect);
}
}
}
}
//- rjf: do interactions
if(ui_slot_press(UI_EventActionSlot_Cancel))
{
rd_cmd(RD_CmdKind_CancelQuery);
}
if(ui_slot_press(UI_EventActionSlot_Accept))
{
}
//- rjf: build darkening rectangle over rest of screen
UI_Rect(window_rect) UI_TagF("inactive")
{
ui_build_box_from_key(UI_BoxFlag_DrawBackground, ui_key_zero());
}
}
}
////////////////////////////
//- rjf: top bar
//
@@ -6820,7 +6412,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
// rjf: close dropdown
UI_Key close_ctx_menu_key = ui_key_from_stringf(ui_key_zero(), "###close_ctx_menu");
UI_CtxMenu(close_ctx_menu_key)
UI_CtxMenu(close_ctx_menu_key) UI_TagF("implicit")
{
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Window, 0, "Close Window")))
{
@@ -10783,44 +10375,6 @@ rd_vocab_info_from_code_name_plural(String8 code_name_plural)
return result;
}
internal DR_FStrList
rd_title_fstrs_from_code_name(Arena *arena, String8 code_name)
{
DR_FStrList result = {0};
{
RD_VocabInfo *info = rd_vocab_info_from_code_name(code_name);
//- rjf: set up color/size for all parts of the title
//
// the "running" part implies that it changes as things are added -
// so if a primary title is pushed, we can make the rest of the title
// more faded/smaller, but only after a primary title is pushed,
// which could be caused by many different potential parts of a cfg.
//
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")), ui_top_font_size()};
//- rjf: push icon
if(info->icon_kind != RD_IconKind_Null) UI_Tag(str8_lit("weak"))
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[info->icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text")));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push display name
if(info->display_name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, info->display_name);
}
//- rjf: push code name as a fallback
else
{
dr_fstrs_push_new(arena, &result, &params, code_name, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code));
}
}
return result;
}
////////////////////////////////
//~ rjf: Continuous Frame Requests
@@ -14704,19 +14258,10 @@ Z(getting_started)
//- rjf: query stack
case RD_CmdKind_PushQuery:
{
RD_Cfg *wcfg = rd_cfg_from_id(rd_regs()->window);
RD_WindowState *ws = rd_window_state_from_cfg(wcfg);
if(ws != &rd_nil_window_state)
{
Arena *arena = arena_alloc();
RD_Lister *lister = push_array(arena, RD_Lister, 1);
lister->arena = arena;
lister->regs = rd_regs_copy(lister->arena, rd_regs());
lister->input_string_size = Min(rd_regs()->string.size, sizeof(lister->input_buffer));
lister->input_cursor = lister->input_mark = txt_pt(1, lister->input_string_size+1);
MemoryCopy(lister->input_buffer, rd_regs()->string.str, lister->input_string_size);
SLLStackPush(ws->top_query_lister, lister);
}
RD_Cfg *window = rd_cfg_from_id(rd_regs()->window);
RD_Cfg *current_query = rd_cfg_child_from_string(window, str8_lit("query"));
rd_cfg_release(current_query);
RD_Cfg *new_query = rd_cfg_new(window, str8_lit("query"));
}break;
case RD_CmdKind_CompleteQuery:
{
@@ -14767,13 +14312,7 @@ Z(getting_started)
case RD_CmdKind_CancelQuery:
{
RD_Cfg *window = rd_cfg_from_id(rd_regs()->window);
RD_WindowState *ws = rd_window_state_from_cfg(window);
RD_Lister *top_lister = ws->top_query_lister;
if(top_lister != 0)
{
SLLStackPop(ws->top_query_lister);
arena_release(top_lister->arena);
}
rd_cfg_release(rd_cfg_child_from_string(window, str8_lit("query")));
}break;
//- rjf: developer commands
-3
View File
@@ -998,7 +998,6 @@ internal String8 rd_label_from_cfg(RD_Cfg *cfg);
internal String8 rd_expr_from_cfg(RD_Cfg *cfg);
internal String8 rd_view_rule_from_cfg(RD_Cfg *cfg);
internal D_Target rd_target_from_cfg(Arena *arena, RD_Cfg *cfg);
internal DR_FStrList rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg);
internal MD_Node *rd_schema_from_name(Arena *arena, String8 name);
@@ -1019,7 +1018,6 @@ internal E_Expr *rd_tag_from_cfg(Arena *arena, RD_Cfg *cfg);
internal Vec4F32 rd_color_from_ctrl_entity(CTRL_Entity *entity);
internal String8 rd_name_from_ctrl_entity(Arena *arena, CTRL_Entity *entity);
internal DR_FStrList rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_extras);
////////////////////////////////
//~ rjf: Evaluation Spaces
@@ -1183,7 +1181,6 @@ internal RD_VocabInfo *rd_vocab_info_from_code_name_plural(String8 code_name_plu
#define rd_display_plural_from_code_name(code_name) (rd_vocab_info_from_code_name(code_name)->display_name_plural)
#define rd_icon_kind_from_code_name(code_name) (rd_vocab_info_from_code_name(code_name)->icon_kind)
#define rd_singular_from_code_name_plural(code_name_plural) (rd_vocab_info_from_code_name_plural(code_name_plural)->code_name)
internal DR_FStrList rd_title_fstrs_from_code_name(Arena *arena, String8 code_name);
////////////////////////////////
//~ rjf: Continuous Frame Requests
+13 -15
View File
@@ -1030,6 +1030,12 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
{
if(0){}
// rjf: lister rows
else if(rd_cfg_child_from_string(rd_cfg_from_id(rd_regs()->view), str8_lit("lister")) != &rd_nil_cfg)
{
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .flags = RD_WatchCellFlag_Button, .pct = 1.f);
}
// rjf: top-level cfg rows
else if(is_top_level && evalled_cfg != &rd_nil_cfg)
{
@@ -1116,16 +1122,9 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_top_palette()->text, ui_top_font_size()};
E_Type *type = e_type_from_key__cached(info.eval.type_key);
String8 file_path = e_string_from_id(info.eval.value.u64);
String8 file_name = str8_skip_last_slash(file_path);
DR_FStrList fstrs = rd_title_fstrs_from_file_path(arena, file_path);
if(str8_match(type->name, str8_lit("folder"), 0))
{
DR_FStrList fstrs = {0};
if(file_name.size)
{
dr_fstrs_push_new(arena, &fstrs, &params, rd_icon_kind_text_table[RD_IconKind_FolderClosedFilled], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_top_palette()->text_weak);
dr_fstrs_push_new(arena, &fstrs, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &fstrs, &params, file_name);
}
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr,
.flags = RD_WatchCellFlag_Button|RD_WatchCellFlag_IsNonCode,
.pct = 1.f,
@@ -1139,13 +1138,6 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
RD_Cfg *w_cfg = style->first;
F32 next_pct = 0;
#define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct)
DR_FStrList fstrs = {0};
if(file_name.size)
{
dr_fstrs_push_new(arena, &fstrs, &params, rd_icon_kind_text_table[RD_IconKind_FileOutline], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_top_palette()->text_weak);
dr_fstrs_push_new(arena, &fstrs, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &fstrs, &params, file_name);
}
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr,
.flags = RD_WatchCellFlag_Button|RD_WatchCellFlag_IsNonCode,
.default_pct = 0.35f,
@@ -1435,6 +1427,12 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla
String8 cmd_name = rd_cmd_kind_info_table[cmd_kind].string;
result.cmd_name = cmd_name;
}
else if(result.eval.space.kind == E_SpaceKind_FileSystem)
{
String8 file_path = e_string_from_id(result.eval.value.u64);
result.fstrs = rd_title_fstrs_from_file_path(arena, file_path);
result.flags |= RD_WatchCellFlag_Button;
}
}break;
case RD_WatchCellKind_Eval:
{
+567
View File
@@ -1,6 +1,573 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: UI Widgets: Fancy Title Strings
internal DR_FStrList
rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg)
{
DR_FStrList result = {0};
{
Temp scratch = scratch_begin(&arena, 1);
//- rjf: unpack config
B32 is_disabled = rd_disabled_from_cfg(cfg);
RD_Location loc = rd_location_from_cfg(cfg);
D_Target target = rd_target_from_cfg(scratch.arena, cfg);
String8 label_string = rd_label_from_cfg(cfg);
String8 expr_string = rd_expr_from_cfg(cfg);
String8 collection_name = {0};
String8 file_path = {0};
Vec4F32 rgba = rd_color_from_cfg(cfg);
if(rgba.w == 0)
{
rgba = ui_color_from_name(str8_lit("text"));
}
Vec4F32 rgba_secondary = rgba;
UI_TagF("weak")
{
rgba_secondary = ui_color_from_name(str8_lit("text"));
}
RD_IconKind icon_kind = rd_icon_kind_from_code_name(cfg->string);
B32 is_from_command_line = 0;
{
RD_Cfg *cmd_line_root = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("command_line"));
for(RD_Cfg *p = cfg->parent; p != &rd_nil_cfg; p = p->parent)
{
if(p == cmd_line_root)
{
is_from_command_line = 1;
break;
}
}
}
B32 is_within_window = 0;
{
for(RD_Cfg *p = cfg->parent; p != &rd_nil_cfg; p = p->parent)
{
if(str8_match(p->string, str8_lit("window"), 0))
{
is_within_window = 1;
break;
}
}
}
if(expr_string.size != 0)
{
String8 query_name = rd_query_from_eval_string(arena, expr_string);
if(query_name.size != 0 && !str8_match(query_name, str8_lit("watches"), 0))
{
String8 query_code_name = query_name;
String8 query_display_name = rd_display_from_code_name(query_code_name);
collection_name = query_display_name;
if(query_display_name.size == 0)
{
query_code_name = rd_singular_from_code_name_plural(query_name);
collection_name = rd_display_plural_from_code_name(query_code_name);
}
RD_IconKind query_icon_kind = rd_icon_kind_from_code_name(query_code_name);
if(query_icon_kind != RD_IconKind_Null)
{
icon_kind = query_icon_kind;
}
}
else
{
file_path = rd_file_path_from_eval_string(arena, expr_string);
if(file_path.size != 0)
{
icon_kind = RD_IconKind_FileOutline;
}
}
}
//- rjf: set up color/size for all parts of the title
//
// the "running" part implies that it changes as things are added -
// so if a primary title is pushed, we can make the rest of the title
// more faded/smaller, but only after a primary title is pushed,
// which could be caused by many different potential parts of a cfg.
//
DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), rgba, ui_top_font_size()};
B32 running_is_secondary = 0;
#define start_secondary() if(!running_is_secondary){running_is_secondary = 1; params.color = rgba_secondary; params.size = ui_top_font_size()*0.95f;}
//- rjf: push icon
if(icon_kind != RD_IconKind_Null)
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rgba_secondary);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push warning icon for command-line entities
if(is_from_command_line)
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[RD_IconKind_Info], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rgba_secondary);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push view title, if from window, and no file path
if(is_within_window && file_path.size == 0 && collection_name.size == 0)
{
String8 view_display_name = rd_display_from_code_name(cfg->string);
if(view_display_name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, view_display_name);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
}
//- rjf: push label
if(label_string.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, label_string, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: push collection name
if(collection_name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, collection_name);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: query is file path - do specific file name strings
else if(file_path.size != 0)
{
// rjf: compute disambiguated file name
String8List qualifiers = {0};
String8 file_name = str8_skip_last_slash(file_path);
if(rd_state->ambiguous_path_slots_count != 0)
{
U64 hash = d_hash_from_string__case_insensitive(file_name);
U64 slot_idx = hash%rd_state->ambiguous_path_slots_count;
RD_AmbiguousPathNode *node = 0;
{
for(RD_AmbiguousPathNode *n = rd_state->ambiguous_path_slots[slot_idx];
n != 0;
n = n->next)
{
if(str8_match(n->name, file_name, StringMatchFlag_CaseInsensitive))
{
node = n;
break;
}
}
}
if(node != 0 && node->paths.node_count > 1)
{
// rjf: get all colliding paths
String8Array collisions = str8_array_from_list(scratch.arena, &node->paths);
// rjf: get all reversed path parts for each collision
String8List *collision_parts_reversed = push_array(scratch.arena, String8List, collisions.count);
for EachIndex(idx, collisions.count)
{
String8List parts = str8_split_path(scratch.arena, collisions.v[idx]);
for(String8Node *n = parts.first; n != 0; n = n->next)
{
str8_list_push_front(scratch.arena, &collision_parts_reversed[idx], n->string);
}
}
// rjf: get the search path & its reversed parts
String8List parts = str8_split_path(scratch.arena, file_path);
String8List parts_reversed = {0};
for(String8Node *n = parts.first; n != 0; n = n->next)
{
str8_list_push_front(scratch.arena, &parts_reversed, n->string);
}
// rjf: iterate all collision part reversed lists, in lock-step with
// search path; disqualify until we only have one path remaining; gather
// qualifiers
{
U64 num_collisions_left = collisions.count;
String8Node **collision_nodes = push_array(scratch.arena, String8Node *, collisions.count);
for EachIndex(idx, collisions.count)
{
collision_nodes[idx] = collision_parts_reversed[idx].first;
}
for(String8Node *n = parts_reversed.first; num_collisions_left > 1 && n != 0; n = n->next)
{
B32 part_is_qualifier = 0;
for EachIndex(idx, collisions.count)
{
if(collision_nodes[idx] != 0 && !str8_match(collision_nodes[idx]->string, n->string, StringMatchFlag_CaseInsensitive))
{
collision_nodes[idx] = 0;
num_collisions_left -= 1;
part_is_qualifier = 1;
}
else if(collision_nodes[idx] != 0)
{
collision_nodes[idx] = collision_nodes[idx]->next;
}
}
if(part_is_qualifier)
{
str8_list_push_front(scratch.arena, &qualifiers, n->string);
}
}
}
}
}
// rjf: push qualifiers
for(String8Node *n = qualifiers.first; n != 0; n = n->next)
{
String8 string = push_str8f(arena, "<%S> ", n->string);
dr_fstrs_push_new(arena, &result, &params, string, .color = ui_top_palette()->text_weak);
}
// rjf: push file name
dr_fstrs_push_new(arena, &result, &params, push_str8_copy(arena, str8_skip_last_slash(file_path)));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: cfg has expression attached -> use that
else if(expr_string.size != 0 && !str8_match(cfg->string, str8_lit("watch"), 0))
{
dr_fstrs_push_new(arena, &result, &params, expr_string, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: push text location
if(loc.file_path.size != 0)
{
String8 location_string = push_str8f(arena, "%S:%I64d:%I64d", str8_skip_last_slash(loc.file_path), loc.pt.line, loc.pt.column);
dr_fstrs_push_new(arena, &result, &params, location_string);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: push target executable name
if(target.exe.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, str8_skip_last_slash(target.exe));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
start_secondary();
}
//- rjf: push target arguments
if(target.args.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, target.args);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push conditions
{
String8 condition = rd_cfg_child_from_string(cfg, str8_lit("condition"))->first->string;
if(condition.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit("if "), .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code));
RD_Font(RD_FontSlot_Code)
{
DR_FStrList fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, params.color, condition);
dr_fstrs_concat_in_place(&result, &fstrs);
}
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
}
//- rjf: push disabled marker
if(is_disabled)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit("(Disabled)"));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push hit count
{
String8 hit_count_value_string = rd_cfg_child_from_string(cfg, str8_lit("hit_count"))->first->string;
U64 hit_count = 0;
if(try_u64_from_str8_c_rules(hit_count_value_string, &hit_count))
{
String8 hit_count_text = push_str8f(arena, "(%I64u hit%s)", hit_count, hit_count == 1 ? "" : "s");
dr_fstrs_push_new(arena, &result, &params, hit_count_text);
}
}
//- rjf: special case: auto view rule
if(str8_match(cfg->string, str8_lit("auto_view_rule"), 0))
{
String8 src_string = rd_cfg_child_from_string(cfg, str8_lit("source"))->first->string;
String8 dst_string = rd_cfg_child_from_string(cfg, str8_lit("dest"))->first->string;
Vec4F32 src_color = rgba;
Vec4F32 dst_color = rgba;
DR_FStrList src_fstrs = {0};
DR_FStrList dst_fstrs = {0};
if(src_string.size == 0)
{
src_string = str8_lit("(type)");
src_color = ui_top_palette()->text_weak;
dr_fstrs_push_new(arena, &src_fstrs, &params, src_string, .color = src_color);
}
else RD_Font(RD_FontSlot_Code)
{
src_fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, src_color, src_string);
}
if(dst_string.size == 0)
{
dst_string = str8_lit("(view rule)");
dst_color = ui_top_palette()->text_weak;
dr_fstrs_push_new(arena, &dst_fstrs, &params, dst_string, .color = dst_color);
}
else RD_Font(RD_FontSlot_Code)
{
dst_fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, dst_color, dst_string);
}
dr_fstrs_concat_in_place(&result, &src_fstrs);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[RD_IconKind_RightArrow], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_top_palette()->text_weak);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_concat_in_place(&result, &dst_fstrs);
}
//- rjf: special case: file path maps
if(str8_match(cfg->string, str8_lit("file_path_map"), 0))
{
String8 src_string = rd_cfg_child_from_string(cfg, str8_lit("source"))->first->string;
String8 dst_string = rd_cfg_child_from_string(cfg, str8_lit("dest"))->first->string;
Vec4F32 src_color = rgba;
Vec4F32 dst_color = rgba;
if(src_string.size == 0)
{
src_string = str8_lit("(source path)");
src_color = ui_top_palette()->text_weak;
}
if(dst_string.size == 0)
{
dst_string = str8_lit("(destination path)");
dst_color = ui_top_palette()->text_weak;
}
dr_fstrs_push_new(arena, &result, &params, src_string, .color = src_color);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[RD_IconKind_RightArrow], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_top_palette()->text_weak);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, dst_string, .color = dst_color);
}
#undef start_secondary
scratch_end(scratch);
}
return result;
}
internal DR_FStrList
rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_extras)
{
DR_FStrList result = {0};
//- rjf: unpack entity info
F32 extras_size = ui_top_font_size()*0.95f;
Vec4F32 color = rd_color_from_ctrl_entity(entity);
if(color.w == 0)
{
color = ui_top_palette()->text;
}
Vec4F32 secondary_color = ui_top_palette()->text_weak;
String8 name = rd_name_from_ctrl_entity(arena, entity);
RD_IconKind icon_kind = RD_IconKind_Null;
B32 name_is_code = 0;
switch(entity->kind)
{
default:{}break;
case CTRL_EntityKind_Machine: {icon_kind = RD_IconKind_Machine;}break;
case CTRL_EntityKind_Process: {icon_kind = RD_IconKind_Threads;}break;
case CTRL_EntityKind_Thread: {icon_kind = RD_IconKind_Thread; name_is_code = 1;}break;
case CTRL_EntityKind_Module: {icon_kind = RD_IconKind_Module;}break;
}
//- rjf: set up drawing params
DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Code), rd_raster_flags_from_slot(RD_FontSlot_Code), color, ui_top_font_size()};
//- rjf: push icon
if(icon_kind != RD_IconKind_Null)
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = secondary_color);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push frozen icon, if frozen
if((entity->kind == CTRL_EntityKind_Machine ||
entity->kind == CTRL_EntityKind_Process ||
entity->kind == CTRL_EntityKind_Thread) &&
ctrl_entity_tree_is_frozen(entity))
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[RD_IconKind_Locked], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_top_palette()->background_bad);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push containing process prefix
if(entity->kind == CTRL_EntityKind_Thread ||
entity->kind == CTRL_EntityKind_Module)
{
CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process);
if(processes.count > 1)
{
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process);
String8 process_name = rd_name_from_ctrl_entity(arena, process);
Vec4F32 process_color = rd_color_from_ctrl_entity(process);
if(process_color.w == 0)
{
process_color = color;
}
if(process_name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, process_name, .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = process_color);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, push_str8f(arena, "(PID: %I64u)", process->id), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = secondary_color, .size = ui_top_font_size()*0.9f);
dr_fstrs_push_new(arena, &result, &params, str8_lit(" / "), .color = secondary_color);
}
}
}
//- rjf: push name
dr_fstrs_push_new(arena, &result, &params, name,
.font = rd_font_from_slot(name_is_code ? RD_FontSlot_Code : RD_FontSlot_Main),
.raster_flags = rd_raster_flags_from_slot(name_is_code ? RD_FontSlot_Code : RD_FontSlot_Main),
.color = color);
//- rjf: push PID
if(entity->kind == CTRL_EntityKind_Process)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, push_str8f(arena, " (PID: %I64u)", entity->id), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = secondary_color, .size = ui_top_font_size()*0.85f);
}
//- rjf: threads get callstack extras
if(entity->kind == CTRL_EntityKind_Thread && include_extras)
{
Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol"));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
DI_Scope *di_scope = di_scope_open();
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process);
Arch arch = entity->arch;
CTRL_Unwind unwind = d_query_cached_unwind_from_thread(entity);
for(U64 idx = 0, limit = 6; idx < unwind.frames.count && idx < limit; idx += 1)
{
CTRL_UnwindFrame *f = &unwind.frames.v[unwind.frames.count - 1 - idx];
U64 rip_vaddr = regs_rip_from_arch_block(arch, f->regs);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
if(rdi != &di_rdi_parsed_nil)
{
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, rip_voff);
String8 name = {0};
name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size);
name = push_str8_copy(arena, name);
if(name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, name, .size = extras_size, .color = symbol_color);
if(idx+1 < unwind.frames.count)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit(" > "), .color = secondary_color, .size = extras_size);
if(idx+1 == limit)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit("..."), .color = secondary_color, .size = extras_size);
}
}
}
}
}
di_scope_close(di_scope);
}
//- rjf: modules get debug info status extras
if(entity->kind == CTRL_EntityKind_Module && include_extras)
{
DI_Scope *di_scope = di_scope_open();
DI_Key dbgi_key = ctrl_dbgi_key_from_module(entity);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
if(rdi->raw_data_size == 0)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &result, &params, str8_lit("(Symbols not found)"), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .size = extras_size, .color = secondary_color);
}
di_scope_close(di_scope);
}
return result;
}
internal DR_FStrList
rd_title_fstrs_from_code_name(Arena *arena, String8 code_name)
{
DR_FStrList result = {0};
{
RD_VocabInfo *info = rd_vocab_info_from_code_name(code_name);
//- rjf: set up color/size for all parts of the title
//
// the "running" part implies that it changes as things are added -
// so if a primary title is pushed, we can make the rest of the title
// more faded/smaller, but only after a primary title is pushed,
// which could be caused by many different potential parts of a cfg.
//
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")), ui_top_font_size()};
//- rjf: push icon
if(info->icon_kind != RD_IconKind_Null) UI_Tag(str8_lit("weak"))
{
dr_fstrs_push_new(arena, &result, &params, rd_icon_kind_text_table[info->icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text")));
dr_fstrs_push_new(arena, &result, &params, str8_lit(" "));
}
//- rjf: push display name
if(info->display_name.size != 0)
{
dr_fstrs_push_new(arena, &result, &params, info->display_name);
}
//- rjf: push code name as a fallback
else
{
dr_fstrs_push_new(arena, &result, &params, code_name, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code));
}
}
return result;
}
internal DR_FStrList
rd_title_fstrs_from_file_path(Arena *arena, String8 file_path)
{
DR_FStrList fstrs = {0};
String8 file_name = str8_skip_last_slash(file_path);
FileProperties props = os_properties_from_file_path(file_path);
RD_IconKind icon_kind = RD_IconKind_FileOutline;
if(props.flags & FilePropertyFlag_IsFolder)
{
icon_kind = RD_IconKind_FolderClosedFilled;
}
if(file_path.size == 0 || str8_match(file_path, str8_lit("/"), StringMatchFlag_SlashInsensitive))
{
icon_kind = RD_IconKind_Machine;
file_name = str8_lit("File System");
}
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")), ui_top_font_size()};
UI_TagF("weak")
{
dr_fstrs_push_new(arena, &fstrs, &params,
rd_icon_kind_text_table[icon_kind],
.font = rd_font_from_slot(RD_FontSlot_Icons),
.raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons),
.color = ui_color_from_name(str8_lit("text")));
}
dr_fstrs_push_new(arena, &fstrs, &params, str8_lit(" "));
dr_fstrs_push_new(arena, &fstrs, &params, file_name);
return fstrs;
}
////////////////////////////////
//~ rjf: UI Widgets: Loading Overlay
+8
View File
@@ -95,6 +95,14 @@ struct RD_CodeSliceSignal
#define RD_Palette(code) UI_Palette(rd_palette_from_code(code))
#define RD_Font(slot) UI_Font(rd_font_from_slot(slot)) UI_TextRasterFlags(rd_raster_flags_from_slot((slot)))
////////////////////////////////
//~ rjf: UI Widgets: Fancy Title Strings
internal DR_FStrList rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg);
internal DR_FStrList rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_extras);
internal DR_FStrList rd_title_fstrs_from_code_name(Arena *arena, String8 code_name);
internal DR_FStrList rd_title_fstrs_from_file_path(Arena *arena, String8 file_path);
////////////////////////////////
//~ rjf: UI Widgets: Loading Overlay