diff --git a/custom/4coder_default_bindings.cpp b/custom/4coder_default_bindings.cpp index d6ed0aa4..c7979ffe 100644 --- a/custom/4coder_default_bindings.cpp +++ b/custom/4coder_default_bindings.cpp @@ -21,7 +21,6 @@ custom_layer_init(Application_Links *app){ Thread_Context *tctx = get_thread_context(app); mapping_init(tctx, &framework_mapping); setup_default_mapping(&framework_mapping); - fill_log_graph_command_map(&framework_mapping); } #endif //NO_BINDING diff --git a/custom/4coder_default_framework_variables.cpp b/custom/4coder_default_framework_variables.cpp index a17e7d70..da89ceee 100644 --- a/custom/4coder_default_framework_variables.cpp +++ b/custom/4coder_default_framework_variables.cpp @@ -84,7 +84,6 @@ enum{ mapid_file, default_code_map, default_lister_ui_map, - default_log_graph_map, default_maps_count, }; diff --git a/custom/4coder_log_parser.cpp b/custom/4coder_log_parser.cpp index 081b4924..e547c666 100644 --- a/custom/4coder_log_parser.cpp +++ b/custom/4coder_log_parser.cpp @@ -1,1054 +1,1080 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 14.08.2019 - * - * Log parser. - * - */ - -// TOP - -internal u64 -log_parse__string_code(Log_Parse *parse, String_Const_u8 string, Log_String_Source string_source){ - u64 result = 0; - if (string.size > 0){ - Data data = make_data(string.str, string.size); - Table_Lookup lookup = table_lookup(&parse->string_to_id_table, data); - if (lookup.found_match){ - table_read(&parse->string_to_id_table, lookup, &result); - } - else{ - if (string_source == LogParse_ExternalString){ - data = push_data_copy(parse->arena, data); - } - result = parse->string_id_counter; - parse->string_id_counter += 1; - table_insert(&parse->string_to_id_table, data, result); - table_insert(&parse->id_to_string_table, result, data); - } - } - return(result); -} - -internal String_Const_u8 -log_parse__get_string(Log_Parse *parse, u64 code){ - Table_Lookup lookup = table_lookup(&parse->id_to_string_table, code); - String_Const_u8 result = {}; - if (lookup.found_match){ - Data val = {}; - table_read(&parse->id_to_string_table, lookup, &val); - result = SCu8(val.data, val.size); - } - return(result); -} - -internal Log_Event* -log_parse__event(Log_Parse *parse, - String_Const_u8 file_name, String_Const_u8 line_number, String_Const_u8 event_name){ - Log_Event *new_event = push_array(parse->arena, Log_Event, 1); - sll_queue_push(parse->first_event, parse->last_event, new_event); - parse->event_count += 1; - new_event->src_file_name = log_parse__string_code(parse, file_name, LogParse_ExternalString); - new_event->event_name = log_parse__string_code(parse, event_name, LogParse_ExternalString); - new_event->line_number = string_to_integer(line_number, 10); - new_event->event_number = parse->event_count; - return(new_event); -} - -internal Log_Tag* -log_parse__tag(Log_Parse *parse, Log_Event *event, String_Const_u8 tag_name, String_Const_u8 tag_value){ - Log_Tag *new_tag = push_array(parse->arena, Log_Tag, 1); - sll_queue_push(event->first_tag, event->last_tag, new_tag); - event->tag_count += 1; - new_tag->name = log_parse__string_code(parse, tag_name, LogParse_ExternalString); - if (tag_value.size == 0){ - new_tag->value.kind = LogTagKind_String; - new_tag->value.value = 0; - } - else{ - if (tag_value.str[0] == '"'){ - if (tag_value.size == 1){ - new_tag->value.kind = LogTagKind_String; - new_tag->value.value = 0; - } - else{ - tag_value = string_skip(tag_value, 1); - if (tag_value.str[tag_value.size - 1] == '"'){ - tag_value = string_chop(tag_value, 1); - } - String_Const_u8 escape = string_interpret_escapes(parse->arena, tag_value); - new_tag->value.kind = LogTagKind_String; - new_tag->value.value = log_parse__string_code(parse, escape, LogParse_PreAllocatedString); - } - } - else{ - new_tag->value.kind = LogTagKind_Integer; - b32 is_negative = false; - if (string_match(string_prefix(tag_value, 1), string_u8_litexpr("-"))){ - tag_value = string_skip(tag_value, 1); - is_negative = true; - } - if (string_match(string_prefix(tag_value, 2), string_u8_litexpr("0x"))){ - tag_value = string_skip(tag_value, 2); - new_tag->value.value_s = (i64)string_to_integer(tag_value, 16); - } - else{ - new_tag->value.value_s = (i64)string_to_integer(tag_value, 10); - } - if (is_negative){ - new_tag->value.value_s = -new_tag->value.value_s; - } - } - } - return(new_tag); -} - -internal Log_Event_List* -log_parse_get_list_tag_value(Log_Parse *parse, u64 name, Log_Tag_Value value){ - Log_Event_List *result = 0; - Log_Tag_Name_Value key = {name, value}; - Table_Lookup lookup = table_lookup(&parse->tag_value_to_event_list_table, make_data_struct(&key)); - if (lookup.found_match){ - u64 val = 0; - table_read(&parse->tag_value_to_event_list_table, lookup, &val); - result = (Log_Event_List*)IntAsPtr(val); - } - return(result); -} - -internal Log_Event_List* -log_parse__get_or_make_list_tag_value(Log_Parse *parse, Log_Tag *tag){ - Log_Event_List *result = 0; - Log_Tag_Name_Value key = {tag->name, tag->value}; - Data data_key = make_data_struct(&key); - Table_Lookup lookup = table_lookup(&parse->tag_value_to_event_list_table, data_key); - if (lookup.found_match){ - u64 val = 0; - table_read(&parse->tag_value_to_event_list_table, lookup, &val); - result = (Log_Event_List*)IntAsPtr(val); - } - else{ - result = push_array_zero(parse->arena, Log_Event_List, 1); - table_insert(&parse->tag_value_to_event_list_table, push_data_copy(parse->arena, data_key), - (u64)PtrAsInt(result)); - } - return(result); -} - -internal Log_Event_List* -log_parse_get_list_tag_name(Log_Parse *parse, u64 name){ - Log_Event_List *result = 0; - Table_Lookup lookup = table_lookup(&parse->tag_name_to_event_list_table, name); - if (lookup.found_match){ - u64 val = 0; - table_read(&parse->tag_name_to_event_list_table, lookup, &val); - result = (Log_Event_List*)IntAsPtr(val); - } - return(result); -} - -internal Log_Event_List* -log_parse__get_or_make_list_tag_name(Log_Parse *parse, Log_Tag *tag){ - Log_Event_List *result = 0; - Table_Lookup lookup = table_lookup(&parse->tag_name_to_event_list_table, tag->name); - if (lookup.found_match){ - u64 val = 0; - table_read(&parse->tag_name_to_event_list_table, lookup, &val); - result = (Log_Event_List*)IntAsPtr(val); - } - else{ - result = push_array_zero(parse->arena, Log_Event_List, 1); - table_insert(&parse->tag_name_to_event_list_table, tag->name, (u64)PtrAsInt(result)); - } - return(result); -} - -internal Log_Parse -make_log_parse(Arena *arena, String_Const_u8 source){ - Log_Parse parse = {}; - parse.arena = arena; - parse.string_id_counter = 1; - parse.string_to_id_table = make_table_Data_u64(arena->base_allocator, 500); - parse.id_to_string_table = make_table_u64_Data(arena->base_allocator, 500); - - for (;source.size > 0;){ - umem end_of_line = string_find_first(source, '\n'); - String_Const_u8 line = string_prefix(source, end_of_line); - line = string_skip_chop_whitespace(line); - source = string_skip(source, end_of_line + 1); - - String_Const_u8 src_file_name = {}; - String_Const_u8 src_line_number = {}; - b32 got_source_position = false; - - String_Const_u8 whole_line = line; - - { - umem colon1 = string_find_first(line, ':'); - src_file_name = string_prefix(line, colon1); - line = string_skip(line, colon1 + 1); +/* + * Mr. 4th Dimention - Allen Webster + * + * 14.08.2019 + * + * Log parser. + * + */ + +// TOP + +internal u64 +log_parse__string_code(Log_Parse *parse, String_Const_u8 string, Log_String_Source string_source){ + u64 result = 0; + if (string.size > 0){ + Data data = make_data(string.str, string.size); + Table_Lookup lookup = table_lookup(&parse->string_to_id_table, data); + if (lookup.found_match){ + table_read(&parse->string_to_id_table, lookup, &result); + } + else{ + if (string_source == LogParse_ExternalString){ + data = push_data_copy(parse->arena, data); + } + result = parse->string_id_counter; + parse->string_id_counter += 1; + table_insert(&parse->string_to_id_table, data, result); + table_insert(&parse->id_to_string_table, result, data); + } + } + return(result); +} + +internal String_Const_u8 +log_parse__get_string(Log_Parse *parse, u64 code){ + Table_Lookup lookup = table_lookup(&parse->id_to_string_table, code); + String_Const_u8 result = {}; + if (lookup.found_match){ + Data val = {}; + table_read(&parse->id_to_string_table, lookup, &val); + result = SCu8(val.data, val.size); + } + return(result); +} + +internal Log_Event* +log_parse__event(Log_Parse *parse, + String_Const_u8 file_name, String_Const_u8 line_number, String_Const_u8 event_name){ + Log_Event *new_event = push_array(parse->arena, Log_Event, 1); + sll_queue_push(parse->first_event, parse->last_event, new_event); + parse->event_count += 1; + new_event->src_file_name = log_parse__string_code(parse, file_name, LogParse_ExternalString); + new_event->event_name = log_parse__string_code(parse, event_name, LogParse_ExternalString); + new_event->line_number = string_to_integer(line_number, 10); + new_event->event_number = parse->event_count; + return(new_event); +} + +internal Log_Tag* +log_parse__tag(Log_Parse *parse, Log_Event *event, String_Const_u8 tag_name, String_Const_u8 tag_value){ + Log_Tag *new_tag = push_array(parse->arena, Log_Tag, 1); + sll_queue_push(event->first_tag, event->last_tag, new_tag); + event->tag_count += 1; + new_tag->name = log_parse__string_code(parse, tag_name, LogParse_ExternalString); + if (tag_value.size == 0){ + new_tag->value.kind = LogTagKind_String; + new_tag->value.value = 0; + } + else{ + if (tag_value.str[0] == '"'){ + if (tag_value.size == 1){ + new_tag->value.kind = LogTagKind_String; + new_tag->value.value = 0; + } + else{ + tag_value = string_skip(tag_value, 1); + if (tag_value.str[tag_value.size - 1] == '"'){ + tag_value = string_chop(tag_value, 1); + } + String_Const_u8 escape = string_interpret_escapes(parse->arena, tag_value); + new_tag->value.kind = LogTagKind_String; + new_tag->value.value = log_parse__string_code(parse, escape, LogParse_PreAllocatedString); + } + } + else{ + new_tag->value.kind = LogTagKind_Integer; + b32 is_negative = false; + if (string_match(string_prefix(tag_value, 1), string_u8_litexpr("-"))){ + tag_value = string_skip(tag_value, 1); + is_negative = true; + } + if (string_match(string_prefix(tag_value, 2), string_u8_litexpr("0x"))){ + tag_value = string_skip(tag_value, 2); + new_tag->value.value_s = (i64)string_to_integer(tag_value, 16); + } + else{ + new_tag->value.value_s = (i64)string_to_integer(tag_value, 10); + } + if (is_negative){ + new_tag->value.value_s = -new_tag->value.value_s; + } + } + } + return(new_tag); +} + +internal Log_Event_List* +log_parse_get_list_tag_value(Log_Parse *parse, u64 name, Log_Tag_Value value){ + Log_Event_List *result = 0; + Log_Tag_Name_Value key = {name, value}; + Table_Lookup lookup = table_lookup(&parse->tag_value_to_event_list_table, make_data_struct(&key)); + if (lookup.found_match){ + u64 val = 0; + table_read(&parse->tag_value_to_event_list_table, lookup, &val); + result = (Log_Event_List*)IntAsPtr(val); + } + return(result); +} + +internal Log_Event_List* +log_parse__get_or_make_list_tag_value(Log_Parse *parse, Log_Tag *tag){ + Log_Event_List *result = 0; + Log_Tag_Name_Value key = {tag->name, tag->value}; + Data data_key = make_data_struct(&key); + Table_Lookup lookup = table_lookup(&parse->tag_value_to_event_list_table, data_key); + if (lookup.found_match){ + u64 val = 0; + table_read(&parse->tag_value_to_event_list_table, lookup, &val); + result = (Log_Event_List*)IntAsPtr(val); + } + else{ + result = push_array_zero(parse->arena, Log_Event_List, 1); + table_insert(&parse->tag_value_to_event_list_table, push_data_copy(parse->arena, data_key), + (u64)PtrAsInt(result)); + } + return(result); +} + +internal Log_Event_List* +log_parse_get_list_tag_name(Log_Parse *parse, u64 name){ + Log_Event_List *result = 0; + Table_Lookup lookup = table_lookup(&parse->tag_name_to_event_list_table, name); + if (lookup.found_match){ + u64 val = 0; + table_read(&parse->tag_name_to_event_list_table, lookup, &val); + result = (Log_Event_List*)IntAsPtr(val); + } + return(result); +} + +internal Log_Event_List* +log_parse__get_or_make_list_tag_name(Log_Parse *parse, Log_Tag *tag){ + Log_Event_List *result = 0; + Table_Lookup lookup = table_lookup(&parse->tag_name_to_event_list_table, tag->name); + if (lookup.found_match){ + u64 val = 0; + table_read(&parse->tag_name_to_event_list_table, lookup, &val); + result = (Log_Event_List*)IntAsPtr(val); + } + else{ + result = push_array_zero(parse->arena, Log_Event_List, 1); + table_insert(&parse->tag_name_to_event_list_table, tag->name, (u64)PtrAsInt(result)); + } + return(result); +} + +internal Log_Parse +make_log_parse(Arena *arena, String_Const_u8 source){ + Log_Parse parse = {}; + parse.arena = arena; + parse.string_id_counter = 1; + parse.string_to_id_table = make_table_Data_u64(arena->base_allocator, 500); + parse.id_to_string_table = make_table_u64_Data(arena->base_allocator, 500); + + for (;source.size > 0;){ + umem end_of_line = string_find_first(source, '\n'); + String_Const_u8 line = string_prefix(source, end_of_line); + line = string_skip_chop_whitespace(line); + source = string_skip(source, end_of_line + 1); + + String_Const_u8 src_file_name = {}; + String_Const_u8 src_line_number = {}; + b32 got_source_position = false; + + String_Const_u8 whole_line = line; + + { + umem colon1 = string_find_first(line, ':'); + src_file_name = string_prefix(line, colon1); + line = string_skip(line, colon1 + 1); + + umem colon2 = string_find_first(line, ':'); + src_line_number = string_prefix(line, colon2); + line = string_skip(line, colon2 + 1); + + if (string_is_integer(src_line_number, 10)){ + got_source_position = true; + } + } + + if (!got_source_position){ + line = whole_line; + + umem colon0 = string_find_first(line, ':'); + umem colon1 = string_find_first(line, colon0 + 1, ':'); + src_file_name = string_prefix(line, colon1); + line = string_skip(line, colon1 + 1); + + umem colon2 = string_find_first(line, ':'); + src_line_number = string_prefix(line, colon2); + line = string_skip(line, colon2 + 1); + + if (string_is_integer(src_line_number, 10)){ + got_source_position = true; + } + } + + if (got_source_position){ + umem bracket_open = string_find_first(line, '['); + String_Const_u8 event_name = string_prefix(line, bracket_open); + event_name = string_skip_chop_whitespace(event_name); + line = string_skip(line, bracket_open + 1); + + Log_Event *event = log_parse__event(&parse, + src_file_name, src_line_number, event_name); + + for (;line.size > 0;){ + umem bracket_close = string_find_first(line, ']'); + String_Const_u8 tag = string_prefix(line, bracket_close); + line = string_skip(line, bracket_close + 1); + bracket_open = string_find_first(line, '['); + line = string_skip(line, bracket_open + 1); + + umem equal_sign = string_find_first(tag, '='); + String_Const_u8 tag_name = string_prefix(tag, equal_sign); + String_Const_u8 tag_contents = string_skip(tag, equal_sign + 1); + + log_parse__tag(&parse, event, tag_name, tag_contents); + } + } + } + + //////////////////////////////// + + // NOTE(allen): fill acceleration structures + + parse.tag_value_to_event_list_table = make_table_Data_u64(arena->base_allocator, Thousand(1)); + parse.tag_name_to_event_list_table = make_table_u64_u64(arena->base_allocator, 100); + + for (Log_Event *event = parse.first_event; + event != 0; + event = event->next){ + for (Log_Tag *tag = event->first_tag; + tag != 0; + tag = tag->next){ + { + Log_Event_List *list = log_parse__get_or_make_list_tag_value(&parse, tag); + Log_Event_Ptr_Node *node = push_array(arena, Log_Event_Ptr_Node, 1); + sll_queue_push(list->first, list->last, node); + list->count += 1; + node->event = event; + } + { + Log_Event_List *list = log_parse__get_or_make_list_tag_name(&parse, tag); + Log_Event_Ptr_Node *node = push_array(arena, Log_Event_Ptr_Node, 1); + sll_queue_push(list->first, list->last, node); + list->count += 1; + node->event = event; + } + } + } + + for (Log_Event *event = parse.first_event; + event != 0; + event = event->next){ + i32 slot_count = event->tag_count*3/2; + event->tag_name_to_tag_ptr_table = make_table_u64_u64(arena->base_allocator, slot_count); + for (Log_Tag *tag = event->first_tag; + tag != 0; + tag = tag->next){ + table_insert(&event->tag_name_to_tag_ptr_table, tag->name, (u64)PtrAsInt(tag)); + } + } + + return(parse); +} + +//////////////////////////////// + +internal void +log_events_sort_by_tag__inner(Log_Event **events, Log_Sort_Key *keys, i32 first, i32 one_past_last){ + if (first + 1 < one_past_last){ + i32 pivot_index = one_past_last - 1; + Log_Sort_Key *pivot_key = keys + pivot_index; + i32 j = first; + for (i32 i = first; i < one_past_last; i += 1){ + Log_Sort_Key *key = keys + i; + b32 key_is_less_than_pivot_key = false; + if (key->value.kind < pivot_key->value.kind){ + key_is_less_than_pivot_key = true; + } + else if (key->value.kind == pivot_key->value.kind){ + if (key->value.value < pivot_key->value.value){ + key_is_less_than_pivot_key = true; + } + else if (key->value.value == pivot_key->value.value){ + if (key->number < pivot_key->number){ + key_is_less_than_pivot_key = true; + } + } + } + if (key_is_less_than_pivot_key){ + if (j < i){ + Swap(Log_Event*, events[i], events[j]); + Swap(Log_Sort_Key, keys[i], keys[j]); + } + j += 1; + } + } + Swap(Log_Event*, events[pivot_index], events[j]); + Swap(Log_Sort_Key, keys[pivot_index], keys[j]); + log_events_sort_by_tag__inner(events, keys, first, j); + log_events_sort_by_tag__inner(events, keys, j + 1, one_past_last); + } +} + +internal void +log_events_sort_by_tag(Arena *scratch, Log_Event_Ptr_Array array, u64 tag_name){ + Temp_Memory temp = begin_temp(scratch); + Log_Sort_Key *keys = push_array(scratch, Log_Sort_Key, array.count); + for (i32 i = 0; i < array.count; i += 1){ + Log_Event *event = array.events[i]; + Table_Lookup lookup = table_lookup(&event->tag_name_to_tag_ptr_table, tag_name); + if (lookup.found_match){ + u64 read_val = 0; + table_read(&event->tag_name_to_tag_ptr_table, lookup, &read_val); + Log_Tag *tag = (Log_Tag*)IntAsPtr(read_val); + keys[i].value = tag->value; + } + else{ + keys[i].value.kind = LogTagKind_Null; + keys[i].value.value = 0; + } + keys[i].number = event->event_number; + } + + log_events_sort_by_tag__inner(array.events, keys, 0, array.count); + + end_temp(temp); +} + +internal Log_Event_Ptr_Array +log_event_array_from_list(Arena *arena, Log_Event_List list){ + Log_Event_Ptr_Array array = {}; + array.count = list.count; + array.events = push_array(arena, Log_Event*, array.count); + i32 counter = 0; + for (Log_Event_Ptr_Node *node = list.first; + node != 0; + node = node->next){ + array.events[counter] = node->event; + counter += 1; + } + return(array); +} + +//////////////////////////////// + +global View_ID log_view = 0; +global Arena *log_arena = {}; +global Log_Parse log_parse = {}; +global Log_Graph log_graph = {}; +global Log_Filter_Set log_filter_set = {}; +global Log_Filter_Set log_preview_set = {}; + +internal void +log_filter_set_init(Log_Filter_Set *set){ + block_zero_struct(set); + for (i32 i = ArrayCount(set->filters_memory) - 1; i >= 0; i -= 1){ + sll_stack_push(set->free_filters, &set->filters_memory[i]); + } +} + +internal Log_Filter_Set* +log_filter_set_from_tab(Log_Graph_List_Tab tab){ + Log_Filter_Set *result = 0; + switch (tab){ + case LogTab_Filters: + { + result = &log_filter_set; + }break; + case LogTab_Previews: + { + result = &log_preview_set; + }break; + } + return(result); +} + +internal Log_Filter* +log_filter_set__new_filter(Log_Filter_Set *set, Log_Filter *prototype){ + Log_Filter *result = set->free_filters; + if (result != 0){ + for (Log_Filter *filter = set->first; + filter != 0; + filter = filter->next){ + if (filter->kind == prototype->kind && + filter->tag_name_code == prototype->tag_name_code && + block_match_struct(&filter->tag_value, &prototype->tag_value)){ + result = 0; + break; + } + } + if (result != 0){ + sll_stack_pop(set->free_filters); + block_copy_struct(result, prototype); + zdll_push_back(set->first, set->last, result); + set->count += 1; + set->alter_counter += 1; + } + } + return(result); +} + +internal void +log_filter_set__free_filter(Log_Filter_Set *set, Log_Filter *filter){ + zdll_remove(set->first, set->last, filter); + set->count -= 1; + set->alter_counter += 1; + sll_stack_push(set->free_filters, filter); +} + +internal void +log_graph_fill(Application_Links *app, Rect_f32 layout_region, Face_ID face_id){ + if (log_parse.arena != 0){ + if (log_graph.holding_temp){ + end_temp(log_graph.temp); + } + block_zero_struct(&log_graph); + log_graph.holding_temp = true; + log_graph.temp = begin_temp(log_arena); + log_graph.layout_region = layout_region; + log_graph.face_id = face_id; + log_graph.filter_alter_counter = log_filter_set.alter_counter; + log_graph.preview_alter_counter = log_preview_set.alter_counter; + log_graph.tab = LogTab_Filters; + + f32 details_h = rect_height(layout_region)*.22f; + details_h = clamp_top(details_h, 250.f); + + Rect_f32 details_region = Rf32(layout_region.x0, layout_region.y0, + layout_region.x1, layout_region.y0 + details_h); + Rect_f32 event_list_region = Rf32(layout_region.x0, layout_region.y0 + details_h, + layout_region.x1, layout_region.y1); + + log_graph.details_region = details_region; + log_graph.details_region.p0 -= layout_region.p0; + log_graph.details_region.p1 -= layout_region.p0; + + u64 thread_code = log_parse__string_code(&log_parse, string_u8_litexpr("thread"), + LogParse_ExternalString); + + if (log_filter_set.count == 0){ + // NOTE(allen): everything goes into the filtered list + for (Log_Event *event = log_parse.first_event; + event != 0; + event = event->next){ + Log_Event_Ptr_Node *node = push_array(log_arena, Log_Event_Ptr_Node, 1); + node->event = event; + sll_queue_push(log_graph.filtered_list.first, log_graph.filtered_list.last, node); + log_graph.filtered_list.count += 1; + } + } + else{ + for (Log_Filter *filter = log_filter_set.first; + filter != 0; + filter = filter->next){ + Log_Event_List *filter_list = 0; + if (filter->kind == LogFilter_TagValue){ + filter_list = log_parse_get_list_tag_value(&log_parse, filter->tag_name_code, + filter->tag_value); + } + else if (filter->kind == LogFilter_Tag){ + filter_list = log_parse_get_list_tag_name(&log_parse, filter->tag_name_code); + } + + // NOTE(allen): combine with existing result + if (filter == log_filter_set.first){ + for (Log_Event_Ptr_Node *node = filter_list->first; + node != 0; + node = node->next){ + Log_Event_Ptr_Node *new_node = push_array(log_arena, Log_Event_Ptr_Node, 1); + new_node->event = node->event; + sll_queue_push(log_graph.filtered_list.first, log_graph.filtered_list.last, new_node); + log_graph.filtered_list.count += 1; + } + } + else{ + Log_Event_Ptr_Node **fixup_ptr = &log_graph.filtered_list.first; + log_graph.filtered_list.last = 0; + for (Log_Event_Ptr_Node *node_a = log_graph.filtered_list.first, *next = 0; + node_a != 0; + node_a = next){ + next = node_a->next; + + b32 remove_node_a = true; + for (Log_Event_Ptr_Node *node_b = filter_list->first; + node_b != 0; + node_b = node_b->next){ + if (node_a->event == node_b->event){ + remove_node_a = false; + break; + } + } + + if (remove_node_a){ + *fixup_ptr = next; + } + else{ + fixup_ptr = &node_a->next; + log_graph.filtered_list.last = node_a; + } + } + } + } + } + + log_graph.event_array = log_event_array_from_list(log_arena, + log_graph.filtered_list); + log_events_sort_by_tag(log_arena, log_graph.event_array, thread_code); + + b32 had_a_tag = true; + u64 thread_id_value = 0; + Log_Graph_Thread_Bucket *prev_bucket = 0; + + for (i32 i = 0; i < log_graph.event_array.count; i += 1){ + Table_u64_u64 *tag_table = &log_graph.event_array.events[i]->tag_name_to_tag_ptr_table; + Table_Lookup lookup = table_lookup(tag_table, thread_code); + + b32 emit_next_bucket = false; + if (!lookup.found_match){ + if (had_a_tag){ + had_a_tag = false; + thread_id_value = 0; + emit_next_bucket = true; + } + } + else{ + u64 read_val = 0; + table_read(tag_table, lookup, &read_val); + Log_Tag *tag = (Log_Tag*)IntAsPtr(read_val); + if (!had_a_tag){ + had_a_tag = true; + thread_id_value = tag->value.value; + emit_next_bucket = true; + } + else if (thread_id_value != tag->value.value){ + thread_id_value = tag->value.value; + emit_next_bucket = true; + } + } + + if (emit_next_bucket){ + Log_Graph_Thread_Bucket *bucket = push_array(log_arena, Log_Graph_Thread_Bucket, 1); + sll_queue_push(log_graph.first_bucket, log_graph.last_bucket, bucket); + log_graph.bucket_count += 1; + bucket->range.first = i; + bucket->had_a_tag = had_a_tag; + bucket->thread_id_value = thread_id_value; + if (prev_bucket != 0){ + prev_bucket->range.one_past_last = i; + } + prev_bucket = bucket; + } + } + if (prev_bucket != 0){ + prev_bucket->range.one_past_last = log_graph.event_array.count; + } + + Face_Metrics metrics = get_face_metrics(app, face_id); + f32 line_height = metrics.line_height; + f32 box_h = f32_floor32(line_height*1.5f); + f32 box_w = f32_floor32(rect_width(event_list_region)/log_graph.bucket_count); + f32 y_cursor = event_list_region.y0 - layout_region.y0; + + if (log_graph.bucket_count > 0){ + f32 y_bottom = 0.f; + + for (;;){ + i32 smallest_event_number = max_i32; + i32 bucket_with_next_event_index = -1; + Log_Graph_Thread_Bucket *bucket_with_next_event = 0; + Log_Event *next_event = 0; + i32 iteration_counter = 0; + for (Log_Graph_Thread_Bucket *bucket = log_graph.first_bucket; + bucket != 0; + bucket = bucket->next, iteration_counter += 1){ + if (bucket->range.first < bucket->range.one_past_last){ + Log_Event *event = log_graph.event_array.events[bucket->range.first]; + if (event->event_number < smallest_event_number){ + smallest_event_number = event->event_number; + bucket_with_next_event_index = iteration_counter; + bucket_with_next_event = bucket; + next_event = event; + } + } + } + + if (bucket_with_next_event == 0){ + break; + } + + bucket_with_next_event->range.first += 1; + + Log_Graph_Box *box_node = push_array(log_arena, Log_Graph_Box, 1); + sll_queue_push(log_graph.first_box, log_graph.last_box, box_node); + log_graph.box_count += 1; + Rect_f32 rect = Rf32(box_w*bucket_with_next_event_index , y_cursor, + box_w*(bucket_with_next_event_index + 1), y_cursor + box_h); + box_node->rect = rect; + box_node->event = next_event; + + y_bottom = Max(y_bottom, rect.y1); + + y_cursor += box_h; + } + + log_graph.max_y_scroll = clamp_bot(line_height, y_bottom - rect_height(event_list_region)*0.5f); + } + } +} + +internal void +log_parse_fill(Application_Links *app, Buffer_ID buffer){ + if (log_arena == 0){ + log_arena = reserve_arena(app); + } + + linalloc_clear(log_arena); + block_zero_struct(&log_graph); + log_filter_set_init(&log_filter_set); + log_filter_set_init(&log_preview_set); + + String_Const_u8 log_text = push_whole_buffer(app, log_arena, buffer); + log_parse = make_log_parse(log_arena, log_text); +} + +internal void +log_graph_render__tag(Arena *arena, Fancy_String_List *line, Log_Parse *log, Log_Tag *tag){ + String_Const_u8 tag_name = log_parse__get_string(log, tag->name); + push_fancy_stringf(arena, line, white, "["); + push_fancy_string(arena, line, green, tag_name); + push_fancy_stringf(arena, line, white, "="); + if (tag->value.kind == LogTagKind_Integer){ + push_fancy_stringf(arena, line, pink, "0x%llx", tag->value.value_s); + } + else if (tag->value.kind == LogTagKind_String){ + String_Const_u8 value = log_parse__get_string(log, tag->value.value); + push_fancy_string(arena, line, pink, value); + } + push_fancy_stringf(arena, line, white, "]"); +} + +internal void +log_graph_render(Application_Links *app, View_ID view, Frame_Info frame_info, Rect_f32 inner){ + if (log_parse.arena != 0){ + Face_ID face_id = get_face_id(app, 0); + f32 y_scroll = log_graph.y_scroll; + Log_Event *selected_event = log_graph.selected_event; + if (!log_graph.holding_temp || + inner != log_graph.layout_region || + face_id != log_graph.face_id || + log_filter_set.alter_counter != log_graph.filter_alter_counter){ + log_graph_fill(app, inner, face_id); + } + log_graph.y_scroll = clamp(0.f, y_scroll, log_graph.max_y_scroll); + log_graph.selected_event = selected_event; + + Mouse_State mouse = get_mouse_state(app); + Vec2_f32 m_p = V2f32(mouse.p) - inner.p0; + + Face_Metrics metrics = get_face_metrics(app, log_graph.face_id); + f32 line_height = metrics.line_height; + + Log_Event *hover_event = 0; + + b32 in_details_region = (rect_contains_point(log_graph.details_region, m_p)); + + for (Log_Graph_Box *box_node = log_graph.first_box; + box_node != 0; + box_node = box_node->next){ + Scratch_Block scratch(app); + + Rect_f32 box = box_node->rect; + box.y0 -= log_graph.y_scroll; + box.y1 -= log_graph.y_scroll; + + Rect_f32 box_inner = rect_inner(box, 3.f); + + Fancy_Color margin_color = dark_gray; + if (!in_details_region && hover_event == 0 && rect_contains_point(box, m_p)){ + margin_color = gray; + hover_event = box_node->event; + } + if (box_node->event == log_graph.selected_event){ + margin_color = light_gray; + } + + draw_rectangle_fancy(app, box , margin_color); + draw_rectangle_fancy(app, box_inner, black ); + + Log_Event *event = box_node->event; + + String_Const_u8 event_name = log_parse__get_string(&log_parse, event->event_name); + Fancy_String_List line = {}; + push_fancy_string(scratch, &line, white, event_name); + + for (Log_Filter *filter = log_preview_set.first; + filter != 0; + filter = filter->next){ + Table_u64_u64 *table = &event->tag_name_to_tag_ptr_table; + Table_Lookup lookup = table_lookup(table, filter->tag_name_code); + if (lookup.found_match){ + u64 val = 0; + table_read(table, lookup, &val); + Log_Tag *tag = (Log_Tag*)IntAsPtr(val); + push_fancy_string(scratch, &line, string_u8_litexpr(" ")); + log_graph_render__tag(scratch, &line, &log_parse, tag); + } + } + + + Vec2_f32 p = V2f32(box_inner.x0 + 3.f, + (f32_round32((box_inner.y0 + box_inner.y1 - line_height)*0.5f))); + draw_fancy_string(app, log_graph.face_id, line.first, p, 0, 0, 0, V2f32(1.f, 0.f)); + } + + { + Scratch_Block scratch(app); + + Rect_f32 box = log_graph.details_region; + Rect_f32 box_inner = rect_inner(box, 3.f); + + Log_Graph_List_Tab current_tab = log_graph.tab; + Log_Filter_Set *viewing_filter_set = log_filter_set_from_tab(current_tab); + + draw_rectangle_fancy(app, box , dark_gray); + draw_rectangle_fancy(app, box_inner, black ); + + { + f32 y_cursor = box_inner.y0 + 3.f; + if (y_cursor + line_height > box_inner.y1) goto finish_list_display; + + { + f32 x_cursor = box_inner.x0 + 3.f; + for (i32 i = LogTab_ERROR + 1; i < LogTab_COUNT; i += 1){ + Fancy_Color color = (i == current_tab)?white:gray; + Fancy_String_List line = {}; + switch (i){ + case LogTab_Filters: + { + push_fancy_stringf(scratch, &line, color, "filters"); + }break; + case LogTab_Previews: + { + push_fancy_stringf(scratch, &line, color, "previews"); + }break; + } + + Vec2_f32 p = V2f32(x_cursor, y_cursor); + f32 advance = get_fancy_string_advance(app, log_graph.face_id, line.first); + draw_fancy_string(app, log_graph.face_id, line.first, p, + Stag_Default, Stag_Back, 0, V2f32(1.f, 0.f)); + x_cursor += advance + metrics.normal_advance; + + if (log_graph.has_unused_click){ + Rect_f32 click_rect = Rf32(p.x, p.y, p.x + advance, p.y + line_height); + if (rect_contains_point(click_rect, log_graph.unused_click)){ + log_graph.has_unused_click = false; + log_graph.tab = i; + } + } + } + } + + if (viewing_filter_set != 0){ + for (Log_Filter *filter = viewing_filter_set->first, *next = 0; + filter != 0; + filter = next){ + next = filter->next; + + y_cursor += line_height; + if (y_cursor + line_height > box_inner.y1) goto finish_list_display; + + Fancy_String_List line = {}; + + if (filter->kind == LogFilter_TagValue){ + push_fancy_stringf(scratch, &line, white, "val ["); + String_Const_u8 tag_name = log_parse__get_string(&log_parse, filter->tag_name_code); + push_fancy_stringf(scratch, &line, green, "%.*s", string_expand(tag_name)); + push_fancy_stringf(scratch, &line, white, "="); + if (filter->tag_value.kind == LogTagKind_Integer){ + push_fancy_stringf(scratch, &line, pink, "0x%llx", filter->tag_value.value_s); + } + else if (filter->tag_value.kind == LogTagKind_String){ + String_Const_u8 value = log_parse__get_string(&log_parse, filter->tag_value.value); + push_fancy_stringf(scratch, &line, pink, "%.*s", string_expand(value)); + } + push_fancy_stringf(scratch, &line, white, "]"); + } + else{ + push_fancy_stringf(scratch, &line, white, "name ["); + String_Const_u8 tag_name = log_parse__get_string(&log_parse, filter->tag_name_code); + push_fancy_stringf(scratch, &line, green, "%.*s", string_expand(tag_name)); + push_fancy_stringf(scratch, &line, white, "]"); + } + + Vec2_f32 p = V2f32(box_inner.x0 + 3.f, y_cursor); + f32 advance = get_fancy_string_advance(app, log_graph.face_id, line.first); + draw_fancy_string(app, log_graph.face_id, line.first, p, Stag_Default, Stag_Back, + 0, V2f32(1.f, 0.f)); + + if (log_graph.has_unused_click){ + Rect_f32 click_rect = Rf32(p.x, p.y, p.x + advance, p.y + line_height); + if (rect_contains_point(click_rect, log_graph.unused_click)){ + log_graph.has_unused_click = false; + log_filter_set__free_filter(viewing_filter_set, filter); + } + } + } + } + + finish_list_display:; + } + + Log_Event *view_event = (hover_event!=0)?hover_event:log_graph.selected_event; + if (view_event != 0){ + f32 y_cursor = box_inner.y0 + 3.f; + if (y_cursor + line_height > box_inner.y1) goto finish_event_display; + + { + Fancy_String_List line = {}; + String_Const_u8 file_name = log_parse__get_string(&log_parse, view_event->src_file_name); + push_fancy_stringf(scratch, &line, green, "[%d] ", view_event->event_number); + push_fancy_stringf(scratch, &line, white, "%.*s:", string_expand(file_name)); + push_fancy_stringf(scratch, &line, pink, "%llu", view_event->line_number); + + Vec2_f32 right_p = V2f32(box_inner.x1 - 3.f, y_cursor); + f32 advance = get_fancy_string_advance(app, log_graph.face_id, line.first); + Vec2 p = V2f32(right_p.x - advance, right_p.y); + draw_fancy_string(app, log_graph.face_id, line.first, p, Stag_Default, Stag_Back, + 0, V2(1.f, 0.f)); + } + + for (Log_Tag *tag = view_event->first_tag; + tag != 0; + tag = tag->next){ + y_cursor += line_height; + if (y_cursor + line_height > box_inner.y1) goto finish_event_display; + + { + Fancy_String_List line = {}; + log_graph_render__tag(scratch, &line, &log_parse, tag); + + Vec2_f32 right_p = V2f32(box_inner.x1 - 3.f, y_cursor); + f32 advance = get_fancy_string_advance(app, log_graph.face_id, line.first); + Vec2 p = V2f32(right_p.x - advance, right_p.y); + draw_fancy_string(app, log_graph.face_id, line.first, p, + Stag_Default, Stag_Back, 0, V2(1.f, 0.f)); + + if (log_graph.has_unused_click){ + Rect_f32 click_rect = Rf32(p.x, p.y, right_p.x, p.y + line_height); + if (rect_contains_point(click_rect, log_graph.unused_click)){ + log_graph.has_unused_click = false; + Log_Filter filter = {}; + switch (log_graph.tab){ + case LogTab_Filters: + { + filter.kind = LogFilter_TagValue; + filter.tag_name_code = tag->name; + filter.tag_value = tag->value; + }break; + case LogTab_Previews: + { + filter.kind = LogFilter_Tag; + filter.tag_name_code = tag->name; + }break; + } + if (filter.kind != LogTab_ERROR){ + log_filter_set__new_filter(viewing_filter_set, &filter); + animate_in_n_milliseconds(app, 0); + } + } + } + } + } + + finish_event_display:; + } + } + + log_graph.has_unused_click = false; + } +} + +CUSTOM_COMMAND_SIG(log_graph__escape) +CUSTOM_DOC("Ends the log grapher") +{ + if (log_view != 0){ + view_end_ui_mode(app, log_view); + log_view = 0; + } +} + +CUSTOM_COMMAND_SIG(log_graph__scroll_wheel) +CUSTOM_DOC("Scrolls the log graph") +{ + if (log_view != 0){ + Mouse_State mouse = get_mouse_state(app); + if (mouse.wheel != 0){ + log_graph.y_scroll += mouse.wheel; + } + } +} + +internal Log_Graph_Box* +log_graph__get_box_at_point(Log_Graph *graph, Vec2_f32 p){ + Log_Graph_Box *result = 0; + if (!rect_contains_point(graph->details_region, p)){ + for (Log_Graph_Box *box_node = graph->first_box; + box_node != 0; + box_node = box_node->next){ + Rect_f32 box = box_node->rect; + box.y0 -= graph->y_scroll; + box.y1 -= graph->y_scroll; + if (rect_contains_point(box, p)){ + result = box_node; + break; + } + } + } + return(result); +} + +internal Log_Graph_Box* +log_graph__get_box_at_mouse_point(Application_Links *app, Log_Graph *graph){ + Mouse_State mouse = get_mouse_state(app); + Vec2_f32 m_p = V2f32(mouse.p) - graph->layout_region.p0; + return(log_graph__get_box_at_point(graph, m_p)); +} + +function void +log_graph__click_select_event(Application_Links *app, Vec2_f32 m_p) +{ + if (log_view != 0 && log_graph.holding_temp){ + Log_Graph_Box *box_node = log_graph__get_box_at_point(&log_graph, m_p); + if (box_node != 0){ + log_graph.selected_event = box_node->event; + } + else{ + log_graph.has_unused_click = true; + log_graph.unused_click = m_p; + } + } +} + +function void +log_graph__click_jump_to_event_source(Application_Links *app, Vec2_f32 m_p){ + if (log_view != 0 && log_graph.holding_temp){ + Log_Graph_Box *box_node = log_graph__get_box_at_point(&log_graph, m_p); + if (box_node != 0){ + Log_Event *event = box_node->event; + log_graph.selected_event = event; - umem colon2 = string_find_first(line, ':'); - src_line_number = string_prefix(line, colon2); - line = string_skip(line, colon2 + 1); - - if (string_is_integer(src_line_number, 10)){ - got_source_position = true; - } - } - - if (!got_source_position){ - line = whole_line; - - umem colon0 = string_find_first(line, ':'); - umem colon1 = string_find_first(line, colon0 + 1, ':'); - src_file_name = string_prefix(line, colon1); - line = string_skip(line, colon1 + 1); - - umem colon2 = string_find_first(line, ':'); - src_line_number = string_prefix(line, colon2); - line = string_skip(line, colon2 + 1); - - if (string_is_integer(src_line_number, 10)){ - got_source_position = true; - } - } - - if (got_source_position){ - umem bracket_open = string_find_first(line, '['); - String_Const_u8 event_name = string_prefix(line, bracket_open); - event_name = string_skip_chop_whitespace(event_name); - line = string_skip(line, bracket_open + 1); - - Log_Event *event = log_parse__event(&parse, - src_file_name, src_line_number, event_name); - - for (;line.size > 0;){ - umem bracket_close = string_find_first(line, ']'); - String_Const_u8 tag = string_prefix(line, bracket_close); - line = string_skip(line, bracket_close + 1); - bracket_open = string_find_first(line, '['); - line = string_skip(line, bracket_open + 1); - - umem equal_sign = string_find_first(tag, '='); - String_Const_u8 tag_name = string_prefix(tag, equal_sign); - String_Const_u8 tag_contents = string_skip(tag, equal_sign + 1); - - log_parse__tag(&parse, event, tag_name, tag_contents); - } - } - } - - //////////////////////////////// - - // NOTE(allen): fill acceleration structures - - parse.tag_value_to_event_list_table = make_table_Data_u64(arena->base_allocator, Thousand(1)); - parse.tag_name_to_event_list_table = make_table_u64_u64(arena->base_allocator, 100); - - for (Log_Event *event = parse.first_event; - event != 0; - event = event->next){ - for (Log_Tag *tag = event->first_tag; - tag != 0; - tag = tag->next){ - { - Log_Event_List *list = log_parse__get_or_make_list_tag_value(&parse, tag); - Log_Event_Ptr_Node *node = push_array(arena, Log_Event_Ptr_Node, 1); - sll_queue_push(list->first, list->last, node); - list->count += 1; - node->event = event; - } - { - Log_Event_List *list = log_parse__get_or_make_list_tag_name(&parse, tag); - Log_Event_Ptr_Node *node = push_array(arena, Log_Event_Ptr_Node, 1); - sll_queue_push(list->first, list->last, node); - list->count += 1; - node->event = event; - } - } - } - - for (Log_Event *event = parse.first_event; - event != 0; - event = event->next){ - i32 slot_count = event->tag_count*3/2; - event->tag_name_to_tag_ptr_table = make_table_u64_u64(arena->base_allocator, slot_count); - for (Log_Tag *tag = event->first_tag; - tag != 0; - tag = tag->next){ - table_insert(&event->tag_name_to_tag_ptr_table, tag->name, (u64)PtrAsInt(tag)); - } - } - - return(parse); -} + View_ID target_view = get_next_view_looped_primary_panels(app, log_view, AccessProtected); + if (target_view != 0){ + String_Const_u8 file_name = log_parse__get_string(&log_parse, event->src_file_name); + Buffer_ID target_buffer = get_buffer_by_file_name(app, file_name, AccessAll); + if (target_buffer == 0){ + target_buffer = get_buffer_by_name(app, file_name, AccessAll); + } + if (target_buffer != 0){ + if (target_view == log_view){ + view_end_ui_mode(app, target_view); + } + set_view_to_location(app, target_view, target_buffer, + seek_line_col(event->line_number, 1)); + } + } + } + else{ + log_graph.has_unused_click = true; + log_graph.unused_click = m_p; + } + } +} -//////////////////////////////// +#if 0 +internal void +fill_log_graph_command_map(Mapping *mapping){ + MappingScope(); + SelectMapping(mapping); + SelectMap(default_log_graph_map); + //Bind(log_graph__escape, KeyCode_Escape); + //BindMouseWheel(log_graph__scroll_wheel); + //BindMouse(log_graph__click_jump_to_event_source, MouseCode_Left); + //BindMouse(log_graph__click_select_event, MouseCode_Right); + Bind(log_graph__page_up, KeyCode_PageUp); + Bind(log_graph__page_down, KeyCode_PageDown); +} + #endif -internal void -log_events_sort_by_tag__inner(Log_Event **events, Log_Sort_Key *keys, i32 first, i32 one_past_last){ - if (first + 1 < one_past_last){ - i32 pivot_index = one_past_last - 1; - Log_Sort_Key *pivot_key = keys + pivot_index; - i32 j = first; - for (i32 i = first; i < one_past_last; i += 1){ - Log_Sort_Key *key = keys + i; - b32 key_is_less_than_pivot_key = false; - if (key->value.kind < pivot_key->value.kind){ - key_is_less_than_pivot_key = true; - } - else if (key->value.kind == pivot_key->value.kind){ - if (key->value.value < pivot_key->value.value){ - key_is_less_than_pivot_key = true; - } - else if (key->value.value == pivot_key->value.value){ - if (key->number < pivot_key->number){ - key_is_less_than_pivot_key = true; - } - } - } - if (key_is_less_than_pivot_key){ - if (j < i){ - Swap(Log_Event*, events[i], events[j]); - Swap(Log_Sort_Key, keys[i], keys[j]); - } - j += 1; - } - } - Swap(Log_Event*, events[pivot_index], events[j]); - Swap(Log_Sort_Key, keys[pivot_index], keys[j]); - log_events_sort_by_tag__inner(events, keys, first, j); - log_events_sort_by_tag__inner(events, keys, j + 1, one_past_last); - } -} - -internal void -log_events_sort_by_tag(Arena *scratch, Log_Event_Ptr_Array array, u64 tag_name){ - Temp_Memory temp = begin_temp(scratch); - Log_Sort_Key *keys = push_array(scratch, Log_Sort_Key, array.count); - for (i32 i = 0; i < array.count; i += 1){ - Log_Event *event = array.events[i]; - Table_Lookup lookup = table_lookup(&event->tag_name_to_tag_ptr_table, tag_name); - if (lookup.found_match){ - u64 read_val = 0; - table_read(&event->tag_name_to_tag_ptr_table, lookup, &read_val); - Log_Tag *tag = (Log_Tag*)IntAsPtr(read_val); - keys[i].value = tag->value; - } - else{ - keys[i].value.kind = LogTagKind_Null; - keys[i].value.value = 0; - } - keys[i].number = event->event_number; - } - - log_events_sort_by_tag__inner(array.events, keys, 0, array.count); - - end_temp(temp); -} - -internal Log_Event_Ptr_Array -log_event_array_from_list(Arena *arena, Log_Event_List list){ - Log_Event_Ptr_Array array = {}; - array.count = list.count; - array.events = push_array(arena, Log_Event*, array.count); - i32 counter = 0; - for (Log_Event_Ptr_Node *node = list.first; - node != 0; - node = node->next){ - array.events[counter] = node->event; - counter += 1; - } - return(array); -} - -//////////////////////////////// - -global View_ID log_view = 0; -global Arena *log_arena = {}; -global Log_Parse log_parse = {}; -global Log_Graph log_graph = {}; -global Log_Filter_Set log_filter_set = {}; -global Log_Filter_Set log_preview_set = {}; - -internal void -log_filter_set_init(Log_Filter_Set *set){ - block_zero_struct(set); - for (i32 i = ArrayCount(set->filters_memory) - 1; i >= 0; i -= 1){ - sll_stack_push(set->free_filters, &set->filters_memory[i]); - } -} - -internal Log_Filter_Set* -log_filter_set_from_tab(Log_Graph_List_Tab tab){ - Log_Filter_Set *result = 0; - switch (tab){ - case LogTab_Filters: - { - result = &log_filter_set; - }break; - case LogTab_Previews: - { - result = &log_preview_set; - }break; - } - return(result); -} - -internal Log_Filter* -log_filter_set__new_filter(Log_Filter_Set *set, Log_Filter *prototype){ - Log_Filter *result = set->free_filters; - if (result != 0){ - for (Log_Filter *filter = set->first; - filter != 0; - filter = filter->next){ - if (filter->kind == prototype->kind && - filter->tag_name_code == prototype->tag_name_code && - block_match_struct(&filter->tag_value, &prototype->tag_value)){ - result = 0; - break; - } - } - if (result != 0){ - sll_stack_pop(set->free_filters); - block_copy_struct(result, prototype); - zdll_push_back(set->first, set->last, result); - set->count += 1; - set->alter_counter += 1; - } - } - return(result); -} - -internal void -log_filter_set__free_filter(Log_Filter_Set *set, Log_Filter *filter){ - zdll_remove(set->first, set->last, filter); - set->count -= 1; - set->alter_counter += 1; - sll_stack_push(set->free_filters, filter); -} - -internal void -log_graph_fill(Application_Links *app, Rect_f32 layout_region, Face_ID face_id){ - if (log_parse.arena != 0){ - if (log_graph.holding_temp){ - end_temp(log_graph.temp); - } - block_zero_struct(&log_graph); - log_graph.holding_temp = true; - log_graph.temp = begin_temp(log_arena); - log_graph.layout_region = layout_region; - log_graph.face_id = face_id; - log_graph.filter_alter_counter = log_filter_set.alter_counter; - log_graph.preview_alter_counter = log_preview_set.alter_counter; - log_graph.tab = LogTab_Filters; - - f32 details_h = rect_height(layout_region)*.22f; - details_h = clamp_top(details_h, 250.f); - - Rect_f32 details_region = Rf32(layout_region.x0, layout_region.y0, - layout_region.x1, layout_region.y0 + details_h); - Rect_f32 event_list_region = Rf32(layout_region.x0, layout_region.y0 + details_h, - layout_region.x1, layout_region.y1); - - log_graph.details_region = details_region; - log_graph.details_region.p0 -= layout_region.p0; - log_graph.details_region.p1 -= layout_region.p0; - - u64 thread_code = log_parse__string_code(&log_parse, string_u8_litexpr("thread"), - LogParse_ExternalString); - - if (log_filter_set.count == 0){ - // NOTE(allen): everything goes into the filtered list - for (Log_Event *event = log_parse.first_event; - event != 0; - event = event->next){ - Log_Event_Ptr_Node *node = push_array(log_arena, Log_Event_Ptr_Node, 1); - node->event = event; - sll_queue_push(log_graph.filtered_list.first, log_graph.filtered_list.last, node); - log_graph.filtered_list.count += 1; - } - } - else{ - for (Log_Filter *filter = log_filter_set.first; - filter != 0; - filter = filter->next){ - Log_Event_List *filter_list = 0; - if (filter->kind == LogFilter_TagValue){ - filter_list = log_parse_get_list_tag_value(&log_parse, filter->tag_name_code, - filter->tag_value); - } - else if (filter->kind == LogFilter_Tag){ - filter_list = log_parse_get_list_tag_name(&log_parse, filter->tag_name_code); - } - - // NOTE(allen): combine with existing result - if (filter == log_filter_set.first){ - for (Log_Event_Ptr_Node *node = filter_list->first; - node != 0; - node = node->next){ - Log_Event_Ptr_Node *new_node = push_array(log_arena, Log_Event_Ptr_Node, 1); - new_node->event = node->event; - sll_queue_push(log_graph.filtered_list.first, log_graph.filtered_list.last, new_node); - log_graph.filtered_list.count += 1; - } - } - else{ - Log_Event_Ptr_Node **fixup_ptr = &log_graph.filtered_list.first; - log_graph.filtered_list.last = 0; - for (Log_Event_Ptr_Node *node_a = log_graph.filtered_list.first, *next = 0; - node_a != 0; - node_a = next){ - next = node_a->next; - - b32 remove_node_a = true; - for (Log_Event_Ptr_Node *node_b = filter_list->first; - node_b != 0; - node_b = node_b->next){ - if (node_a->event == node_b->event){ - remove_node_a = false; - break; - } - } - - if (remove_node_a){ - *fixup_ptr = next; - } - else{ - fixup_ptr = &node_a->next; - log_graph.filtered_list.last = node_a; - } - } - } - } - } - - log_graph.event_array = log_event_array_from_list(log_arena, - log_graph.filtered_list); - log_events_sort_by_tag(log_arena, log_graph.event_array, thread_code); - - b32 had_a_tag = true; - u64 thread_id_value = 0; - Log_Graph_Thread_Bucket *prev_bucket = 0; - - for (i32 i = 0; i < log_graph.event_array.count; i += 1){ - Table_u64_u64 *tag_table = &log_graph.event_array.events[i]->tag_name_to_tag_ptr_table; - Table_Lookup lookup = table_lookup(tag_table, thread_code); - - b32 emit_next_bucket = false; - if (!lookup.found_match){ - if (had_a_tag){ - had_a_tag = false; - thread_id_value = 0; - emit_next_bucket = true; - } - } - else{ - u64 read_val = 0; - table_read(tag_table, lookup, &read_val); - Log_Tag *tag = (Log_Tag*)IntAsPtr(read_val); - if (!had_a_tag){ - had_a_tag = true; - thread_id_value = tag->value.value; - emit_next_bucket = true; - } - else if (thread_id_value != tag->value.value){ - thread_id_value = tag->value.value; - emit_next_bucket = true; - } - } - - if (emit_next_bucket){ - Log_Graph_Thread_Bucket *bucket = push_array(log_arena, Log_Graph_Thread_Bucket, 1); - sll_queue_push(log_graph.first_bucket, log_graph.last_bucket, bucket); - log_graph.bucket_count += 1; - bucket->range.first = i; - bucket->had_a_tag = had_a_tag; - bucket->thread_id_value = thread_id_value; - if (prev_bucket != 0){ - prev_bucket->range.one_past_last = i; - } - prev_bucket = bucket; - } - } - if (prev_bucket != 0){ - prev_bucket->range.one_past_last = log_graph.event_array.count; - } - - Face_Metrics metrics = get_face_metrics(app, face_id); - f32 line_height = metrics.line_height; - f32 box_h = f32_floor32(line_height*1.5f); - f32 box_w = f32_floor32(rect_width(event_list_region)/log_graph.bucket_count); - f32 y_cursor = event_list_region.y0 - layout_region.y0; - - if (log_graph.bucket_count > 0){ - f32 y_bottom = 0.f; - - for (;;){ - i32 smallest_event_number = max_i32; - i32 bucket_with_next_event_index = -1; - Log_Graph_Thread_Bucket *bucket_with_next_event = 0; - Log_Event *next_event = 0; - i32 iteration_counter = 0; - for (Log_Graph_Thread_Bucket *bucket = log_graph.first_bucket; - bucket != 0; - bucket = bucket->next, iteration_counter += 1){ - if (bucket->range.first < bucket->range.one_past_last){ - Log_Event *event = log_graph.event_array.events[bucket->range.first]; - if (event->event_number < smallest_event_number){ - smallest_event_number = event->event_number; - bucket_with_next_event_index = iteration_counter; - bucket_with_next_event = bucket; - next_event = event; - } - } - } - - if (bucket_with_next_event == 0){ - break; - } - - bucket_with_next_event->range.first += 1; - - Log_Graph_Box *box_node = push_array(log_arena, Log_Graph_Box, 1); - sll_queue_push(log_graph.first_box, log_graph.last_box, box_node); - log_graph.box_count += 1; - Rect_f32 rect = Rf32(box_w*bucket_with_next_event_index , y_cursor, - box_w*(bucket_with_next_event_index + 1), y_cursor + box_h); - box_node->rect = rect; - box_node->event = next_event; - - y_bottom = Max(y_bottom, rect.y1); - - y_cursor += box_h; - } - - log_graph.max_y_scroll = clamp_bot(line_height, y_bottom - rect_height(event_list_region)*0.5f); - } - } -} - -internal void -log_parse_fill(Application_Links *app, Buffer_ID buffer){ - if (log_arena == 0){ - log_arena = reserve_arena(app); - } - - linalloc_clear(log_arena); - block_zero_struct(&log_graph); - log_filter_set_init(&log_filter_set); - log_filter_set_init(&log_preview_set); - - String_Const_u8 log_text = push_whole_buffer(app, log_arena, buffer); - log_parse = make_log_parse(log_arena, log_text); -} - -internal void -log_graph_render__tag(Arena *arena, Fancy_String_List *line, Log_Parse *log, Log_Tag *tag){ - String_Const_u8 tag_name = log_parse__get_string(log, tag->name); - push_fancy_stringf(arena, line, white, "["); - push_fancy_string(arena, line, green, tag_name); - push_fancy_stringf(arena, line, white, "="); - if (tag->value.kind == LogTagKind_Integer){ - push_fancy_stringf(arena, line, pink, "0x%llx", tag->value.value_s); - } - else if (tag->value.kind == LogTagKind_String){ - String_Const_u8 value = log_parse__get_string(log, tag->value.value); - push_fancy_string(arena, line, pink, value); - } - push_fancy_stringf(arena, line, white, "]"); -} - -internal void -log_graph_render(Application_Links *app, View_ID view, Frame_Info frame_info, Rect_f32 inner){ - if (log_parse.arena != 0){ - Face_ID face_id = get_face_id(app, 0); - f32 y_scroll = log_graph.y_scroll; - Log_Event *selected_event = log_graph.selected_event; - if (!log_graph.holding_temp || - inner != log_graph.layout_region || - face_id != log_graph.face_id || - log_filter_set.alter_counter != log_graph.filter_alter_counter){ - log_graph_fill(app, inner, face_id); - } - log_graph.y_scroll = clamp(0.f, y_scroll, log_graph.max_y_scroll); - log_graph.selected_event = selected_event; - - Mouse_State mouse = get_mouse_state(app); - Vec2_f32 m_p = V2f32(mouse.p) - inner.p0; - - Face_Metrics metrics = get_face_metrics(app, log_graph.face_id); - f32 line_height = metrics.line_height; - - Log_Event *hover_event = 0; - - b32 in_details_region = (rect_contains_point(log_graph.details_region, m_p)); - - for (Log_Graph_Box *box_node = log_graph.first_box; - box_node != 0; - box_node = box_node->next){ - Scratch_Block scratch(app); - - Rect_f32 box = box_node->rect; - box.y0 -= log_graph.y_scroll; - box.y1 -= log_graph.y_scroll; - - Rect_f32 box_inner = rect_inner(box, 3.f); - - Fancy_Color margin_color = dark_gray; - if (!in_details_region && hover_event == 0 && rect_contains_point(box, m_p)){ - margin_color = gray; - hover_event = box_node->event; - } - if (box_node->event == log_graph.selected_event){ - margin_color = light_gray; - } - - draw_rectangle_fancy(app, box , margin_color); - draw_rectangle_fancy(app, box_inner, black ); - - Log_Event *event = box_node->event; - - String_Const_u8 event_name = log_parse__get_string(&log_parse, event->event_name); - Fancy_String_List line = {}; - push_fancy_string(scratch, &line, white, event_name); - - for (Log_Filter *filter = log_preview_set.first; - filter != 0; - filter = filter->next){ - Table_u64_u64 *table = &event->tag_name_to_tag_ptr_table; - Table_Lookup lookup = table_lookup(table, filter->tag_name_code); - if (lookup.found_match){ - u64 val = 0; - table_read(table, lookup, &val); - Log_Tag *tag = (Log_Tag*)IntAsPtr(val); - push_fancy_string(scratch, &line, string_u8_litexpr(" ")); - log_graph_render__tag(scratch, &line, &log_parse, tag); - } - } - - - Vec2_f32 p = V2f32(box_inner.x0 + 3.f, - (f32_round32((box_inner.y0 + box_inner.y1 - line_height)*0.5f))); - draw_fancy_string(app, log_graph.face_id, line.first, p, 0, 0, 0, V2f32(1.f, 0.f)); - } - - { - Scratch_Block scratch(app); - - Rect_f32 box = log_graph.details_region; - Rect_f32 box_inner = rect_inner(box, 3.f); - - Log_Graph_List_Tab current_tab = log_graph.tab; - Log_Filter_Set *viewing_filter_set = log_filter_set_from_tab(current_tab); - - draw_rectangle_fancy(app, box , dark_gray); - draw_rectangle_fancy(app, box_inner, black ); - - { - f32 y_cursor = box_inner.y0 + 3.f; - if (y_cursor + line_height > box_inner.y1) goto finish_list_display; - - { - f32 x_cursor = box_inner.x0 + 3.f; - for (i32 i = LogTab_ERROR + 1; i < LogTab_COUNT; i += 1){ - Fancy_Color color = (i == current_tab)?white:gray; - Fancy_String_List line = {}; - switch (i){ - case LogTab_Filters: - { - push_fancy_stringf(scratch, &line, color, "filters"); - }break; - case LogTab_Previews: - { - push_fancy_stringf(scratch, &line, color, "previews"); - }break; - } - - Vec2_f32 p = V2f32(x_cursor, y_cursor); - f32 advance = get_fancy_string_advance(app, log_graph.face_id, line.first); - draw_fancy_string(app, log_graph.face_id, line.first, p, - Stag_Default, Stag_Back, 0, V2f32(1.f, 0.f)); - x_cursor += advance + metrics.normal_advance; - - if (log_graph.has_unused_click){ - Rect_f32 click_rect = Rf32(p.x, p.y, p.x + advance, p.y + line_height); - if (rect_contains_point(click_rect, log_graph.unused_click)){ - log_graph.has_unused_click = false; - log_graph.tab = i; - } - } - } - } - - if (viewing_filter_set != 0){ - for (Log_Filter *filter = viewing_filter_set->first, *next = 0; - filter != 0; - filter = next){ - next = filter->next; - - y_cursor += line_height; - if (y_cursor + line_height > box_inner.y1) goto finish_list_display; - - Fancy_String_List line = {}; - - if (filter->kind == LogFilter_TagValue){ - push_fancy_stringf(scratch, &line, white, "val ["); - String_Const_u8 tag_name = log_parse__get_string(&log_parse, filter->tag_name_code); - push_fancy_stringf(scratch, &line, green, "%.*s", string_expand(tag_name)); - push_fancy_stringf(scratch, &line, white, "="); - if (filter->tag_value.kind == LogTagKind_Integer){ - push_fancy_stringf(scratch, &line, pink, "0x%llx", filter->tag_value.value_s); - } - else if (filter->tag_value.kind == LogTagKind_String){ - String_Const_u8 value = log_parse__get_string(&log_parse, filter->tag_value.value); - push_fancy_stringf(scratch, &line, pink, "%.*s", string_expand(value)); - } - push_fancy_stringf(scratch, &line, white, "]"); - } - else{ - push_fancy_stringf(scratch, &line, white, "name ["); - String_Const_u8 tag_name = log_parse__get_string(&log_parse, filter->tag_name_code); - push_fancy_stringf(scratch, &line, green, "%.*s", string_expand(tag_name)); - push_fancy_stringf(scratch, &line, white, "]"); - } - - Vec2_f32 p = V2f32(box_inner.x0 + 3.f, y_cursor); - f32 advance = get_fancy_string_advance(app, log_graph.face_id, line.first); - draw_fancy_string(app, log_graph.face_id, line.first, p, Stag_Default, Stag_Back, - 0, V2f32(1.f, 0.f)); - - if (log_graph.has_unused_click){ - Rect_f32 click_rect = Rf32(p.x, p.y, p.x + advance, p.y + line_height); - if (rect_contains_point(click_rect, log_graph.unused_click)){ - log_graph.has_unused_click = false; - log_filter_set__free_filter(viewing_filter_set, filter); - } - } - } - } - - finish_list_display:; - } - - Log_Event *view_event = (hover_event!=0)?hover_event:log_graph.selected_event; - if (view_event != 0){ - f32 y_cursor = box_inner.y0 + 3.f; - if (y_cursor + line_height > box_inner.y1) goto finish_event_display; - - { - Fancy_String_List line = {}; - String_Const_u8 file_name = log_parse__get_string(&log_parse, view_event->src_file_name); - push_fancy_stringf(scratch, &line, green, "[%d] ", view_event->event_number); - push_fancy_stringf(scratch, &line, white, "%.*s:", string_expand(file_name)); - push_fancy_stringf(scratch, &line, pink, "%llu", view_event->line_number); - - Vec2_f32 right_p = V2f32(box_inner.x1 - 3.f, y_cursor); - f32 advance = get_fancy_string_advance(app, log_graph.face_id, line.first); - Vec2 p = V2f32(right_p.x - advance, right_p.y); - draw_fancy_string(app, log_graph.face_id, line.first, p, Stag_Default, Stag_Back, - 0, V2(1.f, 0.f)); - } - - for (Log_Tag *tag = view_event->first_tag; - tag != 0; - tag = tag->next){ - y_cursor += line_height; - if (y_cursor + line_height > box_inner.y1) goto finish_event_display; - - { - Fancy_String_List line = {}; - log_graph_render__tag(scratch, &line, &log_parse, tag); - - Vec2_f32 right_p = V2f32(box_inner.x1 - 3.f, y_cursor); - f32 advance = get_fancy_string_advance(app, log_graph.face_id, line.first); - Vec2 p = V2f32(right_p.x - advance, right_p.y); - draw_fancy_string(app, log_graph.face_id, line.first, p, - Stag_Default, Stag_Back, 0, V2(1.f, 0.f)); - - if (log_graph.has_unused_click){ - Rect_f32 click_rect = Rf32(p.x, p.y, right_p.x, p.y + line_height); - if (rect_contains_point(click_rect, log_graph.unused_click)){ - log_graph.has_unused_click = false; - Log_Filter filter = {}; - switch (log_graph.tab){ - case LogTab_Filters: - { - filter.kind = LogFilter_TagValue; - filter.tag_name_code = tag->name; - filter.tag_value = tag->value; - }break; - case LogTab_Previews: - { - filter.kind = LogFilter_Tag; - filter.tag_name_code = tag->name; - }break; - } - if (filter.kind != LogTab_ERROR){ - log_filter_set__new_filter(viewing_filter_set, &filter); - animate_in_n_milliseconds(app, 0); - } - } - } - } - } - - finish_event_display:; - } - } - - log_graph.has_unused_click = false; - } -} - -CUSTOM_COMMAND_SIG(log_graph__escape) -CUSTOM_DOC("Ends the log grapher") -{ - if (log_view != 0){ - view_end_ui_mode(app, log_view); - log_view = 0; - } -} - -CUSTOM_COMMAND_SIG(log_graph__scroll_wheel) -CUSTOM_DOC("Scrolls the log graph") -{ - if (log_view != 0){ - Mouse_State mouse = get_mouse_state(app); - if (mouse.wheel != 0){ - log_graph.y_scroll += mouse.wheel; - } - } -} - -CUSTOM_COMMAND_SIG(log_graph__page_up) -CUSTOM_DOC("Scroll the log graph up one whole page") -{ - if (log_view != 0){ - log_graph.y_scroll -= get_page_jump(app, log_view); - } -} - -CUSTOM_COMMAND_SIG(log_graph__page_down) -CUSTOM_DOC("Scroll the log graph down one whole page") -{ - if (log_view != 0){ - log_graph.y_scroll += get_page_jump(app, log_view); - } -} - -internal Log_Graph_Box* -log_graph__get_box_at_point(Log_Graph *graph, Vec2_f32 p){ - Log_Graph_Box *result = 0; - if (!rect_contains_point(graph->details_region, p)){ - for (Log_Graph_Box *box_node = graph->first_box; - box_node != 0; - box_node = box_node->next){ - Rect_f32 box = box_node->rect; - box.y0 -= graph->y_scroll; - box.y1 -= graph->y_scroll; - if (rect_contains_point(box, p)){ - result = box_node; - break; - } - } - } - return(result); -} - -internal Log_Graph_Box* -log_graph__get_box_at_mouse_point(Application_Links *app, Log_Graph *graph){ - Mouse_State mouse = get_mouse_state(app); - Vec2_f32 m_p = V2f32(mouse.p) - graph->layout_region.p0; - return(log_graph__get_box_at_point(graph, m_p)); -} - -CUSTOM_COMMAND_SIG(log_graph__click_select_event) -CUSTOM_DOC("Select the event record at the mouse point in the log graph") -{ - if (log_view != 0){ - if (log_graph.holding_temp){ - Mouse_State mouse = get_mouse_state(app); - Vec2_f32 m_p = V2f32(mouse.p) - log_graph.layout_region.p0; - Log_Graph_Box *box_node = log_graph__get_box_at_point(&log_graph, m_p); - if (box_node != 0){ - log_graph.selected_event = box_node->event; - } - else{ - log_graph.has_unused_click = true; - log_graph.unused_click = m_p; - } - } - } -} - -CUSTOM_COMMAND_SIG(log_graph__click_jump_to_event_source) -CUSTOM_DOC("Jump to the code that logged the event record at the mouse point in the log graph") -{ - if (log_view != 0){ - if (log_graph.holding_temp){ - Mouse_State mouse = get_mouse_state(app); - Vec2_f32 m_p = V2f32(mouse.p) - log_graph.layout_region.p0; - Log_Graph_Box *box_node = log_graph__get_box_at_point(&log_graph, m_p); - if (box_node != 0){ - Log_Event *event = box_node->event; - log_graph.selected_event = event; - - View_ID target_view = get_next_view_looped_primary_panels(app, log_view, AccessProtected); - if (target_view != 0){ - String_Const_u8 file_name = log_parse__get_string(&log_parse, event->src_file_name); - Buffer_ID target_buffer = get_buffer_by_file_name(app, file_name, AccessAll); - if (target_buffer == 0){ - target_buffer = get_buffer_by_name(app, file_name, AccessAll); - } - if (target_buffer != 0){ - if (target_view == log_view){ - view_end_ui_mode(app, target_view); - } - set_view_to_location(app, target_view, target_buffer, - seek_line_col(event->line_number, 1)); - } - } - } - else{ - log_graph.has_unused_click = true; - log_graph.unused_click = m_p; - } - } - } -} - -internal void -fill_log_graph_command_map(Mapping *mapping){ - MappingScope(); - SelectMapping(mapping); - SelectMap(default_log_graph_map); - Bind(log_graph__escape, KeyCode_Escape); - BindMouseWheel(log_graph__scroll_wheel); - BindMouse(log_graph__click_jump_to_event_source, MouseCode_Left); - BindMouse(log_graph__click_select_event, MouseCode_Right); - Bind(log_graph__page_up, KeyCode_PageUp); - Bind(log_graph__page_down, KeyCode_PageDown); -} - -CUSTOM_COMMAND_SIG(show_the_log_graph) -CUSTOM_DOC("Parser *log* and displays the 'log graph' UI") -{ - Buffer_ID log_buffer = get_buffer_by_name(app, string_u8_litexpr("*log*"), AccessAll); - log_parse_fill(app, log_buffer); - - if (log_view == 0){ - log_view = get_active_view(app, AccessAll); - } - Managed_Scope scope = view_get_managed_scope(app, log_view); - View_Render_Hook **hook = scope_attachment(app, scope, view_render_hook, View_Render_Hook*); +CUSTOM_COMMAND_SIG(show_the_log_graph) +CUSTOM_DOC("Parses *log* and displays the 'log graph' UI") +{ + Buffer_ID log_buffer = get_buffer_by_name(app, string_u8_litexpr("*log*"), AccessAll); + log_parse_fill(app, log_buffer); + + if (log_view == 0){ + log_view = get_active_view(app, AccessAll); + } + Managed_Scope scope = view_get_managed_scope(app, log_view); + View_Render_Hook **hook = scope_attachment(app, scope, view_render_hook, View_Render_Hook*); *hook = log_graph_render; - view_set_setting(app, log_view, ViewSetting_UICommandMap, default_log_graph_map); - view_begin_ui_mode(app, log_view); - view_set_quit_ui_handler(app, log_view, ui_quit_clear_render_hook); -} - -// BOTTOM - + + for (;;){ + User_Input in = get_user_input(app, + EventPropertyGroup_AnyUserInput, + KeyCode_Escape); + if (in.abort){ + log_view = 0; + break; + } + + switch (in.event.kind){ + case InputEventKind_KeyStroke: + { + switch (in.event.key.code){ + case KeyCode_PageUp: + { + log_graph.y_scroll -= get_page_jump(app, log_view); + }break; + + case KeyCode_PageDown: + { + log_graph.y_scroll += get_page_jump(app, log_view); + }break; + } + }break; + + case InputEventKind_MouseButton: + { + Vec2_f32 m_p = V2f32(in.event.mouse.p) - log_graph.layout_region.p0; + switch (in.event.mouse.code){ + case MouseCode_Left: + { + log_graph__click_jump_to_event_source(app, m_p); + }break; + + case MouseCode_Right: + { + log_graph__click_select_event(app, m_p); + }break; + } + }break; + + case InputEventKind_MouseWheel: + { + f32 value = in.event.mouse_wheel.value; + log_graph.y_scroll += f32_round32(value); + }break; + } + } + + hook = scope_attachment(app, scope, view_render_hook, View_Render_Hook*); + *hook = 0; +} + +// BOTTOM + diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index 1b97d340..408b2722 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -2,7 +2,7 @@ #define command_id(c) (fcoder_metacmd_ID_##c) #define command_metadata(c) (&fcoder_metacmd_table[command_id(c)]) #define command_metadata_by_id(id) (&fcoder_metacmd_table[id]) -#define command_one_past_last_id 225 +#define command_one_past_last_id 221 #if defined(CUSTOM_COMMAND_SIG) #define PROC_LINKS(x,y) x #else @@ -177,10 +177,6 @@ CUSTOM_COMMAND_SIG(if_read_only_goto_position_same_panel); CUSTOM_COMMAND_SIG(view_jump_list_with_lister); CUSTOM_COMMAND_SIG(log_graph__escape); CUSTOM_COMMAND_SIG(log_graph__scroll_wheel); -CUSTOM_COMMAND_SIG(log_graph__page_up); -CUSTOM_COMMAND_SIG(log_graph__page_down); -CUSTOM_COMMAND_SIG(log_graph__click_select_event); -CUSTOM_COMMAND_SIG(log_graph__click_jump_to_event_source); CUSTOM_COMMAND_SIG(show_the_log_graph); CUSTOM_COMMAND_SIG(copy); CUSTOM_COMMAND_SIG(cut); @@ -245,7 +241,7 @@ char *source_name; i32 source_name_len; i32 line_number; }; -static Command_Metadata fcoder_metacmd_table[225] = { +static Command_Metadata fcoder_metacmd_table[221] = { { PROC_LINKS(default_view_input_handler, 0), "default_view_input_handler", 26, "Input consumption loop for base view behavior", 45, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 17 }, { PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 1984 }, { PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 1990 }, @@ -414,11 +410,7 @@ static Command_Metadata fcoder_metacmd_table[225] = { { PROC_LINKS(view_jump_list_with_lister, 0), "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 102 }, { PROC_LINKS(log_graph__escape, 0), "log_graph__escape", 17, "Ends the log grapher", 20, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 906 }, { PROC_LINKS(log_graph__scroll_wheel, 0), "log_graph__scroll_wheel", 23, "Scrolls the log graph", 21, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 915 }, -{ PROC_LINKS(log_graph__page_up, 0), "log_graph__page_up", 18, "Scroll the log graph up one whole page", 38, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 926 }, -{ PROC_LINKS(log_graph__page_down, 0), "log_graph__page_down", 20, "Scroll the log graph down one whole page", 40, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 934 }, -{ PROC_LINKS(log_graph__click_select_event, 0), "log_graph__click_select_event", 29, "Select the event record at the mouse point in the log graph", 59, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 968 }, -{ PROC_LINKS(log_graph__click_jump_to_event_source, 0), "log_graph__click_jump_to_event_source", 37, "Jump to the code that logged the event record at the mouse point in the log graph", 81, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 987 }, -{ PROC_LINKS(show_the_log_graph, 0), "show_the_log_graph", 18, "Parser *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 1036 }, +{ PROC_LINKS(show_the_log_graph, 0), "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 1013 }, { PROC_LINKS(copy, 0), "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 19 }, { PROC_LINKS(cut, 0), "cut", 3, "Cut the text in the range from the cursor to the mark onto the clipboard.", 73, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 28 }, { PROC_LINKS(paste, 0), "paste", 5, "At the cursor, insert the text at the top of the clipboard.", 59, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 39 }, @@ -640,61 +632,57 @@ static i32 fcoder_metacmd_ID_if_read_only_goto_position_same_panel = 164; static i32 fcoder_metacmd_ID_view_jump_list_with_lister = 165; static i32 fcoder_metacmd_ID_log_graph__escape = 166; static i32 fcoder_metacmd_ID_log_graph__scroll_wheel = 167; -static i32 fcoder_metacmd_ID_log_graph__page_up = 168; -static i32 fcoder_metacmd_ID_log_graph__page_down = 169; -static i32 fcoder_metacmd_ID_log_graph__click_select_event = 170; -static i32 fcoder_metacmd_ID_log_graph__click_jump_to_event_source = 171; -static i32 fcoder_metacmd_ID_show_the_log_graph = 172; -static i32 fcoder_metacmd_ID_copy = 173; -static i32 fcoder_metacmd_ID_cut = 174; -static i32 fcoder_metacmd_ID_paste = 175; -static i32 fcoder_metacmd_ID_paste_next = 176; -static i32 fcoder_metacmd_ID_paste_and_indent = 177; -static i32 fcoder_metacmd_ID_paste_next_and_indent = 178; -static i32 fcoder_metacmd_ID_execute_previous_cli = 179; -static i32 fcoder_metacmd_ID_execute_any_cli = 180; -static i32 fcoder_metacmd_ID_build_search = 181; -static i32 fcoder_metacmd_ID_build_in_build_panel = 182; -static i32 fcoder_metacmd_ID_close_build_panel = 183; -static i32 fcoder_metacmd_ID_change_to_build_panel = 184; -static i32 fcoder_metacmd_ID_close_all_code = 185; -static i32 fcoder_metacmd_ID_open_all_code = 186; -static i32 fcoder_metacmd_ID_open_all_code_recursive = 187; -static i32 fcoder_metacmd_ID_load_project = 188; -static i32 fcoder_metacmd_ID_project_fkey_command = 189; -static i32 fcoder_metacmd_ID_project_go_to_root_directory = 190; -static i32 fcoder_metacmd_ID_setup_new_project = 191; -static i32 fcoder_metacmd_ID_setup_build_bat = 192; -static i32 fcoder_metacmd_ID_setup_build_sh = 193; -static i32 fcoder_metacmd_ID_setup_build_bat_and_sh = 194; -static i32 fcoder_metacmd_ID_project_command_lister = 195; -static i32 fcoder_metacmd_ID_list_all_functions_current_buffer = 196; -static i32 fcoder_metacmd_ID_list_all_functions_current_buffer_lister = 197; -static i32 fcoder_metacmd_ID_list_all_functions_all_buffers = 198; -static i32 fcoder_metacmd_ID_list_all_functions_all_buffers_lister = 199; -static i32 fcoder_metacmd_ID_select_surrounding_scope = 200; -static i32 fcoder_metacmd_ID_select_next_scope_absolute = 201; -static i32 fcoder_metacmd_ID_select_next_scope_after_current = 202; -static i32 fcoder_metacmd_ID_select_prev_scope_absolute = 203; -static i32 fcoder_metacmd_ID_place_in_scope = 204; -static i32 fcoder_metacmd_ID_delete_current_scope = 205; -static i32 fcoder_metacmd_ID_open_long_braces = 206; -static i32 fcoder_metacmd_ID_open_long_braces_semicolon = 207; -static i32 fcoder_metacmd_ID_open_long_braces_break = 208; -static i32 fcoder_metacmd_ID_if0_off = 209; -static i32 fcoder_metacmd_ID_write_todo = 210; -static i32 fcoder_metacmd_ID_write_hack = 211; -static i32 fcoder_metacmd_ID_write_note = 212; -static i32 fcoder_metacmd_ID_write_block = 213; -static i32 fcoder_metacmd_ID_write_zero_struct = 214; -static i32 fcoder_metacmd_ID_comment_line = 215; -static i32 fcoder_metacmd_ID_uncomment_line = 216; -static i32 fcoder_metacmd_ID_comment_line_toggle = 217; -static i32 fcoder_metacmd_ID_snippet_lister = 218; -static i32 fcoder_metacmd_ID_miblo_increment_basic = 219; -static i32 fcoder_metacmd_ID_miblo_decrement_basic = 220; -static i32 fcoder_metacmd_ID_miblo_increment_time_stamp = 221; -static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp = 222; -static i32 fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 223; -static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 224; +static i32 fcoder_metacmd_ID_show_the_log_graph = 168; +static i32 fcoder_metacmd_ID_copy = 169; +static i32 fcoder_metacmd_ID_cut = 170; +static i32 fcoder_metacmd_ID_paste = 171; +static i32 fcoder_metacmd_ID_paste_next = 172; +static i32 fcoder_metacmd_ID_paste_and_indent = 173; +static i32 fcoder_metacmd_ID_paste_next_and_indent = 174; +static i32 fcoder_metacmd_ID_execute_previous_cli = 175; +static i32 fcoder_metacmd_ID_execute_any_cli = 176; +static i32 fcoder_metacmd_ID_build_search = 177; +static i32 fcoder_metacmd_ID_build_in_build_panel = 178; +static i32 fcoder_metacmd_ID_close_build_panel = 179; +static i32 fcoder_metacmd_ID_change_to_build_panel = 180; +static i32 fcoder_metacmd_ID_close_all_code = 181; +static i32 fcoder_metacmd_ID_open_all_code = 182; +static i32 fcoder_metacmd_ID_open_all_code_recursive = 183; +static i32 fcoder_metacmd_ID_load_project = 184; +static i32 fcoder_metacmd_ID_project_fkey_command = 185; +static i32 fcoder_metacmd_ID_project_go_to_root_directory = 186; +static i32 fcoder_metacmd_ID_setup_new_project = 187; +static i32 fcoder_metacmd_ID_setup_build_bat = 188; +static i32 fcoder_metacmd_ID_setup_build_sh = 189; +static i32 fcoder_metacmd_ID_setup_build_bat_and_sh = 190; +static i32 fcoder_metacmd_ID_project_command_lister = 191; +static i32 fcoder_metacmd_ID_list_all_functions_current_buffer = 192; +static i32 fcoder_metacmd_ID_list_all_functions_current_buffer_lister = 193; +static i32 fcoder_metacmd_ID_list_all_functions_all_buffers = 194; +static i32 fcoder_metacmd_ID_list_all_functions_all_buffers_lister = 195; +static i32 fcoder_metacmd_ID_select_surrounding_scope = 196; +static i32 fcoder_metacmd_ID_select_next_scope_absolute = 197; +static i32 fcoder_metacmd_ID_select_next_scope_after_current = 198; +static i32 fcoder_metacmd_ID_select_prev_scope_absolute = 199; +static i32 fcoder_metacmd_ID_place_in_scope = 200; +static i32 fcoder_metacmd_ID_delete_current_scope = 201; +static i32 fcoder_metacmd_ID_open_long_braces = 202; +static i32 fcoder_metacmd_ID_open_long_braces_semicolon = 203; +static i32 fcoder_metacmd_ID_open_long_braces_break = 204; +static i32 fcoder_metacmd_ID_if0_off = 205; +static i32 fcoder_metacmd_ID_write_todo = 206; +static i32 fcoder_metacmd_ID_write_hack = 207; +static i32 fcoder_metacmd_ID_write_note = 208; +static i32 fcoder_metacmd_ID_write_block = 209; +static i32 fcoder_metacmd_ID_write_zero_struct = 210; +static i32 fcoder_metacmd_ID_comment_line = 211; +static i32 fcoder_metacmd_ID_uncomment_line = 212; +static i32 fcoder_metacmd_ID_comment_line_toggle = 213; +static i32 fcoder_metacmd_ID_snippet_lister = 214; +static i32 fcoder_metacmd_ID_miblo_increment_basic = 215; +static i32 fcoder_metacmd_ID_miblo_decrement_basic = 216; +static i32 fcoder_metacmd_ID_miblo_increment_time_stamp = 217; +static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp = 218; +static i32 fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 219; +static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 220; #endif