1 package gel
2 3 import (
4 l "github.com/p9c/gio/layout"
5 "golang.org/x/exp/shiny/text"
6 )
7 8 // WrapList is a generalised layout for creating lists from widgets lined up in one axis and wrapped into lines across
9 // a given axis. It can be used for an icon view, for a text console cell grid, for laying out selectable text.
10 type WrapList struct {
11 *Window
12 list *List
13 widgets []l.Widget
14 axis l.Axis
15 dir text.Direction
16 }
17 18 // WrapList creates a new WrapList
19 func (w *Window) WrapList() *WrapList {
20 return &WrapList{
21 Window: w,
22 list: w.WidgetPool.GetList(),
23 }
24 }
25 26 // Axis sets the axis that will be scrollable
27 func (w *WrapList) Axis(axis l.Axis) *WrapList {
28 w.axis = axis
29 return w
30 }
31 32 // Direction sets the direction across the axis, for vertical, text.Forwards means left to right, text.Backwards means
33 // right to left, and for horizontal, text.Forwards means top to bottom, text.Backwards means bottom to top
34 func (w *WrapList) Direction(dir text.Direction) *WrapList {
35 w.dir = dir
36 return w
37 }
38 39 // Widgets loads a set of widgets into the WrapList
40 func (w *WrapList) Widgets(widgets []l.Widget) *WrapList {
41 w.widgets = widgets
42 return w
43 }
44 45 // Fn renders the WrapList in the current context
46 // todo: this needs to be cached and have a hook in the WrapList.Widgets method to trigger generation
47 func (w *WrapList) Fn(gtx l.Context) l.Dimensions {
48 // first get the dimensions of the widget list
49 if len(w.widgets) > 0 {
50 le := func(gtx l.Context, index int) l.Dimensions {
51 dims := w.widgets[index](gtx)
52 return dims
53 }
54 gtx1 := CopyContextDimensionsWithMaxAxis(gtx, w.axis)
55 // generate the dimensions for all the list elements
56 allDims := GetDimensionList(gtx1, len(w.widgets), le)
57 var out = [][]l.Widget{{}}
58 cursor := 0
59 runningTotal := 0
60 _, width := axisCrossConstraint(w.axis, gtx.Constraints)
61 for i := range allDims {
62 runningTotal += axisCross(w.axis, allDims[i].Size)
63 if runningTotal > width {
64 cursor++
65 runningTotal = 0
66 out = append(out, []l.Widget{})
67 }
68 out[cursor] = append(out[cursor], w.widgets[i])
69 }
70 le2 := func(gtx l.Context, index int) l.Dimensions {
71 o := w.Flex().AlignStart()
72 if w.axis == l.Horizontal {
73 o = w.VFlex().AlignStart()
74 }
75 // for _, y := range out {
76 y := out[index]
77 var outRow []l.Widget
78 for j, x := range y {
79 if w.dir == text.Forwards {
80 outRow = append(outRow, x)
81 } else {
82 outRow = append(outRow, y[len(y)-1-j])
83 }
84 }
85 for i := range outRow {
86 o.Rigid(outRow[i])
87 }
88 // }
89 return o.Fn(gtx)
90 }
91 return w.list.Vertical().Length(len(out)).ListElement(le2).Fn(gtx)
92 } else {
93 return l.Dimensions{}
94 }
95 }
96