helpers.go raw
1 package gel
2
3 import (
4 "errors"
5 "image"
6 "image/color"
7 "time"
8
9 "github.com/p9c/gio/f32"
10 "github.com/p9c/gio/io/system"
11 l "github.com/p9c/gio/layout"
12 "github.com/p9c/gio/op"
13 "github.com/p9c/gio/text"
14 )
15
16 // Defining these as types gives flexibility later to create methods that modify them
17
18 type Fonts map[string]text.Typeface
19 type Icons map[string]*Icon
20 type Collection []text.FontFace
21
22 func (c Collection) Font(font string) (out text.Font, e error) {
23 for i := range c {
24 if c[i].Font.Typeface == text.Typeface(font) {
25 out = c[i].Font
26 return
27 }
28 }
29 return out, errors.New("font " + font + " not found")
30
31 }
32
33 const Inf = 1e6
34
35 // Fill is a general fill function that covers the background of the current context space
36 func Fill(gtx l.Context, col color.NRGBA) l.Dimensions {
37 cs := gtx.Constraints
38 d := cs.Min
39 // dr := f32.Rectangle{
40 // Max: f32.Point{X: float32(d.X), Y: float32(d.Y)},
41 // }
42 // paint.ColorOp{Color: col}.Add(gtx.Ops)
43 // paint.PaintOp{Rect: dr}.Add(gtx.Ops)
44 fill(gtx, col, d, 0, 0)
45 return l.Dimensions{Size: d}
46 }
47
48 // func (th *Theme) GetFont(font string) *text.Font {
49 // for i := range th.collection {
50 // if th.collection[i].Font.Typeface == text.Typeface(font) {
51 // return &th.collection[i].Font
52 // }
53 // }
54 // return nil
55 // }
56
57 // func rgb(c uint32) color.RGBA {
58 // return argb(0xff000000 | c)
59 // }
60
61 func argb(c uint32) color.RGBA {
62 return color.RGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)}
63 }
64
65 // FPt converts an point to a f32.Point.
66 func Fpt(p image.Point) f32.Point {
67 return f32.Point{
68 X: float32(p.X), Y: float32(p.Y),
69 }
70 }
71
72 func axisPoint(a l.Axis, main, cross int) image.Point {
73 if a == l.Horizontal {
74 return image.Point{X: main, Y: cross}
75 } else {
76 return image.Point{X: cross, Y: main}
77 }
78 }
79
80 // axisConvert a point in (x, y) coordinates to (main, cross) coordinates,
81 // or vice versa. Specifically, Convert((x, y)) returns (x, y) unchanged
82 // for the horizontal axis, or (y, x) for the vertical axis.
83 func axisConvert(a l.Axis, pt image.Point) image.Point {
84 if a == l.Horizontal {
85 return pt
86 }
87 return image.Pt(pt.Y, pt.X)
88 }
89
90 func axisMain(a l.Axis, sz image.Point) int {
91 if a == l.Horizontal {
92 return sz.X
93 }
94 return sz.Y
95 }
96
97 func axisCross(a l.Axis, sz image.Point) int {
98 if a == l.Horizontal {
99 return sz.Y
100 }
101 return sz.X
102 }
103
104 func axisMainConstraint(a l.Axis, cs l.Constraints) (int, int) {
105 if a == l.Horizontal {
106 return cs.Min.X, cs.Max.X
107 }
108 return cs.Min.Y, cs.Max.Y
109 }
110
111 func axisCrossConstraint(a l.Axis, cs l.Constraints) (int, int) {
112 if a == l.Horizontal {
113 return cs.Min.Y, cs.Max.Y
114 }
115 return cs.Min.X, cs.Max.X
116 }
117
118 func axisConstraints(a l.Axis, mainMin, mainMax, crossMin, crossMax int) l.Constraints {
119 if a == l.Horizontal {
120 return l.Constraints{Min: image.Pt(mainMin, crossMin), Max: image.Pt(mainMax, crossMax)}
121 }
122 return l.Constraints{Min: image.Pt(crossMin, mainMin), Max: image.Pt(crossMax, mainMax)}
123 }
124
125 func EmptySpace(x, y int) func(gtx l.Context) l.Dimensions {
126 return func(gtx l.Context) l.Dimensions {
127 return l.Dimensions{
128 Size: image.Point{
129 X: x,
130 Y: y,
131 },
132 }
133 }
134 }
135
136 func EmptyFromSize(size image.Point) func(gtx l.Context) l.Dimensions {
137 return func(gtx l.Context) l.Dimensions {
138 return l.Dimensions{
139 Size: size,
140 }
141 }
142 }
143
144 func EmptyMaxWidth() func(gtx l.Context) l.Dimensions {
145 return func(gtx l.Context) l.Dimensions {
146 return l.Dimensions{
147 Size: image.Point{X: gtx.Constraints.Max.X, Y: gtx.Constraints.Min.Y},
148 Baseline: 0,
149 }
150 }
151 }
152 func EmptyMaxHeight() func(gtx l.Context) l.Dimensions {
153 return func(gtx l.Context) l.Dimensions {
154 return l.Dimensions{Size: image.Point{X: gtx.Constraints.Min.X, Y: gtx.Constraints.Min.Y}}
155 }
156 }
157
158 func EmptyMinWidth() func(gtx l.Context) l.Dimensions {
159 return func(gtx l.Context) l.Dimensions {
160 return l.Dimensions{
161 Size: image.Point{X: gtx.Constraints.Min.X, Y: gtx.Constraints.Min.Y},
162 Baseline: 0,
163 }
164 }
165 }
166 func EmptyMinHeight() func(gtx l.Context) l.Dimensions {
167 return func(gtx l.Context) l.Dimensions {
168 return l.Dimensions{Size: image.Point{Y: gtx.Constraints.Min.Y}}
169 }
170 }
171
172 // CopyContextDimensionsWithMaxAxis copies the dimensions out with the max set by an image.Point along the axis
173 func CopyContextDimensionsWithMaxAxis(gtx l.Context, axis l.Axis) l.Context {
174 ip := image.Point{}
175 if axis == l.Horizontal {
176 ip.Y = gtx.Constraints.Max.Y
177 ip.X = gtx.Constraints.Max.X
178 } else {
179 ip.Y = gtx.Constraints.Max.Y
180 ip.X = gtx.Constraints.Max.X
181 }
182 var ops op.Ops
183 gtx1 := l.NewContext(
184 &ops, system.FrameEvent{
185 Now: time.Now(),
186 Metric: gtx.Metric,
187 Size: ip,
188 },
189 )
190 if axis == l.Horizontal {
191 gtx1.Constraints.Min.X = 0
192 gtx1.Constraints.Min.Y = gtx.Constraints.Min.Y
193 } else {
194 gtx1.Constraints.Min.X = gtx.Constraints.Min.X
195 gtx1.Constraints.Min.Y = 0
196 }
197 return gtx1
198 }
199
200 // GetInfContext creates a context with infinite max constraints
201 func GetInfContext(gtx l.Context) l.Context {
202 ip := image.Point{}
203 ip.Y = Inf
204 ip.X = Inf
205 var ops op.Ops
206 gtx1 := l.NewContext(
207 &ops, system.FrameEvent{
208 Now: time.Now(),
209 Metric: gtx.Metric,
210 Size: ip,
211 },
212 )
213 return gtx1
214 }
215
216 func If(value bool, t, f l.Widget) l.Widget {
217 if value {
218 return t
219 } else {
220 return f
221 }
222 }
223
224 func (th *Theme) SliceToWidget(w []l.Widget, axis l.Axis) l.Widget {
225 var out *Flex
226 if axis == l.Horizontal {
227 out = th.Flex().AlignStart()
228 } else {
229 out = th.VFlex().AlignStart()
230 }
231 for i := range w {
232 out.Rigid(w[i])
233 }
234 return out.Fn
235 }
236