use "collections"
actor Label is Widget
"""
A text display widget that does not accept focus. Renders a single
line of text with configurable alignment within the widget's width.
"""
let _state: WidgetState
var _text: String val
var _fg: Color
var _bg: Color
var _align: Alignment
new create(
p: WidgetParent tag,
text: String val = "",
fg: Color = White,
bg: Color = Default,
align: Alignment = AlignStart)
=>
_state = WidgetState(p)
_text = text
_fg = fg
_bg = bg
_align = align
be set_text(text: String val) =>
"""
Update the label text and re-render.
"""
_text = text
render_and_send()
be set_color(fg: Color, bg: Color = Default) =>
"""
Update the label colors and re-render.
"""
_fg = fg
_bg = bg
render_and_send()
be set_align(align: Alignment) =>
"""
Set text alignment and re-render.
"""
_align = align
render_and_send()
// -- Widget required helpers --
fun ref state(): WidgetState => _state
fun ref render(): Grid =>
let w = _state.width
let h = _state.height
let text = _text
let fg = _fg
let bg = _bg
let text_len = text.size().min(w)
let offset = match _align
| AlignStart => USize(0)
| AlignCenter => (w - text_len) / 2
| AlignEnd => w - text_len
end
let empty = _state.empty_cell()
let cells = recover val
let size = w * h
let arr = Array[Cell](size)
for row in Range(0, h) do
for col in Range(0, w) do
let text_col = col - offset
if (row == 0) and (col >= offset) and (text_col < text_len) then
try
arr.push(Cell(text(text_col)?.u32(), 1, fg, bg, 0))
else
arr.push(empty)
end
else
arr.push(empty)
end
end
end
arr
end
GridFactory(w, h, cells)