floating windows
parent
705606e92a
commit
2a4e85c868
|
@ -101,6 +101,7 @@ PanelType :: union {
|
|||
|
||||
FileBufferPanel :: struct {
|
||||
buffer: FileBuffer,
|
||||
viewed_symbol: Maybe(string),
|
||||
|
||||
// only used for initialization
|
||||
file_path: string,
|
||||
|
|
|
@ -59,39 +59,45 @@ draw :: proc(state: ^State) {
|
|||
new_ui.max_size.x = state.screen_width
|
||||
new_ui.max_size.y = state.screen_height
|
||||
|
||||
ui.open_element(new_ui, nil, {
|
||||
dir = .LeftToRight,
|
||||
kind = {ui.Grow{}, ui.Grow{}},
|
||||
})
|
||||
ui.open_element(new_ui, nil,
|
||||
{
|
||||
dir = .LeftToRight,
|
||||
kind = {ui.Grow{}, ui.Grow{}},
|
||||
},
|
||||
style = {
|
||||
background_color = .Background1
|
||||
}
|
||||
)
|
||||
{
|
||||
floating_panels := [16]int{}
|
||||
num_floating := 0
|
||||
|
||||
for i in 0..<len(state.panels.data) {
|
||||
if panel, ok := util.get(&state.panels, i).?; ok {
|
||||
if panel.render != nil {
|
||||
|
||||
background_color: theme.PaletteColor = .Background1 if panel.id == state.current_panel else .Background2
|
||||
|
||||
ui.open_element(new_ui, nil,
|
||||
{
|
||||
dir = .LeftToRight,
|
||||
kind = {ui.Grow{}, ui.Grow{}},
|
||||
},
|
||||
style = {
|
||||
border = {.Left, .Right, .Top, .Bottom },
|
||||
border_color = .Green,
|
||||
background_color = background_color,
|
||||
if panel.is_floating {
|
||||
if num_floating < len(floating_panels) {
|
||||
floating_panels[num_floating] = i
|
||||
num_floating += 1
|
||||
}
|
||||
)
|
||||
{
|
||||
} else {
|
||||
panel->render(state)
|
||||
}
|
||||
ui.close_element(new_ui)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..<num_floating {
|
||||
panel_id := floating_panels[i]
|
||||
|
||||
if panel, ok := util.get(&state.panels, panel_id).?; ok {
|
||||
panel->render(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
ui.close_element(new_ui)
|
||||
|
||||
ui.compute_layout_2(new_ui)
|
||||
ui.compute_layout(new_ui)
|
||||
ui.draw(new_ui, state)
|
||||
|
||||
// TODO: figure out when to not show the input help menu
|
||||
|
|
|
@ -69,6 +69,24 @@ make_file_buffer_panel :: proc(file_path: string, line: int = 0, col: int = 0) -
|
|||
s := transmute(^ui.State)state.ui
|
||||
render_file_buffer(state, s, &panel_state.buffer)
|
||||
|
||||
if viewed_symbol, ok := panel_state.viewed_symbol.?; ok {
|
||||
ui.open_element(s, nil,
|
||||
{
|
||||
dir = .TopToBottom,
|
||||
kind = {ui.Fit{}, ui.Fit{}},
|
||||
floating = true,
|
||||
},
|
||||
style = {
|
||||
background_color = .Background2,
|
||||
},
|
||||
)
|
||||
{
|
||||
ui.open_element(s, viewed_symbol, {})
|
||||
ui.close_element(s)
|
||||
}
|
||||
ui.close_element(s)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -143,10 +161,12 @@ render_file_buffer :: proc(state: ^core.State, s: ^ui.State, buffer: ^core.FileB
|
|||
|
||||
file_buffer_leader_actions :: proc(input_map: ^core.InputActions) {
|
||||
core.register_key_action(input_map, .K, proc(state: ^core.State, user_data: rawptr) {
|
||||
buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer
|
||||
panel := transmute(^core.Panel)user_data
|
||||
panel_state := &panel.type.(core.FileBufferPanel)
|
||||
buffer := &panel_state.buffer
|
||||
|
||||
ts.update_cursor(&buffer.tree, buffer.history.cursor.line, buffer.history.cursor.col)
|
||||
ts.print_node_type(&buffer.tree)
|
||||
panel_state.viewed_symbol = ts.print_node_type(&buffer.tree)
|
||||
|
||||
core.reset_input_map(state)
|
||||
}, "View Symbol")
|
||||
|
@ -260,6 +280,13 @@ file_buffer_input_actions :: proc(input_map: ^core.InputActions) {
|
|||
buffer.selection = core.new_selection(buffer.history.cursor);
|
||||
}, "enter visual mode");
|
||||
|
||||
core.register_key_action(input_map, .ESCAPE, proc(state: ^core.State, user_data: rawptr) {
|
||||
panel := transmute(^core.Panel)user_data
|
||||
panel_state := &panel.type.(core.FileBufferPanel)
|
||||
buffer := &panel_state.buffer
|
||||
|
||||
panel_state.viewed_symbol = nil
|
||||
});
|
||||
}
|
||||
|
||||
file_buffer_visual_actions :: proc(input_map: ^core.InputActions) {
|
||||
|
|
|
@ -48,6 +48,7 @@ make_grep_panel :: proc() -> core.Panel {
|
|||
|
||||
return core.Panel {
|
||||
type = core.GrepPanel {},
|
||||
is_floating = true,
|
||||
drop = proc(panel: ^core.Panel, state: ^core.State) {
|
||||
panel_state := &panel.type.(core.GrepPanel)
|
||||
|
||||
|
@ -147,10 +148,16 @@ make_grep_panel :: proc() -> core.Panel {
|
|||
if panel_state, ok := &panel.type.(core.GrepPanel); ok {
|
||||
s := transmute(^ui.State)state.ui
|
||||
|
||||
ui.open_element(s, nil, {
|
||||
dir = .TopToBottom,
|
||||
kind = {ui.Grow{}, ui.Grow{}}
|
||||
})
|
||||
ui.open_element(s, nil,
|
||||
{
|
||||
dir = .TopToBottom,
|
||||
kind = {ui.Grow{}, ui.Grow{}},
|
||||
floating = true,
|
||||
},
|
||||
style = {
|
||||
background_color = .Background1,
|
||||
},
|
||||
)
|
||||
{
|
||||
// query results and file contents side-by-side
|
||||
ui.open_element(s, nil, {
|
||||
|
@ -196,7 +203,7 @@ make_grep_panel :: proc() -> core.Panel {
|
|||
style.background_color = .Background2
|
||||
}
|
||||
|
||||
ui.open_element(s, result.file_path, {}, style)
|
||||
ui.open_element(s, result.file_path[len(state.directory):], {}, style)
|
||||
ui.close_element(s)
|
||||
}
|
||||
}
|
||||
|
@ -217,9 +224,14 @@ make_grep_panel :: proc() -> core.Panel {
|
|||
ui.close_element(s)
|
||||
|
||||
// text input
|
||||
ui.open_element(s, nil, {
|
||||
kind = {ui.Grow{}, ui.Exact(state.source_font_height)}
|
||||
})
|
||||
ui.open_element(s, nil,
|
||||
{
|
||||
kind = {ui.Grow{}, ui.Exact(state.source_font_height)}
|
||||
},
|
||||
style = {
|
||||
background_color = .Background2
|
||||
}
|
||||
)
|
||||
{
|
||||
defer ui.close_element(s)
|
||||
|
||||
|
|
|
@ -349,15 +349,15 @@ load_highlights :: proc(state: ^State) {
|
|||
}
|
||||
}
|
||||
|
||||
print_node_type :: proc(state: ^State) {
|
||||
print_node_type :: proc(state: ^State) -> Maybe(string) {
|
||||
if state.tree == nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
current_node := tree_cursor_current_node(&state.cursor)
|
||||
if node_is_null(current_node) {
|
||||
log.error("Current node is null after goto_first_child")
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
node_type_str := node_type(current_node)
|
||||
|
@ -376,4 +376,6 @@ print_node_type :: proc(state: ^State) {
|
|||
log.infof("Node position: (%d:%d) to (%d:%d)",
|
||||
start_point.row+1, start_point.column+1,
|
||||
end_point.row+1, end_point.column+1)
|
||||
|
||||
return string(node_type_str)
|
||||
}
|
120
src/ui/ui.odin
120
src/ui/ui.odin
|
@ -48,6 +48,8 @@ UI_Layout :: struct {
|
|||
kind: [2]UI_Size_Kind,
|
||||
size: [2]int,
|
||||
pos: [2]int,
|
||||
|
||||
floating: bool,
|
||||
}
|
||||
|
||||
UI_Size_Kind :: union {
|
||||
|
@ -82,8 +84,11 @@ open_element :: proc(state: ^State, kind: UI_Element_Kind, layout: UI_Layout, st
|
|||
layout = layout,
|
||||
style = style,
|
||||
}
|
||||
e.layout.pos = state.curr_elements[state.num_curr].layout.pos
|
||||
e.layout.size = state.curr_elements[state.num_curr].layout.size
|
||||
|
||||
if !e.layout.floating {
|
||||
e.layout.pos = state.curr_elements[state.num_curr].layout.pos
|
||||
e.layout.size = state.curr_elements[state.num_curr].layout.size
|
||||
}
|
||||
|
||||
if parent, ok := state.current_open_element.?; ok {
|
||||
e.parent = parent
|
||||
|
@ -130,9 +135,9 @@ close_element :: proc(state: ^State, loc := #caller_location) -> UI_Layout {
|
|||
|
||||
case Exact: { e.layout.size.x = int(v) }
|
||||
case Fit: {
|
||||
child_index := e.first
|
||||
for child_index != nil {
|
||||
child := &state.curr_elements[child_index.?]
|
||||
it := e.first
|
||||
for child in iterate_siblings(state, &it) {
|
||||
if child.layout.floating { continue }
|
||||
|
||||
switch e.layout.dir {
|
||||
case .RightToLeft: fallthrough
|
||||
|
@ -145,8 +150,6 @@ close_element :: proc(state: ^State, loc := #caller_location) -> UI_Layout {
|
|||
e.layout.size.x = math.max(e.layout.size.x, child.layout.size.x)
|
||||
}
|
||||
}
|
||||
|
||||
child_index = child.next
|
||||
}
|
||||
}
|
||||
case Grow: {
|
||||
|
@ -173,9 +176,9 @@ close_element :: proc(state: ^State, loc := #caller_location) -> UI_Layout {
|
|||
|
||||
case Exact: { e.layout.size.y = int(v) }
|
||||
case Fit: {
|
||||
child_index := e.first
|
||||
for child_index != nil {
|
||||
child := &state.curr_elements[child_index.?]
|
||||
it := e.first
|
||||
for child in iterate_siblings(state, &it) {
|
||||
if child.layout.floating { continue }
|
||||
|
||||
switch e.layout.dir {
|
||||
case .RightToLeft: fallthrough
|
||||
|
@ -188,8 +191,6 @@ close_element :: proc(state: ^State, loc := #caller_location) -> UI_Layout {
|
|||
e.layout.size.y += child.layout.size.y
|
||||
}
|
||||
}
|
||||
|
||||
child_index = child.next
|
||||
}
|
||||
}
|
||||
case Grow: { /* Done in the Grow pass */ }
|
||||
|
@ -206,18 +207,64 @@ close_element :: proc(state: ^State, loc := #caller_location) -> UI_Layout {
|
|||
}
|
||||
|
||||
@(private)
|
||||
non_fit_parent_size :: proc(state: ^State, index: int, axis: int) -> [2]int {
|
||||
iterate_siblings :: proc(state: ^State, sibling: ^Maybe(int)) -> (e: ^UI_Element, index: int, cond: bool) {
|
||||
if sibling == nil || sibling^ == nil {
|
||||
cond = false
|
||||
return
|
||||
}
|
||||
|
||||
e = &state.curr_elements[sibling.?]
|
||||
index = sibling.?
|
||||
cond = true
|
||||
|
||||
sibling^ = e.next
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@(private)
|
||||
iterate_siblings_reverse :: proc(state: ^State, sibling: ^Maybe(int)) -> (e: ^UI_Element, index: int, cond: bool) {
|
||||
if sibling == nil || sibling^ == nil {
|
||||
cond = false
|
||||
return
|
||||
}
|
||||
|
||||
e = &state.curr_elements[sibling.?]
|
||||
index = sibling.?
|
||||
cond = true
|
||||
|
||||
sibling^ = e.prev
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@(private)
|
||||
non_fit_parent_size :: proc(state: ^State, index: int, axis: int) -> int {
|
||||
if _, ok := state.curr_elements[index].layout.kind[axis].(Fit); ok {
|
||||
if parent_index, ok := state.curr_elements[index].parent.?; ok {
|
||||
if parent_index, ok := state.curr_elements[index].parent.?; ok && !state.curr_elements[index].layout.floating {
|
||||
return non_fit_parent_size(state, parent_index, axis)
|
||||
} else {
|
||||
return state.max_size
|
||||
return state.max_size[axis]
|
||||
}
|
||||
} else if state.curr_elements[index].layout.floating {
|
||||
return state.max_size[axis]
|
||||
} else {
|
||||
return state.curr_elements[index].layout.size
|
||||
return state.curr_elements[index].layout.size[axis]
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
prev_non_floating :: proc(state: ^State, index: Maybe(int)) -> Maybe(int) {
|
||||
it := index
|
||||
for sibling, index in iterate_siblings_reverse(state, &it) {
|
||||
if sibling.layout.floating { continue }
|
||||
|
||||
return index
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@(private)
|
||||
grow_children :: proc(state: ^State, index: int) {
|
||||
e := &state.curr_elements[index]
|
||||
|
@ -228,9 +275,14 @@ grow_children :: proc(state: ^State, index: int) {
|
|||
children_size: [2]int
|
||||
num_growing: [2]int
|
||||
|
||||
child_index := e.first
|
||||
for child_index != nil {
|
||||
child := &state.curr_elements[child_index.?]
|
||||
has_floating := false
|
||||
|
||||
it := e.first
|
||||
for child in iterate_siblings(state, &it) {
|
||||
if child.layout.floating {
|
||||
has_floating = true
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := child.layout.kind.x.(Grow); ok {
|
||||
num_growing.x += 1
|
||||
|
@ -258,37 +310,33 @@ grow_children :: proc(state: ^State, index: int) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
child_index = child.next
|
||||
}
|
||||
|
||||
if num_growing.x > 0 || num_growing.y > 0 {
|
||||
remaining_size := [2]int{ x_e.x, y_e.y } - children_size
|
||||
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
|
||||
to_grow.y = 0 if num_growing.y < 1 else remaining_size.y/num_growing.y
|
||||
|
||||
child_index := e.first
|
||||
for child_index != nil {
|
||||
child := &state.curr_elements[child_index.?]
|
||||
|
||||
it := e.first
|
||||
for child, child_index in iterate_siblings(state, &it) {
|
||||
switch e.layout.dir {
|
||||
case .RightToLeft: fallthrough
|
||||
case .LeftToRight: {
|
||||
if _, ok := child.layout.kind.x.(Grow); ok {
|
||||
child.layout.size.x = to_grow.x
|
||||
child.layout.size.x = state.max_size.x if child.layout.floating else to_grow.x
|
||||
}
|
||||
if _, ok := child.layout.kind.y.(Grow); ok {
|
||||
child.layout.size.y = remaining_size.y
|
||||
child.layout.size.y = state.max_size.y if child.layout.floating else y_e
|
||||
}
|
||||
}
|
||||
case .BottomToTop: fallthrough
|
||||
case .TopToBottom: {
|
||||
if _, ok := child.layout.kind.x.(Grow); ok {
|
||||
child.layout.size.x = remaining_size.x
|
||||
child.layout.size.x = state.max_size.x if child.layout.floating else x_e
|
||||
}
|
||||
if _, ok := child.layout.kind.y.(Grow); ok {
|
||||
child.layout.size.y = to_grow.y
|
||||
child.layout.size.y = state.max_size.y if child.layout.floating else to_grow.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -296,25 +344,23 @@ 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 {
|
||||
grow_children(state, child_index.?)
|
||||
if x_growing || y_growing || child.layout.floating {
|
||||
grow_children(state, child_index)
|
||||
}
|
||||
|
||||
child_index = child.next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compute_layout_2 :: proc(state: ^State) {
|
||||
compute_layout :: proc(state: ^State) {
|
||||
grow_children(state, 0)
|
||||
|
||||
for i in 0..<state.num_curr {
|
||||
e := &state.curr_elements[i]
|
||||
|
||||
if parent_index, ok := e.parent.?; ok {
|
||||
if parent_index, ok := e.parent.?; ok && !e.layout.floating {
|
||||
parent := &state.curr_elements[parent_index]
|
||||
|
||||
if prev_index, ok := e.prev.?; ok {
|
||||
if prev_index, ok := prev_non_floating(state, e.prev).?; ok {
|
||||
prev := &state.curr_elements[prev_index]
|
||||
|
||||
switch parent.layout.dir {
|
||||
|
|
Loading…
Reference in New Issue