From d27c566ff11db6128991df67d6d949ef3e3665c6 Mon Sep 17 00:00:00 2001 From: Patrick Cleaveliln Date: Sat, 26 Jul 2025 23:05:26 +0000 Subject: [PATCH] add debug panel, don't open same file twice --- src/core/core.odin | 19 +++++- src/core/file_buffer.odin | 7 +- src/main.odin | 6 +- src/panels/debug.odin | 140 ++++++++++++++++++++++++++++++++++++++ src/ui/ui.odin | 75 +++++++++++++------- 5 files changed, 218 insertions(+), 29 deletions(-) create mode 100644 src/panels/debug.odin diff --git a/src/core/core.odin b/src/core/core.odin index 5aec7fd..5ec62a3 100644 --- a/src/core/core.odin +++ b/src/core/core.odin @@ -96,10 +96,14 @@ Panel_VTable :: struct { } PanelType :: union { + DebugPanel, FileBufferPanel, GrepPanel, } +DebugPanel :: struct { +} + FileBufferPanel :: struct { buffer_id: int, viewed_symbol: Maybe(string), @@ -136,8 +140,10 @@ GrepQueryResult :: struct { current_buffer :: proc(state: ^State) -> ^FileBuffer { if current_panel, ok := state.current_panel.?; ok { if panel, ok := util.get(&state.panels, current_panel).?; ok { - buffer, _ := panel->buffer(state) - return buffer + if panel.buffer != nil { + buffer, _ := panel->buffer(state) + return buffer + } } } @@ -149,6 +155,15 @@ new_buffer_virtual :: proc(state: ^State) -> (id: int, buffer: ^FileBuffer, ok: } new_buffer_file :: proc(state: ^State, file_path: string, line: int = 0, col: int = 0) -> (id: int, buffer: ^FileBuffer, ok: bool) { + for i in 0.. FileBuffer { glyphs = make_glyph_buffer(width, height), }; + push_new_snapshot(&buffer.history) + return buffer; } @@ -812,6 +814,7 @@ make_file_buffer :: proc(allocator: mem.Allocator, file_path: string, base_dir: glyphs = make_glyph_buffer(width, height), }; + push_new_snapshot(&buffer.history) ts.parse_buffer(&buffer.tree, tree_sitter_file_buffer_input(&buffer)) return buffer, error(); @@ -905,8 +908,8 @@ color_character :: proc(buffer: ^FileBuffer, start: Cursor, end: Cursor, palette } draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x, y, w, h: int, show_line_numbers: bool = true, show_cursor: bool = true) { - glyph_width := math.min(256, int(w / state.source_font_width)); - glyph_height := math.min(256, int(h / state.source_font_height)) + 1; + glyph_width := math.max(math.min(256, int(w / state.source_font_width)), 1); + glyph_height := math.max(math.min(256, int(h / state.source_font_height)) + 1, 1); update_glyph_buffer(buffer, glyph_width, glyph_height); diff --git a/src/main.odin b/src/main.odin index f345e13..6742d42 100644 --- a/src/main.odin +++ b/src/main.odin @@ -265,6 +265,10 @@ main :: proc() { panels.open(&state, panels.make_file_buffer_panel("")) } + + panels.open(&state, panels.make_debug_panel()) + panels.open(&state, panels.make_debug_panel()) + if sdl2.Init({.VIDEO}) < 0 { log.error("SDL failed to initialize:", sdl2.GetError()); return; @@ -331,8 +335,6 @@ main :: proc() { sdl2.AddEventWatch(expose_event_watcher, &state); - core.push_new_snapshot(&core.current_buffer(&state).history) - control_key_pressed: bool; for !state.should_close { { diff --git a/src/panels/debug.odin b/src/panels/debug.odin new file mode 100644 index 0000000..5886179 --- /dev/null +++ b/src/panels/debug.odin @@ -0,0 +1,140 @@ +package panels + +import "base:runtime" +import "core:mem" +import "core:fmt" +import "core:strings" +import "core:log" + +import "vendor:sdl2" + +import "../core" +import "../util" +import "../ui" + +make_debug_panel :: proc() -> core.Panel { + return core.Panel { + type = core.DebugPanel {}, + create = proc(panel: ^core.Panel, state: ^core.State) { + context.allocator = panel.allocator + + panel_state := &panel.type.(core.DebugPanel) + panel.input_map = core.new_input_map(show_help = true) + + panel_actions := core.new_input_actions(show_help = true) + register_default_panel_actions(&panel_actions) + core.register_ctrl_key_action(&panel.input_map.mode[.Normal], .W, panel_actions, "Panel Navigation") + }, + render = proc(panel: ^core.Panel, state: ^core.State) -> (ok: bool) { + if panel_state, ok := &panel.type.(core.DebugPanel); ok { + s := transmute(^ui.State)state.ui + + ui.open_element(s, nil, + { + dir = .TopToBottom, + kind = {ui.Fit{}, ui.Grow{}}, + }, + style = { + background_color = .Background1, + }, + ) + { + render_buffer_list(state, s) + + ui.open_element(s, nil, { + kind = {ui.Fit{}, ui.Exact(8)}, + }) + ui.close_element(s) + + render_panel_list(state, s) + } + ui.close_element(s) + } + + return true + } + } +} + +render_buffer_list :: proc(state: ^core.State, s: ^ui.State) { + ui.open_element(s, nil, + { + dir = .TopToBottom, + kind = {ui.Fit{}, ui.Fit{}}, + }, + style = { + background_color = .Background1, + }, + ) + { + ui.open_element(s, "Open Buffers", + { + kind = {ui.Grow{}, ui.Fit{}}, + }, + style = { + border = {.Bottom}, + border_color = .Background4, + } + ) + ui.close_element(s) + + ui.open_element(s, nil, { + kind = {ui.Fit{}, ui.Exact(8)}, + }) + ui.close_element(s) + + for i in 0.. UI_Layout { case Exact: { e.layout.size.x = int(v) } case Fit: { it := e.first - for child in iterate_siblings(state, &it) { - if child.layout.floating { continue } - switch e.layout.dir { - case .RightToLeft: fallthrough - case .LeftToRight: { - e.layout.size.x += child.layout.size.x - } + if it != nil { + for child in iterate_siblings(state, &it) { + if child.layout.floating { continue } - case .BottomToTop: fallthrough - case .TopToBottom: { - e.layout.size.x = math.max(e.layout.size.x, child.layout.size.x) + switch e.layout.dir { + case .RightToLeft: fallthrough + case .LeftToRight: { + e.layout.size.x += child.layout.size.x + } + + case .BottomToTop: fallthrough + case .TopToBottom: { + e.layout.size.x = math.max(e.layout.size.x, child.layout.size.x) + } } } + } else { + switch v in e.kind { + case UI_Element_Kind_Text: { + // FIXME: properly use font size + e.layout.size.x = len(v) * 12 + } + case UI_Element_Kind_Image: { + // TODO + } + case UI_Element_Kind_Custom: { } + } } } case Grow: { @@ -177,20 +191,35 @@ close_element :: proc(state: ^State, loc := #caller_location) -> UI_Layout { case Exact: { e.layout.size.y = int(v) } case Fit: { it := e.first - for child in iterate_siblings(state, &it) { - if child.layout.floating { continue } - switch e.layout.dir { - case .RightToLeft: fallthrough - case .LeftToRight: { - e.layout.size.y = math.max(e.layout.size.y, child.layout.size.y) - } + if it != nil { + for child in iterate_siblings(state, &it) { + if child.layout.floating { continue } - case .BottomToTop: fallthrough - case .TopToBottom: { - e.layout.size.y += child.layout.size.y + switch e.layout.dir { + case .RightToLeft: fallthrough + case .LeftToRight: { + e.layout.size.y = math.max(e.layout.size.y, child.layout.size.y) + } + + case .BottomToTop: fallthrough + case .TopToBottom: { + e.layout.size.y += child.layout.size.y + } } } + } else { + switch v in e.kind { + case UI_Element_Kind_Text: { + // TODO: wrap text + // FIXME: properly use font size + e.layout.size.y = 16 + } + case UI_Element_Kind_Image: { + // TODO + } + case UI_Element_Kind_Custom: { } + } } } case Grow: { @@ -316,7 +345,7 @@ grow_children :: proc(state: ^State, index: int) { } } - if num_growing.x > 0 || num_growing.y > 0 { + if true || num_growing.x > 0 || num_growing.y > 0 { remaining_size := [2]int{ x_e, y_e } - children_size to_grow: [2]int to_grow.x = 0 if num_growing.x < 1 else remaining_size.x/num_growing.x @@ -348,9 +377,9 @@ grow_children :: proc(state: ^State, index: int) { _, x_growing := child.layout.kind.x.(Grow) _, y_growing := child.layout.kind.y.(Grow) - if x_growing || y_growing || child.layout.floating { + // if x_growing || y_growing || child.layout.floating { grow_children(state, child_index) - } + // } } } }