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) {
- 23
- 24 // Brief: justify does not align the bottom row correctly
- 25 // y axis also needs to be done
- 26 verbs := strings.Split(n.Style["flex-direction"], "-")
- 27
- 28 orderedNode := order(*n, n.Children, verbs[0], len(verbs) > 1, n.Style["flex-wrap"] == "wrap")
- 29
- 30 // var i int
- 31
- 32 colWidth := n.Properties.Width / float32(len(orderedNode))
- 33
- 34 var xOffset, yOffset float32
- 35 // if n.Style["justify-content"] == "space-evenly" {
- 36 // b, _ := utils.ConvertToPixels(n.Children[i].Properties.Border.Width, n.Children[i].Properties.EM, n.Properties.Width)
- 37 // cwV := utils.Max((colWidth-(n.Children[i].Properties.Width+(b*2)))/2, 0)
- 38 // xOffset = cwV
- 39 // }
- 40
- 41 posTrack := map[int]int{}
- 42 p := 0
- 43
- 44 for a, column := range orderedNode {
- 45 var maxColumnHeight float32
- 46 for _, item := range column {
- 47 maxColumnHeight = utils.Max(item.Properties.Height, maxColumnHeight)
- 48 }
- 49
- 50 yOffset = n.Children[0].Properties.Y
- 51 for _, item := range column {
- 52 var i int
- 53 for c, v := range n.Children {
- 54 if v.Properties.Id == item.Properties.Id {
- 55 i = c
- 56 }
- 57 }
- 58 posTrack[p] = i
- 59 p++
- 60 // n.Children[i] = item
- 61 if n.Style["justify-content"] == "space-between" {
- 62 cwV := utils.Max((colWidth - (item.Properties.Width)), 0)
- 63 if a == 0 {
- 64 n.Children[i].Properties.X += xOffset
- 65 } else if a == len(orderedNode)-1 {
- 66 n.Children[i].Properties.X += xOffset + cwV
- 67 } else {
- 68 n.Children[i].Properties.X += xOffset + cwV/2
- 69 }
- 70 } else if n.Style["justify-content"] == "flex-end" || n.Style["justify-content"] == "center" {
- 71 dif := n.Properties.Width - (xOffset)
- 72 if n.Style["justify-content"] == "center" {
- 73 dif = dif / 2
- 74 }
- 75 n.Children[i].Properties.X += dif
- 76 } else if n.Style["justify-content"] == "flex-start" || n.Style["justify-content"] == "" {
- 77 n.Children[i].Properties.X += xOffset
- 78 } else {
- 79 cwV := utils.Max((colWidth-(item.Properties.Width))/2, 0)
- 80 var offset float32
- 81 if n.Style["justify-content"] == "space-evenly" {
- 82 offset = ((cwV * 2) / float32(len(orderedNode))) * float32(a)
- 83 }
- 84 n.Children[i].Properties.X += xOffset + (cwV - offset)
- 85
- 86 }
- 87 n.Children[i].Properties.Y = yOffset
- 88 yOffset += maxColumnHeight
- 89 i++
- 90
- 91 }
- 92 xOffset += colWidth
- 93 }
- 94
- 95 content := n.Style["align-content"]
- 96
- 97 if n.Style["flex-direction"] == "column" {
- 98 content = n.Style["justify-content"]
- 99 }
-100
-101 if content != "" && content != "flex-start" {
-102 var min, max, rows, col, currY float32
-103 min = 1000000000000
-104 for _, v := range n.Children {
-105 min = utils.Min(min, v.Properties.Y)
-106 max = utils.Max(max, v.Properties.Height+v.Properties.Y)
-107 if v.Properties.Y > currY {
-108 rows++
-109 currY = v.Properties.Y
-110 }
-111 }
-112
-113 height := max - min
-114 rowHeight := ((n.Properties.Height - height) / rows)
-115
-116 for e := range n.Children {
-117 i := posTrack[e]
-118 row := float32(int(e % int(rows)))
-119 if row == 0 {
-120 col++
-121 }
-122 if len(orderedNode[int(col)-1]) <= int(row) {
-123 row = 0
-124 }
-125
-126 if content == "center" {
-127 n.Children[i].Properties.Y += (n.Properties.Height - height) / 2
-128 } else if content == "flex-end" {
-129 n.Children[i].Properties.Y += (n.Properties.Height - height)
-130 } else if content == "space-around" {
-131 n.Children[i].Properties.Y += (rowHeight * row) + (rowHeight / 2)
-132 } else if content == "space-evenly" {
-133 n.Children[i].Properties.Y += (rowHeight * row) + (rowHeight / 2)
-134 } else if content == "space-between" {
-135 n.Children[i].Properties.Y += (((n.Properties.Height - height) / (rows - 1)) * row)
-136 } else if content == "stretch" {
-137 n.Children[i].Properties.Y += (rowHeight * row)
-138 if n.Children[i].Style["height"] == "" {
-139 n.Children[i].Properties.Height = n.Properties.Height / rows
-140 }
-141 }
-142 }
-143 }
-144 },
-145 }
-146}
-147
-148func order(p element.Node, elements []element.Node, direction string, reversed, wrap bool) [][]element.Node {
-149 var dir, marginStart, marginEnd string
-150 if direction == "column" {
-151 dir = "Height"
-152 marginStart = "Top"
-153 marginEnd = "Bottom"
-154 } else {
-155 dir = "Width"
-156 marginStart = "Left"
-157 marginEnd = "Right"
-158 }
-159 max, _ := utils.GetStructField(&p.Properties, dir)
-160
-161 nodes := [][]element.Node{}
-162
-163 if wrap {
-164 counter := 0
-165 if direction == "column" {
-166 collector := []element.Node{}
-167 for _, v := range elements {
-168 m := utils.GetMP(v, "margin")
-169 elMax, _ := utils.GetStructField(&v.Properties, "Height")
-170 elMS, _ := utils.GetStructField(&m, marginStart)
-171 elME, _ := utils.GetStructField(&m, marginEnd)
-172 tMax := elMax.(float32) + elMS.(float32) + elME.(float32)
-173 if counter+int(tMax) < int(max.(float32)) {
-174 collector = append(collector, v)
-175 } else {
-176 if reversed {
-177 slices.Reverse(collector)
-178 }
-179 nodes = append(nodes, collector)
-180 collector = []element.Node{}
-181 collector = append(collector, v)
-182 counter = 0
-183 }
-184 counter += int(tMax)
-185 }
-186 if len(collector) > 0 {
-187 nodes = append(nodes, collector)
-188 }
-189 } else {
-190 var mod int
-191 for _, v := range elements {
-192 m := utils.GetMP(v, "margin")
-193 elMax, _ := utils.GetStructField(&v.Properties, "Width")
-194 elMS, _ := utils.GetStructField(&m, marginStart)
-195 elME, _ := utils.GetStructField(&m, marginEnd)
-196 tMax := elMax.(float32) + elMS.(float32) + elME.(float32)
-197 if counter+int(tMax) < int(max.(float32)) {
-198 if len(nodes)-1 < mod {
-199 nodes = append(nodes, []element.Node{v})
-200 } else {
-201 nodes[mod] = append(nodes[mod], v)
-202 }
-203 } else {
-204 mod = 0
-205 counter = 0
-206 if len(nodes)-1 < mod {
-207 nodes = append(nodes, []element.Node{v})
-208 } else {
-209 nodes[mod] = append(nodes[mod], v)
-210 }
-211 }
-212 counter += int(tMax)
-213 mod++
-214 }
-215 if reversed {
-216 slices.Reverse(nodes)
-217 }
-218 }
-219 } else {
-220 var tMax float32
-221 for _, v := range elements {
-222 m := utils.GetMP(v, "margin")
-223 elMax, _ := utils.GetStructField(&v.Properties, dir)
-224 elMS, _ := utils.GetStructField(&m, marginStart)
-225 elME, _ := utils.GetStructField(&m, marginEnd)
-226 tMax += elMax.(float32) + elMS.(float32) + elME.(float32)
-227 }
-228
-229 pMax, err := utils.GetStructField(&p, dir)
-230 utils.Check(err)
-231
-232 // Resize node to fit
-233 var newSize float32
-234 if tMax > pMax.(float32) {
-235 newSize = pMax.(float32) / float32(len(elements))
-236 }
-237 if dir == "Width" {
-238 for _, v := range elements {
-239 if newSize != 0 {
-240 v.Properties.Width = newSize
-241 }
-242 nodes = append(nodes, []element.Node{v})
-243 }
-244 if reversed {
-245 slices.Reverse(nodes)
-246 }
-247 } else {
-248 nodes = append(nodes, []element.Node{})
-249 for _, v := range elements {
-250 if newSize != 0 {
-251 v.Properties.Height = newSize
-252 }
-253 nodes[0] = append(nodes[0], v)
-254 }
-255 if reversed {
-256 slices.Reverse(nodes[0])
-257 }
-258 }
-259
-260 }
-261
-262 return nodes
-263}
-