panel.lua
local terminal = require("terminal")
local Panel = require("terminal.ui.panel")
local function draw_content(self, text, color)
color = color or "white"
local row, col = self.inner_row, self.inner_col
local height, width = self.inner_height, self.inner_width
local text_row = row + math.floor(height / 2)
local text_col = col + math.floor((width - #text) / 2)
terminal.cursor.position.set(text_row, text_col)
terminal.output.write(terminal.text.stack.push_seq({ fg = color }))
terminal.output.write(text)
terminal.output.write(terminal.text.stack.pop_seq())
end
local screen_resized do
local last_rows, last_cols = terminal.size()
function screen_resized()
local current_rows, current_cols = last_rows, last_cols
last_rows, last_cols = terminal.size()
return current_rows ~= last_rows or current_cols ~= last_cols
end
end
local function create_fullscreen_panel(content_func)
return Panel {
content = content_func,
border = {
format = terminal.draw.box_fmt.single,
title = ""
}
}
end
local function run_example_1()
terminal.clear.screen()
terminal.cursor.position.set(1, 1)
local rows, cols = terminal.size()
local simple_panel = create_fullscreen_panel(function(self)
draw_content(self, "Hello World! Press any key to continue...", "green")
end)
simple_panel:calculate_layout(1, 1, rows, cols)
simple_panel:render()
while not terminal.input.readansi(0.1) do
if screen_resized() then
rows, cols = terminal.size()
simple_panel:calculate_layout(1, 1, rows, cols)
simple_panel:render()
end
end
end
local function run_example_2()
terminal.clear.screen()
terminal.cursor.position.set(1, 1)
local rows, cols = terminal.size()
local horizontal_panel = Panel {
orientation = Panel.orientations.horizontal,
split_ratio = 0.6, children = {
Panel {
content = function(self)
draw_content(self, "60% - Press any key", "blue")
end,
border = {
format = terminal.draw.box_fmt.double,
attr = { fg = "blue" },
title = "Left Panel"
},
},
Panel {
content = function(self)
draw_content(self, "40%", "red")
end,
border = {
format = terminal.draw.box_fmt.double,
attr = { fg = "red" },
title = "Right Panel"
},
}
}
}
horizontal_panel:calculate_layout(1, 1, rows, cols)
horizontal_panel:render()
while not terminal.input.readansi(0.1) do
if screen_resized() then
rows, cols = terminal.size()
horizontal_panel:calculate_layout(1, 1, rows, cols)
horizontal_panel:render()
end
end
end
local function run_example_3()
terminal.clear.screen()
terminal.cursor.position.set(1, 1)
local rows, cols = terminal.size()
local vertical_panel = Panel {
orientation = Panel.orientations.vertical,
split_ratio = 0.4, children = {
Panel {
content = function(self)
draw_content(self, "40% - Press any key", "yellow")
end,
border = {
format = terminal.draw.box_fmt.single,
attr = { fg = "yellow" },
title = "Top Panel"
},
},
Panel {
content = function(self)
draw_content(self, "60%", "magenta")
end,
border = {
format = terminal.draw.box_fmt.single,
attr = { fg = "magenta" },
title = "Bottom Panel"
},
}
}
}
vertical_panel:calculate_layout(1, 1, rows, cols)
vertical_panel:render()
while not terminal.input.readansi(0.1) do
if screen_resized() then
rows, cols = terminal.size()
vertical_panel:calculate_layout(1, 1, rows, cols)
vertical_panel:render()
end
end
end
local function run_example_4()
terminal.clear.screen()
terminal.cursor.position.set(1, 1)
local fmt_top_left = terminal.draw.box_fmt.copy(terminal.draw.box_fmt.single)
fmt_top_left.tr = "┬" fmt_top_left.b = "" fmt_top_left.bl = fmt_top_left.l fmt_top_left.br = fmt_top_left.l
local fmt_bottom_left = terminal.draw.box_fmt.copy(terminal.draw.box_fmt.single)
fmt_bottom_left.tl = "├" fmt_bottom_left.tr = "┤" fmt_bottom_left.br = "┴"
local fmt_right = terminal.draw.box_fmt.copy(terminal.draw.box_fmt.single)
fmt_right.l = "" fmt_right.tl = fmt_right.t fmt_right.bl = fmt_right.b
local rows, cols = terminal.size()
local nested_panel = Panel {
orientation = Panel.orientations.horizontal,
split_ratio = 0.5,
children = {
Panel {
orientation = Panel.orientations.vertical,
split_ratio = 0.3,
children = {
Panel {
content = function(self)
draw_content(self, "30%", "cyan")
end,
border = {
format = fmt_top_left,
attr = { fg = "cyan" },
title = "Top Left"
},
},
Panel {
content = function(self)
draw_content(self, "70%", "green")
end,
border = {
format = fmt_bottom_left,
attr = { fg = "green" },
title = "Bottom Left"
},
}
}
},
Panel {
content = function(self)
draw_content(self, "Full Right - Press any key", "red")
end,
border = {
format = fmt_right,
attr = { fg = "red" },
title = "Right Side"
},
}
}
}
nested_panel:calculate_layout(1, 1, rows, cols)
nested_panel:render()
while not terminal.input.readansi(0.1) do
if screen_resized() then
rows, cols = terminal.size()
nested_panel:calculate_layout(1, 1, rows, cols)
nested_panel:render()
end
end
end
local function run_example_5()
terminal.clear.screen()
terminal.cursor.position.set(1, 1)
local resizable_panel = Panel {
orientation = Panel.orientations.horizontal,
split_ratio = 0.5,
children = {
Panel {
content = function(self)
draw_content(self, "50%", "blue")
end,
border = {
format = terminal.draw.box_fmt.single,
attr = { fg = "blue" },
title = "Panel A"
},
},
Panel {
content = function(self)
draw_content(self, "50% - Press any key", "red")
end,
border = {
format = terminal.draw.box_fmt.single,
attr = { fg = "red" },
title = "Panel B"
},
}
}
}
for ratio = 0.2, 0.8, 0.2 do
terminal.clear.screen()
terminal.cursor.position.set(1, 1)
local current_rows, current_cols = terminal.size()
resizable_panel:set_split_ratio(ratio)
resizable_panel:calculate_layout(1, 1, current_rows, current_cols)
resizable_panel:render()
terminal.cursor.position.set(current_rows - 1, 1)
terminal.output.write("Split ratio: " .. string.format("%.1f", ratio) .. " - Press any key to continue...")
end
while not terminal.input.readansi(0.1) do
if screen_resized() then
local rows, cols = terminal.size()
resizable_panel:calculate_layout(1, 1, rows, cols)
resizable_panel:render()
end
end
end
local function run_example_6()
terminal.clear.screen()
terminal.cursor.position.set(1, 1)
local rows, cols = terminal.size()
local constrained_panel = Panel {
orientation = Panel.orientations.horizontal,
children = {
Panel {
min_width = math.max(15, math.floor(cols * 0.3)), content = function(self)
draw_content(self, "Min: " .. math.max(15, math.floor(cols * 0.3)), "green")
end,
border = {
format = terminal.draw.box_fmt.double,
attr = { fg = "green" },
title = "Min Width"
},
},
Panel {
max_width = math.min(20, math.floor(cols * 0.7)), content = function(self)
draw_content(self, "Max: " .. math.min(20, math.floor(cols * 0.7)) .. " - Press any key", "red")
end,
border = {
format = terminal.draw.box_fmt.double,
attr = { fg = "red" },
title = "Max Width"
},
}
}
}
constrained_panel:calculate_layout(1, 1, rows, cols)
constrained_panel:render()
while not terminal.input.readansi(0.1) do
if screen_resized() then
local rows, cols = terminal.size()
constrained_panel:calculate_layout(1, 1, rows, cols)
constrained_panel:render()
end
end
end
local function main()
run_example_1()
run_example_2()
run_example_3()
run_example_4()
run_example_5()
run_example_6()
end
main = terminal.initwrap(main, {
displaybackup = true,
filehandle = io.stderr
})
main()
print("Panel examples completed!")