properly switch to last panel after floating panel

main
Patrick Cleaveliln 2025-08-02 19:20:00 +00:00
parent d27c566ff1
commit f6b7d30e38
5 changed files with 82 additions and 19 deletions

View File

@ -50,6 +50,7 @@ State :: struct {
command_args: [dynamic]EditorCommandArgument, command_args: [dynamic]EditorCommandArgument,
current_panel: Maybe(int), current_panel: Maybe(int),
last_panel: Maybe(int),
panels: util.StaticList(Panel), panels: util.StaticList(Panel),
buffers: util.StaticList(FileBuffer), buffers: util.StaticList(FileBuffer),
} }
@ -150,6 +151,20 @@ current_buffer :: proc(state: ^State) -> ^FileBuffer {
return nil return nil
} }
switch_to_panel :: proc(state: ^State, panel_id: int) {
if panel, ok := util.get(&state.panels, panel_id).?; ok {
if current_panel, ok := state.current_panel.?; ok {
if current_panel, ok := util.get(&state.panels, current_panel).?; ok {
if !current_panel.is_floating {
state.last_panel = state.current_panel
}
}
}
state.current_panel = panel_id
}
}
new_buffer_virtual :: proc(state: ^State) -> (id: int, buffer: ^FileBuffer, ok: bool) { new_buffer_virtual :: proc(state: ^State) -> (id: int, buffer: ^FileBuffer, ok: bool) {
return util.append(&state.buffers, new_virtual_file_buffer(context.allocator)) return util.append(&state.buffers, new_virtual_file_buffer(context.allocator))
} }
@ -178,19 +193,37 @@ new_buffer_file :: proc(state: ^State, file_path: string, line: int = 0, col: in
new_buffer :: proc{new_buffer_file, new_buffer_virtual} new_buffer :: proc{new_buffer_file, new_buffer_virtual}
open_buffer_file :: proc(state: ^State, file_path: string, line: int = 0, col: int = 0) { open_buffer_file :: proc(state: ^State, file_path: string, line: int = 0, col: int = 0) {
attempt_switch_to_panel_buffer :: proc(state: ^State, panel: ^Panel, file_path: string, line: int, col: int) -> bool {
if type, ok := &panel.type.(FileBufferPanel); ok {
buffer_id, _, ok := new_buffer_file(state, file_path, line, col)
if ok {
type.buffer_id = buffer_id
switch_to_panel(state, panel.id)
return true
}
}
return false
}
if last_panel, ok := state.last_panel.?; ok {
if panel, ok := util.get(&state.panels, last_panel).?; ok {
if attempt_switch_to_panel_buffer(state, panel, file_path, line, col) {
return
}
}
}
next_id := 0 next_id := 0
for { for {
if panel, ok := util.get(&state.panels, next_id).?; ok { if panel, ok := util.get(&state.panels, next_id).?; ok {
if type, ok := &panel.type.(FileBufferPanel); ok { if attempt_switch_to_panel_buffer(state, panel, file_path, line, col) {
buffer_id, _, ok := new_buffer_file(state, file_path, line, col)
if ok {
type.buffer_id = buffer_id
state.current_panel = panel.id
}
break break
} else { }
next_id := util.get_next(&state.panels, next_id)
if id, ok := util.get_next(&state.panels, next_id).?; ok {
next_id = id
continue continue
} }
} }

View File

@ -265,10 +265,6 @@ main :: proc() {
panels.open(&state, panels.make_file_buffer_panel("")) 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 { if sdl2.Init({.VIDEO}) < 0 {
log.error("SDL failed to initialize:", sdl2.GetError()); log.error("SDL failed to initialize:", sdl2.GetError());
return; return;

View File

@ -85,7 +85,13 @@ render_buffer_list :: proc(state: ^core.State, s: ^ui.State) {
for i in 0..<len(state.buffers.data) { for i in 0..<len(state.buffers.data) {
if buffer, ok := util.get(&state.buffers, i).?; ok { if buffer, ok := util.get(&state.buffers, i).?; ok {
buffer_label := fmt.tprintf("buf '%v' - %v", i, buffer.file_path[len(state.directory):]) buffer_label: string
if len(buffer.file_path) > len(state.directory) {
buffer_label = fmt.tprintf("buf '%v' - %v", i, buffer.file_path[len(state.directory):])
} else {
buffer_label = fmt.tprintf("buf '%v' - %v", i, buffer.file_path)
}
ui.open_element(s, buffer_label, {}) ui.open_element(s, buffer_label, {})
ui.close_element(s) ui.close_element(s)
} }
@ -121,6 +127,13 @@ render_panel_list :: proc(state: ^core.State, s: ^ui.State) {
}) })
ui.close_element(s) ui.close_element(s)
if state.last_panel != nil {
last_panel_label := fmt.tprintf("last panel id '%v'", state.last_panel.?)
ui.open_element(s, last_panel_label, {})
ui.close_element(s)
}
for i in 0..<len(state.panels.data) { for i in 0..<len(state.panels.data) {
if panel, ok := util.get(&state.panels, i).?; ok { if panel, ok := util.get(&state.panels, i).?; ok {
info: string info: string

View File

@ -43,6 +43,7 @@ make_file_buffer_panel :: proc(file_path: string, line: int = 0, col: int = 0) -
drop = proc(panel: ^core.Panel, state: ^core.State) { drop = proc(panel: ^core.Panel, state: ^core.State) {
}, },
create = proc(panel: ^core.Panel, state: ^core.State) { create = proc(panel: ^core.Panel, state: ^core.State) {
state_allocator = context.allocator
context.allocator = panel.allocator context.allocator = panel.allocator
panel_state := &panel.type.(core.FileBufferPanel) panel_state := &panel.type.(core.FileBufferPanel)
@ -58,6 +59,7 @@ make_file_buffer_panel :: proc(file_path: string, line: int = 0, col: int = 0) -
panel_state.search_buffer = core.new_virtual_file_buffer(panel.allocator) panel_state.search_buffer = core.new_virtual_file_buffer(panel.allocator)
if len(panel_state.file_path) == 0 { if len(panel_state.file_path) == 0 {
// FIXME: don't allocate with the panel allocator
if buffer_id, _, ok := core.new_buffer(state); ok { if buffer_id, _, ok := core.new_buffer(state); ok {
panel_state.buffer_id = buffer_id panel_state.buffer_id = buffer_id
} else { } else {

View File

@ -21,13 +21,23 @@ register_default_leader_actions :: proc(input_map: ^core.InputActions) {
core.register_key_action(input_map, .R, proc(state: ^core.State, user_data: rawptr) { core.register_key_action(input_map, .R, proc(state: ^core.State, user_data: rawptr) {
open_grep_panel(state) open_grep_panel(state)
}, "Grep Workspace") }, "Grep Workspace")
core.register_key_action(input_map, .COMMA, proc(state: ^core.State, user_data: rawptr) {
current_panel := state.current_panel
open(state, make_debug_panel())
state.current_panel = current_panel
core.reset_input_map(state)
}, "DEBUG WINDOW")
} }
register_default_panel_actions :: proc(input_map: ^core.InputActions) { register_default_panel_actions :: proc(input_map: ^core.InputActions) {
core.register_key_action(input_map, .H, proc(state: ^core.State, user_data: rawptr) { core.register_key_action(input_map, .H, proc(state: ^core.State, user_data: rawptr) {
if current_panel, ok := state.current_panel.?; ok { if current_panel, ok := state.current_panel.?; ok {
if prev, ok := util.get_prev(&state.panels, current_panel).?; ok { if prev, ok := util.get_prev(&state.panels, current_panel).?; ok {
state.current_panel = prev core.switch_to_panel(state, prev)
} }
} }
@ -36,13 +46,19 @@ register_default_panel_actions :: proc(input_map: ^core.InputActions) {
core.register_key_action(input_map, .L, proc(state: ^core.State, user_data: rawptr) { core.register_key_action(input_map, .L, proc(state: ^core.State, user_data: rawptr) {
if current_panel, ok := state.current_panel.?; ok { if current_panel, ok := state.current_panel.?; ok {
if next, ok := util.get_next(&state.panels, current_panel).?; ok { if next, ok := util.get_next(&state.panels, current_panel).?; ok {
state.current_panel = next core.switch_to_panel(state, next)
} }
} }
core.reset_input_map(state) core.reset_input_map(state)
}, "focus panel to the right"); }, "focus panel to the right");
core.register_key_action(input_map, .V, proc(state: ^core.State, user_data: rawptr) {
open(state, make_file_buffer_panel(""))
core.reset_input_map(state)
}, "Split Panel");
core.register_key_action(input_map, .Q, proc(state: ^core.State, user_data: rawptr) { core.register_key_action(input_map, .Q, proc(state: ^core.State, user_data: rawptr) {
if current_panel, ok := state.current_panel.?; ok { if current_panel, ok := state.current_panel.?; ok {
close(state, current_panel) close(state, current_panel)
@ -54,7 +70,6 @@ register_default_panel_actions :: proc(input_map: ^core.InputActions) {
open :: proc(state: ^core.State, panel: core.Panel, make_active: bool = true) -> (panel_id: int, ok: bool) { open :: proc(state: ^core.State, panel: core.Panel, make_active: bool = true) -> (panel_id: int, ok: bool) {
if panel_id, panel, ok := util.append_static_list(&state.panels, panel); ok && make_active { if panel_id, panel, ok := util.append_static_list(&state.panels, panel); ok && make_active {
panel.id = panel_id panel.id = panel_id
state.current_panel = panel_id
arena_bytes, err := make([]u8, 1024*1024*8) arena_bytes, err := make([]u8, 1024*1024*8)
if err != nil { if err != nil {
@ -68,6 +83,7 @@ open :: proc(state: ^core.State, panel: core.Panel, make_active: bool = true) ->
panel->create(state) panel->create(state)
core.switch_to_panel(state, panel_id)
core.reset_input_map(state) core.reset_input_map(state)
return panel_id, true return panel_id, true
@ -86,9 +102,12 @@ close :: proc(state: ^core.State, panel_id: int) {
util.delete(&state.panels, panel_id) util.delete(&state.panels, panel_id)
// TODO: keep track of the last active panel instead of focusing back to the first one if last_panel, ok := state.last_panel.?; ok {
if first_active, ok := util.get_first_active_index(&state.panels).?; ok { core.switch_to_panel(state, last_panel)
} else if first_active, ok := util.get_first_active_index(&state.panels).?; ok {
state.current_panel = first_active state.current_panel = first_active
} else {
// TODO: open panel
} }
core.reset_input_map(state) core.reset_input_map(state)