Files
musicplayer/src/musicplayer/ui/plot.gleam
2025-12-26 11:56:24 +01:00

86 lines
2.0 KiB
Gleam

import gleam/dict.{type Dict}
import gleam/list
import gleam/string
pub type Buffer =
Dict(#(Int, Int), String)
pub fn flush_buffer(buffer: Buffer, columns: Int, rows: Int) -> String {
list.range(1, rows)
|> list.map(fn(y) {
list.range(1, columns)
|> list.map(fn(x) {
case dict.get(buffer, #(x, y)) {
Ok(char) -> char
Error(_) -> " "
}
})
|> string.join("")
})
|> string.join("\r\n")
}
pub fn text(buffer: Buffer, text: String, x: Int, y: Int) -> Buffer {
text
|> string.to_graphemes
|> list.index_fold(buffer, fn(acc, char, i) {
dict.insert(acc, #(x + i, y), char)
})
}
pub fn box(buffer: Buffer, x: Int, y: Int, width: Int, height: Int) -> Buffer {
// TODO move box style to `layout.Style`
let box_chars = #("", "", "", "", "", "")
let #(tl, tr, bl, br, hor, ver) = box_chars
case width < 2 || height < 2 {
True -> buffer
False -> {
buffer
|> dict.insert(#(x, y), tl)
|> dict.insert(#(x + width - 1, y), tr)
|> dict.insert(#(x, y + height - 1), bl)
|> dict.insert(#(x + width - 1, y + height - 1), br)
|> horizontal_line(x + 1, y, width - 2, hor)
|> horizontal_line(x + 1, y + height - 1, width - 2, hor)
|> vertical_line(x, y + 1, height - 2, ver)
|> vertical_line(x + width - 1, y + 1, height - 2, ver)
}
}
}
pub fn box_with_heading(
buffer: Buffer,
x: Int,
y: Int,
width: Int,
height: Int,
heading: String,
) -> Buffer {
let heading_margin = 1
box(buffer, x, y, width, height)
|> text(heading, x + heading_margin, y)
}
fn horizontal_line(
buffer: Buffer,
x: Int,
y: Int,
len: Int,
char: String,
) -> Buffer {
list.range(0, len - 1)
|> list.fold(buffer, fn(acc, i) { dict.insert(acc, #(x + i, y), char) })
}
fn vertical_line(
buffer: Buffer,
x: Int,
y: Int,
len: Int,
char: String,
) -> Buffer {
list.range(0, len - 1)
|> list.fold(buffer, fn(acc, i) { dict.insert(acc, #(x, y + i), char) })
}