Files
prevara/wraplist.go
2025-11-30 16:45:22 +00:00

96 lines
2.6 KiB
Go

package gel
import (
l "github.com/p9c/p9/pkg/gel/gio/layout"
"golang.org/x/exp/shiny/text"
)
// WrapList is a generalised layout for creating lists from widgets lined up in one axis and wrapped into lines across
// a given axis. It can be used for an icon view, for a text console cell grid, for laying out selectable text.
type WrapList struct {
*Window
list *List
widgets []l.Widget
axis l.Axis
dir text.Direction
}
// WrapList creates a new WrapList
func (w *Window) WrapList() *WrapList {
return &WrapList{
Window: w,
list: w.WidgetPool.GetList(),
}
}
// Axis sets the axis that will be scrollable
func (w *WrapList) Axis(axis l.Axis) *WrapList {
w.axis = axis
return w
}
// Direction sets the direction across the axis, for vertical, text.Forwards means left to right, text.Backwards means
// right to left, and for horizontal, text.Forwards means top to bottom, text.Backwards means bottom to top
func (w *WrapList) Direction(dir text.Direction) *WrapList {
w.dir = dir
return w
}
// Widgets loads a set of widgets into the WrapList
func (w *WrapList) Widgets(widgets []l.Widget) *WrapList {
w.widgets = widgets
return w
}
// Fn renders the WrapList in the current context
// todo: this needs to be cached and have a hook in the WrapList.Widgets method to trigger generation
func (w *WrapList) Fn(gtx l.Context) l.Dimensions {
// first get the dimensions of the widget list
if len(w.widgets) > 0 {
le := func(gtx l.Context, index int) l.Dimensions {
dims := w.widgets[index](gtx)
return dims
}
gtx1 := CopyContextDimensionsWithMaxAxis(gtx, w.axis)
// generate the dimensions for all the list elements
allDims := GetDimensionList(gtx1, len(w.widgets), le)
var out = [][]l.Widget{{}}
cursor := 0
runningTotal := 0
_, width := axisCrossConstraint(w.axis, gtx.Constraints)
for i := range allDims {
runningTotal += axisCross(w.axis, allDims[i].Size)
if runningTotal > width {
cursor++
runningTotal = 0
out = append(out, []l.Widget{})
}
out[cursor] = append(out[cursor], w.widgets[i])
}
le2 := func(gtx l.Context, index int) l.Dimensions {
o := w.Flex().AlignStart()
if w.axis == l.Horizontal {
o = w.VFlex().AlignStart()
}
// for _, y := range out {
y := out[index]
var outRow []l.Widget
for j, x := range y {
if w.dir == text.Forwards {
outRow = append(outRow, x)
} else {
outRow = append(outRow, y[len(y)-1-j])
}
}
for i := range outRow {
o.Rigid(outRow[i])
}
// }
return o.Fn(gtx)
}
return w.list.Vertical().Length(len(out)).ListElement(le2).Fn(gtx)
} else {
return l.Dimensions{}
}
}