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,
current_panel: Maybe(int),
last_panel: Maybe(int),
panels: util.StaticList(Panel),
buffers: util.StaticList(FileBuffer),
}
@ -150,6 +151,20 @@ current_buffer :: proc(state: ^State) -> ^FileBuffer {
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) {
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}
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
for {
if panel, ok := util.get(&state.panels, next_id).?; ok {
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
state.current_panel = panel.id
}
if attempt_switch_to_panel_buffer(state, panel, file_path, line, col) {
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
}
}

View File

@ -265,10 +265,6 @@ 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;

View File

@ -85,7 +85,13 @@ render_buffer_list :: proc(state: ^core.State, s: ^ui.State) {
for i in 0..<len(state.buffers.data) {
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.close_element(s)
}
@ -121,6 +127,13 @@ render_panel_list :: proc(state: ^core.State, s: ^ui.State) {
})
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) {
if panel, ok := util.get(&state.panels, i).?; ok {
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) {
},
create = proc(panel: ^core.Panel, state: ^core.State) {
state_allocator = context.allocator
context.allocator = panel.allocator
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)
if len(panel_state.file_path) == 0 {
// FIXME: don't allocate with the panel allocator
if buffer_id, _, ok := core.new_buffer(state); ok {
panel_state.buffer_id = buffer_id
} 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) {
open_grep_panel(state)
}, "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) {
core.register_key_action(input_map, .H, proc(state: ^core.State, user_data: rawptr) {
if current_panel, ok := state.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) {
if current_panel, ok := state.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)
}, "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) {
if current_panel, ok := state.current_panel.?; ok {
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) {
if panel_id, panel, ok := util.append_static_list(&state.panels, panel); ok && make_active {
panel.id = panel_id
state.current_panel = panel_id
arena_bytes, err := make([]u8, 1024*1024*8)
if err != nil {
@ -68,6 +83,7 @@ open :: proc(state: ^core.State, panel: core.Panel, make_active: bool = true) ->
panel->create(state)
core.switch_to_panel(state, panel_id)
core.reset_input_map(state)
return panel_id, true
@ -86,9 +102,12 @@ close :: proc(state: ^core.State, panel_id: int) {
util.delete(&state.panels, panel_id)
// TODO: keep track of the last active panel instead of focusing back to the first one
if first_active, ok := util.get_first_active_index(&state.panels).?; ok {
if last_panel, ok := state.last_panel.?; 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
} else {
// TODO: open panel
}
core.reset_input_map(state)