Flexbox
Flexbox is a high level positioning plugin that allows for dynamic positioning of elements based apon container sizing. To learn more about flexbox refer to this MDN article, in this document we will go into the impleamentation of flexbox rather than the usage of it.
"display": "flex", "justify-content": "*", "align-content": "*", "align-items": "*", "flex-wrap": "*", "flex-direction": "*",
# Flex Properties
justify-content | align-content | align-items | flex-wrap | flex-direction |
---|---|---|---|---|
normal | normal | normal | nowrap | row |
center | center | center | wrap | column |
flex-start | flex-start | flex-start | row-reverse | |
flex-end | flex-end | flex-end | column-reverse | |
space-between | space-between | stretch | ||
space-around | space-around | baseline | ||
space-evenly | stretch |
# order?(go)
asd
1package flex
2
3import (
4 "gui/cstyle"
5 "gui/element"
6 "gui/utils"
7 "slices"
8 "strings"
9)
10
11func Init() cstyle.Plugin {
12 return cstyle.Plugin{
13 Styles: map[string]string{
14 "display": "flex",
15 "justify-content": "*",
16 "align-content": "*",
17 "align-items": "*",
18 "flex-wrap": "*",
19 "flex-direction": "*",
20 },
21 Level: 2,
22 Handler: func(n *element.Node, state *map[string]element.State) {
23 s := *state
24 self := s[n.Properties.Id]
25
26 // Brief: justify does not align the bottom row correctly
27 // y axis also needs to be done
28 verbs := strings.Split(n.Style["flex-direction"], "-")
29
30 orderedNode := order(*n, state, n.Children, verbs[0], len(verbs) > 1, n.Style["flex-wrap"] == "wrap")
31
32 // var i int
33
34 colWidth := self.Width / float32(len(orderedNode))
35
36 var xOffset, yOffset float32
37 // if n.Style["justify-content"] == "space-evenly" {
38 // b, _ := utils.ConvertToPixels(n.Children[i].Properties.Border.Width, n.Children[i].Properties.EM, n.Properties.Computed["width"])
39 // cwV := utils.Max((colWidth-(n.Children[i].Properties.Computed["width"]+(b*2)))/2, 0)
40 // xOffset = cwV
41 // }
42
43 posTrack := map[int]int{}
44 p := 0
45
46 for a, column := range orderedNode {
47 var maxColumnHeight float32
48 for _, item := range column {
49 itemState := s[item.Properties.Id]
50 maxColumnHeight = utils.Max(itemState.Height, maxColumnHeight)
51 }
52
53 yOffset = s[n.Children[0].Properties.Id].Y
54 for _, item := range column {
55 var i int
56 for c, v := range n.Children {
57 if v.Properties.Id == item.Properties.Id {
58 i = c
59 }
60 }
61 posTrack[p] = i
62 p++
63 itemState := s[item.Properties.Id]
64 cState := s[n.Children[i].Properties.Id]
65 // n.Children[i] = item
66 if n.Style["justify-content"] == "space-between" {
67 cwV := utils.Max((colWidth - (itemState.Width)), 0)
68 if a == 0 {
69 cState.X += xOffset
70 } else if a == len(orderedNode)-1 {
71 cState.X += xOffset + cwV
72 } else {
73 cState.X += xOffset + cwV/2
74 }
75 } else if n.Style["justify-content"] == "flex-end" || n.Style["justify-content"] == "center" {
76 dif := self.Width - (xOffset)
77 if n.Style["justify-content"] == "center" {
78 dif = dif / 2
79 }
80 cState.X += dif
81 } else if n.Style["justify-content"] == "flex-start" || n.Style["justify-content"] == "" {
82 cState.X += xOffset
83 } else {
84 cwV := utils.Max((colWidth-(itemState.Width))/2, 0)
85 var offset float32
86 if n.Style["justify-content"] == "space-evenly" {
87 offset = ((cwV * 2) / float32(len(orderedNode))) * float32(a)
88 }
89 cState.X += xOffset + (cwV - offset)
90
91 }
92 cState.Y = yOffset
93 yOffset += maxColumnHeight
94 i++
95
96 }
97 xOffset += colWidth
98 }
99
100 content := n.Style["align-content"]
101
102 if n.Style["flex-direction"] == "column" {
103 content = n.Style["justify-content"]
104 }
105
106 if content != "" && content != "flex-start" {
107 var min, max, rows, col, currY float32
108 min = 1000000000000
109 for _, v := range n.Children {
110 vState := s[v.Properties.Id]
111 min = utils.Min(min, vState.Y)
112 max = utils.Max(max, vState.Height+vState.Y)
113 if vState.Y > currY {
114 rows++
115 currY = vState.Y
116 }
117 }
118
119 height := max - min
120 rowHeight := ((self.Height - height) / rows)
121 for e := range n.Children {
122 i := posTrack[e]
123 cState := s[n.Children[i].Properties.Id]
124 row := float32(int(e % int(rows)))
125 if row == 0 {
126 col++
127 }
128 if len(orderedNode[int(col)-1]) <= int(row) {
129 row = 0
130 }
131
132 if content == "center" {
133 cState.Y += (self.Height - height) / 2
134 } else if content == "flex-end" {
135 cState.Y += (self.Height - height)
136 } else if content == "space-around" {
137 cState.Y += (rowHeight * row) + (rowHeight / 2)
138 } else if content == "space-evenly" {
139 cState.Y += (rowHeight * row) + (rowHeight / 2)
140 } else if content == "space-between" {
141 cState.Y += (((self.Height - height) / (rows - 1)) * row)
142 } else if content == "stretch" {
143 cState.Y += (rowHeight * row)
144 if n.Children[i].Style["height"] == "" {
145 cState.Height = self.Height / rows
146 }
147 }
148 }
149
150 }
151 (*state)[n.Properties.Id] = self
152 },
153 }
154}
155
156func order(p element.Node, state *map[string]element.State, elements []element.Node, direction string, reversed, wrap bool) [][]element.Node {
157 s := *state
158 self := s[p.Properties.Id]
159 var dir, marginStart, marginEnd string
160 if direction == "column" {
161 dir = "Height"
162 marginStart = "Top"
163 marginEnd = "Bottom"
164 } else {
165 dir = "Width"
166 marginStart = "Left"
167 marginEnd = "Right"
168 }
169 max, _ := utils.GetStructField(&self, dir)
170
171 nodes := [][]element.Node{}
172
173 if wrap {
174 counter := 0
175 if direction == "column" {
176 collector := []element.Node{}
177 for _, v := range elements {
178 vState := s[v.Properties.Id]
179 m := utils.GetMP(v, "margin")
180 elMax := vState.Height
181 elMS, _ := utils.GetStructField(&m, marginStart)
182 elME, _ := utils.GetStructField(&m, marginEnd)
183 tMax := elMax + elMS.(float32) + elME.(float32)
184 if counter+int(tMax) < int(max.(float32)) {
185 collector = append(collector, v)
186 } else {
187 if reversed {
188 slices.Reverse(collector)
189 }
190 nodes = append(nodes, collector)
191 collector = []element.Node{}
192 collector = append(collector, v)
193 counter = 0
194 }
195 counter += int(tMax)
196 }
197 if len(collector) > 0 {
198 nodes = append(nodes, collector)
199 }
200 } else {
201 var mod int
202 for _, v := range elements {
203 vState := s[v.Properties.Id]
204 m := utils.GetMP(v, "margin")
205 elMax := vState.Width
206 elMS, _ := utils.GetStructField(&m, marginStart)
207 elME, _ := utils.GetStructField(&m, marginEnd)
208 tMax := elMax + elMS.(float32) + elME.(float32)
209 if counter+int(tMax) < int(max.(float32)) {
210 if len(nodes)-1 < mod {
211 nodes = append(nodes, []element.Node{v})
212 } else {
213 nodes[mod] = append(nodes[mod], v)
214 }
215 } else {
216 mod = 0
217 counter = 0
218 if len(nodes)-1 < mod {
219 nodes = append(nodes, []element.Node{v})
220 } else {
221 nodes[mod] = append(nodes[mod], v)
222 }
223 }
224 counter += int(tMax)
225 mod++
226 }
227 if reversed {
228 slices.Reverse(nodes)
229 }
230 }
231 } else {
232 var tMax float32
233 for _, v := range elements {
234 vState := s[v.Properties.Id]
235 m := utils.GetMP(v, "margin")
236 elMax, _ := utils.GetStructField(&vState, dir)
237 elMS, _ := utils.GetStructField(&m, marginStart)
238 elME, _ := utils.GetStructField(&m, marginEnd)
239 tMax += elMax.(float32) + elMS.(float32) + elME.(float32)
240 }
241
242 pMax, _ := utils.GetStructField(&self, dir)
243
244 // Resize node to fit
245 var newSize float32
246 if tMax > pMax.(float32) {
247 newSize = pMax.(float32) / float32(len(elements))
248 }
249 if dir == "Width" {
250 for _, v := range elements {
251 vState := s[v.Properties.Id]
252 if newSize != 0 {
253 vState.Width = newSize
254 }
255 nodes = append(nodes, []element.Node{v})
256 }
257 if reversed {
258 slices.Reverse(nodes)
259 }
260 } else {
261 nodes = append(nodes, []element.Node{})
262 for _, v := range elements {
263 vState := s[v.Properties.Id]
264 if newSize != 0 {
265 vState.Height = newSize
266 }
267 nodes[0] = append(nodes[0], v)
268 }
269 if reversed {
270 slices.Reverse(nodes[0])
271 }
272 }
273
274 }
275 (*state)[p.Properties.Id] = self
276
277 return nodes
278}