v0.1.0 initial commit
This commit is contained in:
+99
@@ -0,0 +1,99 @@
|
||||
package tui
|
||||
|
||||
import "github.com/lixenwraith/terminal"
|
||||
|
||||
// ListItem represents a single row in a scrollable list
|
||||
type ListItem struct {
|
||||
Indent int // Left padding in cells
|
||||
Icon rune // Expand indicator or bullet, 0 = none
|
||||
IconFg terminal.RGB
|
||||
Check CheckState // CheckNone to skip checkbox
|
||||
CheckFg terminal.RGB
|
||||
Text string
|
||||
TextStyle Style
|
||||
}
|
||||
|
||||
// ListOpts configures list rendering
|
||||
type ListOpts struct {
|
||||
CursorBg terminal.RGB
|
||||
DefaultBg terminal.RGB
|
||||
IconWidth int // Width reserved for icon, default 2
|
||||
}
|
||||
|
||||
// List renders scrollable list items within region, returns number of rows rendered
|
||||
func (r Region) List(items []ListItem, cursor, scroll int, opts ListOpts) int {
|
||||
if r.H < 1 || len(items) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
iconW := opts.IconWidth
|
||||
if iconW == 0 {
|
||||
iconW = 2
|
||||
}
|
||||
|
||||
rendered := 0
|
||||
for y := 0; y < r.H; y++ {
|
||||
idx := scroll + y
|
||||
if idx >= len(items) {
|
||||
break
|
||||
}
|
||||
|
||||
item := items[idx]
|
||||
isCursor := idx == cursor
|
||||
|
||||
// Row background
|
||||
bg := opts.DefaultBg
|
||||
if isCursor {
|
||||
bg = opts.CursorBg
|
||||
}
|
||||
|
||||
// Clear row
|
||||
for x := 0; x < r.W; x++ {
|
||||
r.Cell(x, y, ' ', terminal.RGB{}, bg, terminal.AttrNone)
|
||||
}
|
||||
|
||||
x := item.Indent
|
||||
|
||||
// Icon
|
||||
if item.Icon != 0 && x < r.W {
|
||||
r.Cell(x, y, item.Icon, item.IconFg, bg, terminal.AttrNone)
|
||||
}
|
||||
x += iconW
|
||||
|
||||
// Checkbox
|
||||
if item.Check != CheckNone || item.CheckFg != (terminal.RGB{}) {
|
||||
if x+3 <= r.W {
|
||||
var ch rune
|
||||
switch item.Check {
|
||||
case CheckNone:
|
||||
ch = ' '
|
||||
case CheckPartial:
|
||||
ch = 'o'
|
||||
case CheckFull:
|
||||
ch = 'x'
|
||||
case CheckPlus:
|
||||
ch = '+'
|
||||
}
|
||||
r.Cell(x, y, '[', item.CheckFg, bg, terminal.AttrNone)
|
||||
r.Cell(x+1, y, ch, item.CheckFg, bg, terminal.AttrNone)
|
||||
r.Cell(x+2, y, ']', item.CheckFg, bg, terminal.AttrNone)
|
||||
}
|
||||
x += 4
|
||||
}
|
||||
|
||||
// Text
|
||||
textStyle := item.TextStyle
|
||||
if textStyle.Bg == (terminal.RGB{}) {
|
||||
textStyle.Bg = bg
|
||||
}
|
||||
text := item.Text
|
||||
if x+RuneLen(text) > r.W {
|
||||
text = Truncate(text, r.W-x)
|
||||
}
|
||||
r.TextStyled(x, y, text, textStyle)
|
||||
|
||||
rendered++
|
||||
}
|
||||
|
||||
return rendered
|
||||
}
|
||||
Reference in New Issue
Block a user