Author: LakeFox
Email: [email protected]
Date: Mon, 24 Jun 2024 21:47:02 -0600
docs/cstyle/plugins/flex/index.html
lots of issue need to be fixed
Commits
ae78990ed5b06e02833bd8e578a3af1df49adc00 ae742fdbda42322f4fa1d30761f516bf1ad45a70 1ae1fe418977632fafe3e61c5f02e87f0cad6c87 099527773e9bc03b40b9ce5d8a492ebbcdebcf32 b6acff3a27a7c66e35ab7ea5ffe48f1a69efaf11 07144afe32b8dd752fc4d80efd81529e2df9e4e5 ca735fa2c136dd5f35a5ccf2ffe2133b906c7f94 e2ea9c897ee1e89f89cd5c043632326348191b3a 10f4ce166028ee8ff926170d4d9e17d54e63a4a4 4bd704181610864a1fc4ebe65f20220ea1f1c00b 1c468e139a0f87655e4222b8512c38bec429d067 d8d6cadd2741b05c7a121ccb6753c5a48b8ad1b4 4c0529a8475408ee41d4e4dbd9c969db14594d37 ed8180f077d294d1e2f347f6c30d2977e8670b42 9113424c26a247352fe7b111fff39d1562f6c342 f783d5cacccf047368f8f20fc687bf5ad8f6f66a 66084134570c2a3d87e1336a2ab2ca50341b93b2 031df3b2fd4851345dd6f4c443057141d5b9e65b baf5d8cc1ccf27d14e4e58edcc4c170bba6445df e9c8f7961cf8b188938535b318b50397a76268ba 29572e238d6ba3f401717032bd12a2f409bf1ea9 d6025b04ef9516745adae85a478cbf9f98433597 476d6415583067674f395660961e33b9b40c3e66 906dd99de66ad7df92011a52fb19e0319224741e 4c44132d28d06548d2c90c2f8ca72dd3047fa52d 79e4c754771ba514b29a36e96a7570f266de3c41 36aaa13c4ea4d1235c64febfe9a8fd797037bbb2 6d4b83918686647193953a59c166baf7455b4996 c6a1e4a5102e9a3b5045957c22a0a73ac1a7ca4c db934f090648cdcd96e2f5f12a9bad762c60bfcd 7af8fc3f425ca3814ce1088fbd8a7f82513a1bb2 1c650539c11b715b14ee9013ad7d7faa8f733a7a 717ed8747f4df855c63e13ff95dcab720b8713cd 1c786f0d0efe1a47c285564824c9503881bef393 af527f354d956456e2e71a7f81f1470e74888e69 94ded12a3e3953459ccfbec2f225cecb43b47c73 c0081dc2f877de951fd8b0cd37136568a7ebb586 cbc825d6b458d50debc5913c6b5ed442138d7462 0a3baa3c4708754c79d023ad0addb4cbfb2844c2 a07b34e07b359327e413ccb7ea2dcdf1a91504de 4bf00213a866402775b162fb6f4b7b0bc37a8af7 1b690fa946047f4b897b417d8bc3b02c54cfdb2d 83b05e82a5f28bbe288565ae8a65943ba681cb4a 37d58d4f9de6af12611dada7ba5ae42d51ef05c6 8bbfc0ded0504595111765963d396a4574773e05 81049efedf0b3b521fb2949d8eb03d5ba681b0a5 6dcb369a2fa2bb69f94598fb4224a1349a80db6c c3e4d0cb62570c56ef5bc530f57eeea613f083fc 82d0fbb470daae4091bf30fb57707d66bd193992 166ec9ab6f4a3af0fe522a7dbe166951d2b39b31 992895a8842900d9a0803e7099611d650aba257d 4904b0b2812f9f0f45a59f2efacae89dabe9fe7c 36beac951788f5fb7ab2eeb3381300b07993bfe8 541818a92a5be6442879cd9b3420e1ef27f6e663 43ac3a1bbe6e727869a26ab8697c035eb60577fa d2afd27150a869ff41b8e100e82f20af54146105 0374f24d4685954662fa9db05939a8cbcd492b1c ed04d15b29d4df0329e8a4725c1a371a5cb0a20e 39fc4123096b04a4584b48d6efbb1acd5acacbf9 18315df2eb529bab6c5c79607ecb94626b170ae6 c519a195b90ad689d60d85365252e433b7488eaf d0d2839012c26032488bfe657797b4b590f926c7 8e0cb82ccac15fbc3e08bb53b148563e62437a44 d4413acd4dbad43507018f24e0456a9bc432d156 0dc05886b3ae0c59667f03a245e0728ab094f130 c9a3652d779d9700d9a9d797fd0c58d349a58de1 76425d002c70c3d853c117389a3b407efc53c7c2 fb409ef93b05cd4268e83c7201da73b6b29d482a da1cce88d00f7f7c373df1ce66b18e26e3a2d6e9 fa74cd48bb8959855c9d6b874f874671611611f7 610079be424f3a72ad02aa62e1c89607481750e0 60fda643c807730c3774beaa10a0910a31a4278a 6d2bcdcad816fd2b31c612fe45d3fd5a2fb14f98 b2d960e7d263bee55badbca47dc5d4d4f2d61084 f2ba1e3a96dd571d142c5a37c462743a21148e5f 25cbd33758fdb18f79aa1cf6500d1c1c024ee516 cde2d71846d1f69e5f386d354006465d61a4d19c cf708c22c45491dbdbbdbbb4450b08969f2e33bc 7bda495fbc9ea2c3aa87ac73a5cf4881eecf1482 9499d6967b394b70a22d9be34f47ee1b7a3fc55e 3aa3e67cd8ab769bc2c12b46fc77b11be2b1a0dd abed4927dc46e3e952fd21472f7ae4150ee16044 73953118e02b4c2d8159279624810dddd75e9100 031e4b18d91d825b56ef1e9eda5f1638bcd26629 fa3e1c57efa140ea58f56c6abf1f5f12f9bf2c7d a9b1b82a40fa6c462a9919b2832a89eb6bb47784 a8bf5e2504bdbe257686d48c2bfcaf061abfc95d e2830e4a6650ca8a1c53116a6d86f2975951dbbf 4a48b4c6905999527a7fc8d32e53d8c347c9ac74 9cfdb8c7ddce3a1b34a6590d8872f820601c2c53 128fad8298e89eadafa5feea43ca94f5115b9090 95d4595418fa814d47707441f2dc98d07eac12d6 5e35f7131d999b406eaeafc689374e3426845e6d 3402992fd25a64838e7acecfba3fad645c6c2511 8fcabdf5a34e7d80de988c10426c27adb0622087 1884dd57148595841cfb324f5b812d8640964978 6008cc8c3444f86d729ae5a81ae26919da1bb516 03d40c0d7e8feda38add1d89e3805df74997d915 810685c4aac0a651beaecd0488443a3b293b315d a666abc115c6693b355d5a8ef9cdfc3d77a088ca bcd3619f96c4157ee5b6450bc2bd1f23f27c9d81 9c428f6ab674582e022ea469ef2ac1e3f7ccb933 6e99df4296470d349da01f2e29698dbb34692a0f ed739dfaeb1ca5da10b2c75236faee40bacaf851 006a9351f3320662bff0b96d5d27daa1ba4e52e4 d6b38763cf83ad275aed0450151a97098f48859a 4ea031466d93057705a52caf2dfa21929b215730 a1bead3d96a11f4badedbd5a6eb984473c1cd309 7aa36472009f43cad843b465f67d2927f3428fdf 5f875adcd63ebd9ac9dfaef3ea16e6a6d3735503 4c0cc347e5e52d8ed99e84d42b309c4541d9280c c3de867fbbc27aaefba7aa88f97b5b1406c7c58e 00754639948b6612016ed5c434e97f44e7c65ed6 ffe16b1e768209b1c2021301a142b7fcd9a35a4b 800e568c600187f7228b228874ad20fb57f35166 d36b349e0eea73e99253b64fae3afeb5c4c276ca a7d8eff776e4e28a85e7835ee7ff6d50775748e7 bd0bd280c89d5d742e0ef13673c854436657466f 42da0bb422cdca21c8491af40ca9631206d8e964 e81415f70bedf456983b18692b4ae04355f15283 09c0a9a40ca6d8a8b6eaa6f06ce3f8c2440f7ee1 26eaa5b9c8cc2a84f9de04e17e01f201c122989e 649f49d0618e3c8cb940c4d259a536dfcc66020f 27ec987a8e8a9bc645f6cd38d9f8d5d52e7dbedb eb566ec8284ba205d27699a9bf465e26158b5098 4bdf14d6decad2ef14a77c108227273dd700e9a3 5598cb31dc238e16f58da2f793a1e2f7f5768dba 0bfe812e3d1f25756efcf92162961f5d55c3a5d8 9f96c81ba868d6269f3698c64ca8a83e74b0510f d5f01925db8323eeabbc43ec1b72a685da00dd6b f09195ec50a24c35947cb52feca1978ac5599871 0a10380275edaffc88632ef444a15b15c47ec17e 3f08ca6c77812c1d39f2949d2bab7416c77cc4ca af784841593347b2fd440fb78872fe9ac0fe1c09 9aa492880457b6fc20968f5d036cb6fe912e8964 c622cc4a0d279b98570b0af11fc67278e3355556 4d5dead4c4d3b3e34198e59e6ee0f6b3ca7c64b1 2191ceb040dd58a0794250e9e6c795a509b9fad5 775c1d3bc761967ff2f0a83e345c951117a5e9aa ace03eee6a19e6a12ad12c25e310ac3d223d2d48 f10dbc643cb334dc70657a086a38aadb59b59e29 ea63ec4d6f32b8a652d495d9c66d777313271e4a 038178b09b92d678107449519b75a977a08f45e9 f9cdbbb9ebfc1db9261b430427aa719be56a53c1 0a200674c645cf59ae69f25a25440db0b89c0c30 2e7189bb5db8a803c0ade25613a50bfcc264746a e6ca3edcf724fb8f2457423d9261ab73faf1f5da 6ff2d4a7c2fbc14ea856eb891f019c7978905834 72fac5e32be9bbf531dc8e324f2b865eb265ec4f 351cd2077d369fc0a9b9ec8675ede29288d41f35 061dd2a2659df35d1edd4ba74d67e6e72b531bf7 3c32ab918568bf4f59b0a8b393020de888dc2c3e 08fa11670d73b4f71226541761e09a99fc8a17c9 9d94e556f3eb471fd312af194ca7c4b82b67da6c db70db80c56513ebad6b95b66273e623198c5f44 e666311a274481b4af90702c916004ccbf9b6d8a 9780e12fa7acfb3a5be7d4171068c8c100858c53 baee9c1074cbf844b7c4a3c837ebb17f7861d075 0aae4ce623c90bfd7ea6c4f20967bf50001dc22f c8b42e81407d55a6444986deb435fa8144822c49 9e9967bb87524a82ae9411ca974d3b081ec52c53 3eac611da268444f07e1f718ffd18c7f47bc2a4c fbb2b3a689be07c57cde471e651ba06d7ecf7316 28d61bf3fae304b22ce0380c93a6f997e8c77e32 992c464588845b09ff2b4a61b5de719b9cdaf356 716fff934be2016bc00b2fcf17e19bc0ecfdeeb0 69a2005824c09fa33828ec5ffa24b9df8cd5bcc0 4fa6810e9e944c7d0c4ff06bed6a534e33869034 8dbbcec096317e9016c2f3478be4d458dbb34ad8 2c7c01be15245ae8997185fee247c00106cc81db 5af9b8d40ec97f5741d9a69161ef4aa10c879724 c9851e1b750de6c324c749b4bff5725d79e2b610 0a9f5a297bb97486fc23bb3a0bb39cb8b5b8cc27 aa4bda96b90fab60bf383c255d60b9580b5b6a31 cd8a892d7f6ca71c5d591d4282d98083462d77fe 98cc1a202fd2dbf27e87378c1588edc5eb1c3d60 d3068f5500a98d2a2b71d4c01d5296477224b743 1b28153bff1449200899115d4a1d9f612fac716c d992717d5df7bf68a5907446f9b31c78b5a01f51 497033c40c559bceb5c7980c8d48bd1d935188e3 d967a66b91fd990264e5a4b134385d80e5980c57 a397e9dda8244b6977adb9daeb5ab5ddff6e6140 60b804dc01593469962dae00a1e4004f0a8d7c53 a7b240cf9199d727e494b97ad2d9b65440a9ef1c 2458e3538eef44deb6f3d6a4831aef19414fd0ed c19139b782f5124ea86fc1610fe13ea85f77a279 c67f095bcad89fc6e6b635792a96ed0ed295e1a8 9ecebc8512dbb2a0ed61df1901eafd3832893bf8 95a551f86f299d7f8b424c26da3ff77400368fed ae5c8d61d8c75ed4b01dac60edd37859bc8f9d8f e54f11cae13b053a44afe10cdb47b65f535caca9 9b4fcfd0bee437354defe7e0f431857ff21c0edb ee5c2a995e1b9affef5a8e12f23cff8b0813d2ab 034c3e1601aaa0cba81118030a849485eea2b7ea 0cce165ede3a66867a863d5cb86afff5db406587 375b4fd6eca2d9d63959f9c755de6f8c5d89d302 8bec92a21036bedb734571d443f7b1a14daaa6eb 14d0b11516cd8bbdea84a3fa6cf53cff9619d902 c1e77a9311a8679328d0dc1337dd940682296927 6ab614d3e218d4c5cb3f69001a71350d3d7c65ec 77f6db23a5b65257959cc55e03eff09ee8f25cfc 64b7a40bb5620ec0522d9609fc961cff9cafe68a 62dca0c033d444aa579970c4c871b802c2a82d60 21f5480d3441d7c918a817368172bc14d714a3e8 3fc038d8db20f298b843a7eeeb31f25abf5a2788 492236c84ca4cfc3d8aea9d32d75b6a65a2fe52a 759a12b81483024d52d7b2055f66d675c05ea372 50580213060d8392a2da78eec0b8f08adddeba62 6374e3bb760d470dacdadfc14ef7cb824d9e194c 964b76fe981ab840a2cbc8a807789abae92ae660 b30861536f72d0ffc97c8780b62759fb764ed40b 5edb09e6ea1ba70cdac64a2196481b1f038301c2 34eeb6773589a95ecf66484b999cf443e57632d0 4ee9c48fa4b6f983c03acf77e8d04720fe43e1a6 88ebb8d8af483c96640f7df804e87fca20284c4d ce9fadbe2bd8bac62b475a387a8577f8a806fd52 9e7eb5f80cde5398270e1c4c85258118e22fe8ef a19227e38c38ceb21695ac14ea7754002980cf55 4277bc56f4490533734b1ed78fb5a9c8575f7afb 424479529f31e00ff3263795d42218a026fa528a 91c0289a560e3f3860d7b39549010adf917b8d1b 62a80750f59f92786acc48b18c3365d021bc5590 c0de5849434d88dd115eac9e5bc8eafcd0a0fa76 f869b8a4d7f88ac88437c9f3cfb4416784990e98 ee80bb3fe9cdd54af1ce4aba7f5e2fd136a2499c 8563a689d5957e4fd3ff9fecfbf97def28de4bff de8179675f9250b28678671addf56e33e5829e79 43b815a08101d267bc5d937d0b003a419bb2abd9 9e4164f6b3f847f371351a324905def648ea1747 1f26e1cc07a0de2edb516769b74e99b965b6d75d c36c0e51aad0f40f3f61406e786ba198ab6d90f9 c727bae4cb644789b0a975ec665c8b02652d4651 a61b91abb5ba8128c1438cc59b2f054c71f28d2a 2e1cecf0bba482b9976f3d8f274611195b0cf2f8 707ef18dccda6b917e1b421291e47e658555b3d2 b456956bfd85041b5b70b50d5fb2eaf3c9de64f2 f39d14d001e3dd0e73c4f8200f4132b47ebb40d3 9f0bcb8f5d1922199afb7bc8f8bb57bb10d0fe12 e877036f029a0198d9da39775443c8ac2132309b 2391f2f3881dbdabf96ca33c931e9cd5f42cedc9 82189594b7e20243f5ece31c6f7b804d6b83b0d7 5abd3260994cc77992f5c6437bdcdf45c32d9867 2519053ee4c5b2ce1c2851fee0d47d612d27aa1f 05584371da7da40cdab309ea2809c51c02069384 b61c8342cee8a0942ce276c2d2de773347ab4dcd c7b80824ade46956377b955838b73325d6fbe4d9 9866874e4701f30f1a293a7fd2e5d242bbf82c4f 2308aecbde415948894a55e53201c5abb7184039 e8b44094228f41fa5996788b977d07072fcf87a6 2facd93337f682bd8aa1222805c46720a53edc99 2d9288cec441356241f7d59d120de06ee7b97fdd
Diff
diff --git a/docs/cstyle/plugins/flex/index.html b/docs/cstyle/plugins/flex/index.html
index 86705ac..e00d24c 100644
--- a/docs/cstyle/plugins/flex/index.html
+++ b/docs/cstyle/plugins/flex/index.html
@@ -103,117 +103,117 @@
-   4	"fmt"
-   5	"gui/cstyle"
-   6	"gui/cstyle/plugins/inline"
-   7	"gui/element"
-   8	"gui/utils"
-   9	"sort"
-  10	"strings"
-  11)
-  12
-  13func Init() cstyle.Plugin {
-  14	return cstyle.Plugin{
-  15		Selector: func(n *element.Node) bool {
-  16			styles := map[string]string{
-  17				"display": "flex",
-  18			}
-  19			matches := true
-  20			for name, value := range styles {
-  21				if (n.Style[name] != value || n.Style[name] == "") && !(value == "*") {
-  22					matches = false
-  23				}
-  24			}
-  25			return matches
-  26		},
-  27		Level: 3,
-  28		Handler: func(n *element.Node, state *map[string]element.State) {
-  29			s := *state
-  30			self := s[n.Properties.Id]
-  31
-  32			verbs := strings.Split(n.Style["flex-direction"], "-")
-  33			flexDirection := verbs[0]
-  34			if flexDirection == "" {
-  35				flexDirection = "row"
-  36			}
-  37			flexReversed := false
-  38			if len(verbs) > 1 {
-  39				flexReversed = true
-  40			}
-  41
-  42			var flexWrapped bool
-  43			if n.Style["flex-wrap"] == "wrap" {
-  44				flexWrapped = true
-  45			} else {
-  46				flexWrapped = false
-  47			}
-  48
-  49			alignContent := n.Style["align-content"]
-  50			if alignContent == "" {
-  51				alignContent = "normal"
-  52			}
-  53			alignItems := n.Style["align-items"]
-  54			if alignItems == "" {
-  55				alignItems = "normal"
-  56			}
-  57			justifyItems := n.Style["justify-items"]
-  58			if justifyItems == "" {
-  59				justifyItems = "normal"
-  60			}
-  61
-  62			justifyContent := n.Style["justify-content"]
-  63			if justifyContent == "" {
-  64				justifyContent = "normal"
-  65			}
-  66			// fmt.Println(flexDirection, flexReversed, flexWrapped, hAlign, vAlign, justifyItems, justifyContent)
-  67			rows := [][]int{}
-  68			maxH := float32(0)
-  69			// maxW := float32(0)
-  70
-  71			// Get inital sizing
-  72			textTotal := 0
-  73			textCounts := []int{}
-  74			widths := []float32{}
-  75			// heights := []float32{}
-  76			innerSizes := [][]float32{}
-  77			minWidths := []float32{}
-  78			minHeights := []float32{}
-  79			maxWidths := []float32{}
-  80			// maxHeights := []float32{}
-  81			for _, v := range n.Children {
-  82				count := countText(v)
-  83				textTotal += count
-  84				textCounts = append(textCounts, count)
-  85
-  86				minw := getMinWidth(&v, state)
-  87				minWidths = append(minWidths, minw)
-  88
-  89				maxw := getMaxWidth(&v, state)
-  90				maxWidths = append(maxWidths, maxw)
-  91
-  92				w, h := getInnerSize(&v, state)
-  93
-  94				minh := getMinHeight(&v, state)
-  95				minHeights = append(minHeights, minh)
-  96
-  97				// maxh := getMaxHeight(&v, state)
-  98				// maxHeights = append(maxHeights, maxh)
-  99				innerSizes = append(innerSizes, []float32{w, h})
- 100			}
- 101			selfWidth := (self.Width - self.Padding.Left) - self.Padding.Right
- 102			selfHeight := (self.Height - self.Padding.Top) - self.Padding.Bottom
- 103
- 104			if flexDirection == "row" {
- 105				// if the elements are less than the size of the parent, don't change widths. Just set mins
- 106				if !flexWrapped {
- 107					if add2d(innerSizes, 0) < selfWidth {
- 108						fmt.Println("here")
- 109						for i := range innerSizes {
- 110							// for i, _ := range n.Children {
- 111							// vState := s[v.Properties.Id]
- 112
- 113							w := innerSizes[i][0]
- 114							// w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 115							widths = append(widths, w)
- 116						}
- 117					} else {
- 118						// Modifiy the widths so they aren't under the mins
- 119						for i, v := range n.Children {
- 120							vState := s[v.Properties.Id]
+   4	"gui/cstyle"
+   5	"gui/cstyle/plugins/inline"
+   6	"gui/element"
+   7	"gui/utils"
+   8	"sort"
+   9	"strings"
+  10)
+  11
+  12func Init() cstyle.Plugin {
+  13	return cstyle.Plugin{
+  14		Selector: func(n *element.Node) bool {
+  15			styles := map[string]string{
+  16				"display": "flex",
+  17			}
+  18			matches := true
+  19			for name, value := range styles {
+  20				if (n.Style[name] != value || n.Style[name] == "") && !(value == "*") {
+  21					matches = false
+  22				}
+  23			}
+  24			return matches
+  25		},
+  26		Level: 3,
+  27		Handler: func(n *element.Node, state *map[string]element.State) {
+  28			s := *state
+  29			self := s[n.Properties.Id]
+  30
+  31			verbs := strings.Split(n.Style["flex-direction"], "-")
+  32			flexDirection := verbs[0]
+  33			if flexDirection == "" {
+  34				flexDirection = "row"
+  35			}
+  36			flexReversed := false
+  37			if len(verbs) > 1 {
+  38				flexReversed = true
+  39			}
+  40
+  41			var flexWrapped bool
+  42			if n.Style["flex-wrap"] == "wrap" {
+  43				flexWrapped = true
+  44			} else {
+  45				flexWrapped = false
+  46			}
+  47
+  48			alignContent := n.Style["align-content"]
+  49			if alignContent == "" {
+  50				alignContent = "normal"
+  51			}
+  52			alignItems := n.Style["align-items"]
+  53			if alignItems == "" {
+  54				alignItems = "normal"
+  55			}
+  56			justifyItems := n.Style["justify-items"]
+  57			if justifyItems == "" {
+  58				justifyItems = "normal"
+  59			}
+  60
+  61			justifyContent := n.Style["justify-content"]
+  62			if justifyContent == "" {
+  63				justifyContent = "normal"
+  64			}
+  65			// fmt.Println(flexDirection, flexReversed, flexWrapped, hAlign, vAlign, justifyItems, justifyContent)
+  66			rows := [][]int{}
+  67			maxH := float32(0)
+  68			// maxW := float32(0)
+  69
+  70			// Get inital sizing
+  71			textTotal := 0
+  72			textCounts := []int{}
+  73			widths := []float32{}
+  74			// heights := []float32{}
+  75			innerSizes := [][]float32{}
+  76			minWidths := []float32{}
+  77			minHeights := []float32{}
+  78			maxWidths := []float32{}
+  79			maxHeights := []float32{}
+  80			for _, v := range n.Children {
+  81				count := countText(v)
+  82				textTotal += count
+  83				textCounts = append(textCounts, count)
+  84
+  85				minw := getMinWidth(&v, state)
+  86				minWidths = append(minWidths, minw)
+  87
+  88				maxw := getMaxWidth(&v, state)
+  89				maxWidths = append(maxWidths, maxw)
+  90
+  91				w, h := getInnerSize(&v, state)
+  92
+  93				minh := getMinHeight(&v, state)
+  94				minHeights = append(minHeights, minh)
+  95
+  96				maxh := getMaxHeight(&v, state)
+  97				maxHeights = append(maxHeights, maxh)
+  98				innerSizes = append(innerSizes, []float32{w, h})
+  99			}
+ 100			selfWidth := (self.Width - self.Padding.Left) - self.Padding.Right
+ 101			selfHeight := (self.Height - self.Padding.Top) - self.Padding.Bottom
+ 102
+ 103			if flexDirection == "row" {
+ 104				// if the elements are less than the size of the parent, don't change widths. Just set mins
+ 105				if !flexWrapped {
+ 106					if add2d(innerSizes, 0) < selfWidth {
+ 107						for i, v := range n.Children {
+ 108							vState := s[v.Properties.Id]
+ 109
+ 110							w := innerSizes[i][0]
+ 111							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 112							widths = append(widths, w)
+ 113						}
+ 114					} else {
+ 115						// Modifiy the widths so they aren't under the mins
+ 116						for i, v := range n.Children {
+ 117							vState := s[v.Properties.Id]
+ 118
+ 119							w := ((selfWidth / float32(textTotal)) * float32(textCounts[i]))
+ 120							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
@@ -221,70 +221,70 @@
- 122							w := ((selfWidth / float32(textTotal)) * float32(textCounts[i]))
- 123							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 124
- 125							if w < minWidths[i] {
- 126								selfWidth -= minWidths[i] + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 127								textTotal -= textCounts[i]
- 128								textCounts[i] = 0
- 129							}
- 130
- 131						}
- 132						for i, v := range n.Children {
- 133							vState := s[v.Properties.Id]
- 134
- 135							w := ((selfWidth / float32(textTotal)) * float32(textCounts[i]))
- 136							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 137							// (w!=w) is of NaN
- 138							if w < minWidths[i] || (w != w) {
- 139								w = minWidths[i]
- 140							}
- 141							widths = append(widths, w)
- 142						}
- 143					}
- 144					// Apply the new widths
- 145					fState := s[n.Children[0].Properties.Id]
- 146					for i, v := range n.Children {
- 147						vState := s[v.Properties.Id]
- 148
- 149						vState.Width = widths[i]
- 150						xStore := vState.X
- 151						if i > 0 {
- 152							sState := s[n.Children[i-1].Properties.Id]
- 153							vState.X = sState.X + sState.Width + sState.Margin.Right + vState.Margin.Left + sState.Border.Width + vState.Border.Width
- 154							propagateOffsets(&v, xStore, vState.Y, vState.X, fState.Y+vState.Margin.Top, state)
- 155						}
- 156
- 157						vState.Y = fState.Y + vState.Margin.Top
- 158
- 159						(*state)[v.Properties.Id] = vState
- 160						deInline(&v, state)
- 161						applyInline(&v, state)
- 162						applyBlock(&v, state)
- 163						_, h := getInnerSize(&v, state)
- 164						h = utils.Max(h, vState.Height)
- 165						maxH = utils.Max(maxH, h)
- 166					}
- 167					// When not wrapping everything will be on the same row
- 168					rows = append(rows, []int{0, len(n.Children), int(maxH)})
- 169				} else {
- 170					// Flex Wrapped
- 171					sum := innerSizes[0][0]
- 172					for i := 0; i < len(n.Children); i++ {
- 173						v := n.Children[i]
- 174						vState := s[v.Properties.Id]
- 175
- 176						// if the next plus current will break then
- 177						w := innerSizes[i][0]
- 178						if i > 0 {
- 179							sib := s[n.Children[i-1].Properties.Id]
- 180							if maxWidths[i] > selfWidth {
- 181								w = selfWidth - vState.Margin.Left - vState.Margin.Right - (vState.Border.Width * 2)
- 182							}
- 183							if w+sum > selfWidth {
- 184								sum = w + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 185							} else {
- 186								propagateOffsets(&v, vState.X, vState.Y, vState.X, sib.Y, state)
- 187								vState.Y = sib.Y
- 188								(*state)[v.Properties.Id] = vState
- 189								sum += w + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 190							}
- 191						}
+ 122							if w < minWidths[i] {
+ 123								selfWidth -= minWidths[i] + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 124								textTotal -= textCounts[i]
+ 125								textCounts[i] = 0
+ 126							}
+ 127
+ 128						}
+ 129						for i, v := range n.Children {
+ 130							vState := s[v.Properties.Id]
+ 131
+ 132							w := ((selfWidth / float32(textTotal)) * float32(textCounts[i]))
+ 133							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 134							// (w!=w) is of NaN
+ 135							if w < minWidths[i] || (w != w) {
+ 136								w = minWidths[i]
+ 137							}
+ 138							widths = append(widths, w)
+ 139						}
+ 140					}
+ 141					// Apply the new widths
+ 142					fState := s[n.Children[0].Properties.Id]
+ 143					for i, v := range n.Children {
+ 144						vState := s[v.Properties.Id]
+ 145
+ 146						vState.Width = widths[i]
+ 147						xStore := vState.X
+ 148						if i > 0 {
+ 149							sState := s[n.Children[i-1].Properties.Id]
+ 150							vState.X = sState.X + sState.Width + sState.Margin.Right + vState.Margin.Left + sState.Border.Width + vState.Border.Width
+ 151							propagateOffsets(&v, xStore, vState.Y, vState.X, fState.Y+vState.Margin.Top, state)
+ 152						}
+ 153
+ 154						vState.Y = fState.Y + vState.Margin.Top
+ 155
+ 156						(*state)[v.Properties.Id] = vState
+ 157						deInline(&v, state)
+ 158						applyInline(&v, state)
+ 159						applyBlock(&v, state)
+ 160						_, h := getInnerSize(&v, state)
+ 161						h = utils.Max(h, vState.Height)
+ 162						maxH = utils.Max(maxH, h)
+ 163					}
+ 164					// When not wrapping everything will be on the same row
+ 165					rows = append(rows, []int{0, len(n.Children), int(maxH)})
+ 166				} else {
+ 167					// Flex Wrapped
+ 168					sum := innerSizes[0][0]
+ 169					for i := 0; i < len(n.Children); i++ {
+ 170						v := n.Children[i]
+ 171						vState := s[v.Properties.Id]
+ 172
+ 173						// if the next plus current will break then
+ 174						w := innerSizes[i][0]
+ 175						if i > 0 {
+ 176							sib := s[n.Children[i-1].Properties.Id]
+ 177							if maxWidths[i] > selfWidth {
+ 178								w = selfWidth - vState.Margin.Left - vState.Margin.Right - (vState.Border.Width * 2)
+ 179							}
+ 180							if w+sum > selfWidth {
+ 181								sum = w + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 182							} else {
+ 183								propagateOffsets(&v, vState.X, vState.Y, vState.X, sib.Y, state)
+ 184								vState.Y = sib.Y
+ 185								(*state)[v.Properties.Id] = vState
+ 186								sum += w + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 187							}
+ 188						}
+ 189
+ 190						widths = append(widths, w)
+ 191					}
@@ -292,46 +292,46 @@
- 193						widths = append(widths, w)
- 194					}
- 195
- 196					// Move the elements into the correct position
- 197					start := 0
- 198					var prevOffset float32
- 199					for i := 0; i < len(n.Children); i++ {
- 200						v := n.Children[i]
- 201						vState := s[v.Properties.Id]
- 202
- 203						vState.Width = widths[i]
- 204						xStore := vState.X
- 205						yStore := vState.Y
- 206
- 207						if i > 0 {
- 208							sib := s[n.Children[i-1].Properties.Id]
- 209							if vState.Y+prevOffset == sib.Y {
- 210								yStore += prevOffset
- 211
- 212								if vState.Height < sib.Height {
- 213									vState.Height = minHeight(v, state, sib.Height)
- 214								}
- 215								// Shift right if on a row with sibling
- 216								xStore = sib.X + sib.Width + sib.Margin.Right + sib.Border.Width + vState.Margin.Left + vState.Border.Width
- 217							} else {
- 218								// Shift under sibling
- 219								yStore = sib.Y + sib.Height + sib.Margin.Top + sib.Margin.Bottom + sib.Border.Width*2
- 220								prevOffset = yStore - vState.Y
- 221								rows = append(rows, []int{start, i, int(maxH)})
- 222								start = i
- 223								maxH = 0
- 224							}
- 225							propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
- 226						}
- 227						vState.X = xStore
- 228						vState.Y = yStore
- 229
- 230						(*state)[v.Properties.Id] = vState
- 231						deInline(&v, state)
- 232						applyInline(&v, state)
- 233						applyBlock(&v, state)
- 234						_, h := getInnerSize(&v, state)
- 235						h = utils.Max(h, vState.Height)
- 236						maxH = utils.Max(maxH, h)
- 237						vState.Height = minHeight(v, state, h)
- 238						(*state)[v.Properties.Id] = vState
+ 193					// Move the elements into the correct position
+ 194					start := 0
+ 195					var prevOffset float32
+ 196					for i := 0; i < len(n.Children); i++ {
+ 197						v := n.Children[i]
+ 198						vState := s[v.Properties.Id]
+ 199
+ 200						vState.Width = widths[i]
+ 201						xStore := vState.X
+ 202						yStore := vState.Y
+ 203
+ 204						if i > 0 {
+ 205							sib := s[n.Children[i-1].Properties.Id]
+ 206							if vState.Y+prevOffset == sib.Y {
+ 207								yStore += prevOffset
+ 208
+ 209								if vState.Height < sib.Height {
+ 210									vState.Height = minHeight(v, state, sib.Height)
+ 211								}
+ 212								// Shift right if on a row with sibling
+ 213								xStore = sib.X + sib.Width + sib.Margin.Right + sib.Border.Width + vState.Margin.Left + vState.Border.Width
+ 214							} else {
+ 215								// Shift under sibling
+ 216								yStore = sib.Y + sib.Height + sib.Margin.Top + sib.Margin.Bottom + sib.Border.Width*2
+ 217								prevOffset = yStore - vState.Y
+ 218								rows = append(rows, []int{start, i, int(maxH)})
+ 219								start = i
+ 220								maxH = 0
+ 221							}
+ 222							propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
+ 223						}
+ 224						vState.X = xStore
+ 225						vState.Y = yStore
+ 226
+ 227						(*state)[v.Properties.Id] = vState
+ 228						deInline(&v, state)
+ 229						applyInline(&v, state)
+ 230						applyBlock(&v, state)
+ 231						_, h := getInnerSize(&v, state)
+ 232						h = utils.Max(h, vState.Height)
+ 233						maxH = utils.Max(maxH, h)
+ 234						vState.Height = minHeight(v, state, h)
+ 235						(*state)[v.Properties.Id] = vState
+ 236					}
+ 237					if start < len(n.Children) {
+ 238						rows = append(rows, []int{start, len(n.Children), int(maxH)})
@@ -339,52 +339,52 @@
- 240					if start < len(n.Children) {
- 241						rows = append(rows, []int{start, len(n.Children), int(maxH)})
- 242					}
- 243				}
- 244
- 245				for _, v := range rows {
- 246					for i := v[0]; i < v[1]; i++ {
- 247						vState := s[n.Children[i].Properties.Id]
- 248						// height := float32(v[2])
- 249						if (n.Style["height"] != "" && n.Style["min-height"] != "") && !flexWrapped {
- 250							height := self.Height - self.Padding.Top - self.Padding.Bottom - vState.Margin.Top - vState.Margin.Bottom - (vState.Border.Width * 2)
- 251							vState.Height = minHeight(n.Children[i], state, height)
- 252						}
- 253						(*state)[n.Children[i].Properties.Id] = vState
- 254					}
- 255				}
- 256				// Reverse elements
- 257				if flexReversed {
- 258					rowReverse(rows, n, state)
- 259				}
- 260
- 261				if justifyContent != "" && justifyContent != "normal" {
- 262					justifyRow(rows, n, state, justifyContent, flexReversed)
- 263				}
- 264
- 265				if alignContent != "normal" && flexWrapped {
- 266					alignRow(rows, n, state, alignItems, alignContent)
- 267				}
- 268
- 269			}
- 270
- 271			if flexDirection == "column" {
- 272				if !flexWrapped {
- 273					// if the container has a size restriction
- 274					var totalHeight, maxH float32
- 275					var fixedHeightElements int
- 276					for i, v := range n.Children {
- 277						vState := s[v.Properties.Id]
- 278						if v.Style["min-height"] != "" {
- 279							selfHeight -= vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
- 280							fixedHeightElements++
- 281							maxH = utils.Max(maxH, vState.Height)
- 282						} else {
- 283							// accoutn for element min height
- 284							totalHeight += minHeights[i] + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
- 285							maxH = utils.Max(maxH, minHeights[i])
- 286						}
- 287					}
- 288
- 289					heightDelta := selfHeight - totalHeight
- 290					if heightDelta < 0 {
- 291						heightDelta = -heightDelta
+ 240				}
+ 241
+ 242				for _, v := range rows {
+ 243					for i := v[0]; i < v[1]; i++ {
+ 244						vState := s[n.Children[i].Properties.Id]
+ 245						height := float32(v[2])
+ 246						if (n.Style["height"] != "" || n.Style["min-height"] != "") && !flexWrapped {
+ 247							height = self.Height - self.Padding.Top - self.Padding.Bottom - vState.Margin.Top - vState.Margin.Bottom - (vState.Border.Width * 2)
+ 248						}
+ 249						vState.Height = minHeight(n.Children[i], state, height)
+ 250						(*state)[n.Children[i].Properties.Id] = vState
+ 251					}
+ 252				}
+ 253				// Reverse elements
+ 254				if flexReversed {
+ 255					rowReverse(rows, n, state)
+ 256				}
+ 257
+ 258				if justifyContent != "" && justifyContent != "normal" {
+ 259					justifyRow(rows, n, state, justifyContent, flexReversed)
+ 260				}
+ 261
+ 262				alignRow(rows, n, state, alignItems, alignContent)
+ 263
+ 264			}
+ 265
+ 266			// Column doesn't really need a lot done bc it is basically block styling rn
+ 267			if flexDirection == "column" {
+ 268				if !flexWrapped {
+ 269					// if the container has a size restriction
+ 270					var totalHeight, maxH float32
+ 271					var fixedHeightElements int
+ 272					for i, v := range n.Children {
+ 273						vState := s[v.Properties.Id]
+ 274						if v.Style["min-height"] != "" {
+ 275							selfHeight -= vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+ 276							fixedHeightElements++
+ 277							maxH = utils.Max(maxH, vState.Height)
+ 278						} else {
+ 279							// accoutn for element min height
+ 280							totalHeight += minHeights[i] + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+ 281							maxH = utils.Max(maxH, minHeights[i])
+ 282						}
+ 283					}
+ 284
+ 285					heightDelta := selfHeight - totalHeight
+ 286					if heightDelta < 0 {
+ 287						heightDelta = -heightDelta
+ 288					}
+ 289					heightAdj := heightDelta / float32(len(n.Children)-fixedHeightElements)
+ 290					if heightAdj < 0 {
+ 291						heightAdj = -heightAdj
@@ -392,13 +392,13 @@
- 293					heightAdj := heightDelta / float32(len(n.Children)-fixedHeightElements)
- 294					if heightAdj < 0 {
- 295						heightAdj = -heightAdj
- 296					}
- 297					// We are calculating the amount a element needs to shrink because of its siblings
- 298					for i, v := range n.Children {
- 299						vState := s[v.Properties.Id]
- 300						yStore := vState.Y
- 301						if v.Style["min-height"] == "" {
- 302							vState.Height = minHeights[i] - heightAdj
- 303							if vState.Height < minHeights[i] {
- 304								vState.Height = minHeights[i]
- 305							}
+ 293					// We are calculating the amount a element needs to shrink because of its siblings
+ 294					for i, v := range n.Children {
+ 295						vState := s[v.Properties.Id]
+ 296						yStore := vState.Y
+ 297						if v.Style["min-height"] == "" {
+ 298							vState.Height = minHeights[i] - heightAdj
+ 299							if vState.Height < minHeights[i] {
+ 300								vState.Height = minHeights[i]
+ 301							}
+ 302
+ 303						}
+ 304						if i > 0 {
+ 305							sib := s[n.Children[i-1].Properties.Id]
@@ -406,3 +406,3 @@
- 307						}
- 308						if i > 0 {
- 309							sib := s[n.Children[i-1].Properties.Id]
+ 307							vState.Y = sib.Y + sib.Height + sib.Margin.Bottom + sib.Border.Width + vState.Margin.Top + vState.Border.Width
+ 308						}
+ 309						propagateOffsets(&v, vState.X, yStore, vState.X, vState.Y, state)
@@ -410,13 +410,13 @@
- 311							vState.Y = sib.Y + sib.Height + sib.Margin.Bottom + sib.Border.Width + vState.Margin.Top + vState.Border.Width
- 312						}
- 313						propagateOffsets(&v, vState.X, yStore, vState.X, vState.Y, state)
- 314
- 315						(*state)[v.Properties.Id] = vState
- 316					}
- 317
- 318					rows = append(rows, []int{0, len(n.Children) - 1, int(maxH)})
- 319
- 320				} else {
- 321					var colHeight float32
- 322					var colIndex int
- 323					cols := [][][]float32{}
+ 311						(*state)[v.Properties.Id] = vState
+ 312					}
+ 313
+ 314					rows = append(rows, []int{0, len(n.Children) - 1, int(maxH)})
+ 315
+ 316				} else {
+ 317					var colHeight float32
+ 318					var colIndex int
+ 319					cols := [][][]float32{}
+ 320
+ 321					// Map elements to columns
+ 322					for i, v := range n.Children {
+ 323						vState := s[v.Properties.Id]
@@ -424,80 +424,80 @@
- 325					// Map elements to columns
- 326					for i, v := range n.Children {
- 327						vState := s[v.Properties.Id]
- 328
- 329						height := vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
- 330						if colHeight+height > selfHeight {
- 331							colHeight = height
- 332							colIndex++
- 333							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 334							if colIndex >= len(cols) {
- 335								cols = append(cols, [][]float32{})
- 336							}
- 337							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
- 338						} else {
- 339							colHeight += height
- 340							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 341							if colIndex >= len(cols) {
- 342								cols = append(cols, [][]float32{})
- 343							}
- 344							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
- 345						}
- 346					}
- 347
- 348					// Find the max total width of all columns
- 349					var totalMaxWidth float32
- 350					maxWidths := []float32{}
- 351					for _, col := range cols {
- 352						var maxWidth, maxHeight float32
- 353						for _, element := range col {
- 354							maxHeight = utils.Max(element[1], maxHeight)
- 355							maxWidth = utils.Max(element[2], maxWidth)
- 356						}
- 357						rows = append(rows, []int{int(col[0][0]), int(col[len(col)-1][0]), int(maxHeight)})
- 358						totalMaxWidth += maxWidth
- 359						maxWidths = append(maxWidths, maxWidth)
- 360					}
- 361					offset := (selfWidth - totalMaxWidth) / float32(len(cols))
- 362					// Move the elements into the correct position
- 363					var xOffset float32
- 364					for i, col := range cols {
- 365						// Move the elements into the correct position
- 366						yOffset := self.Y + self.Border.Width + self.Padding.Top
- 367						for _, element := range col {
- 368							vState := s[n.Children[int(element[0])].Properties.Id]
- 369							xStore := vState.X
- 370							yStore := vState.Y
- 371							vState.X = self.X + self.Padding.Left + self.Border.Width + xOffset + vState.Margin.Left
- 372							vState.Y = yOffset + vState.Margin.Top + vState.Border.Width
- 373							propagateOffsets(&n.Children[int(element[0])], xStore, yStore, vState.X, vState.Y, state)
- 374							// vState.Width = element[2] - (vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2))
- 375							fmt.Println(vState.Width, element[2])
- 376							// vState.Width = 120
- 377
- 378							yOffset += vState.Margin.Top + vState.Border.Width + vState.Height + vState.Margin.Bottom + vState.Border.Width
- 379							(*state)[n.Children[int(element[0])].Properties.Id] = vState
- 380						}
- 381						xOffset += maxWidths[i] + offset
- 382					}
- 383
- 384				}
- 385
- 386				if flexReversed {
- 387					colReverse(rows, n, state)
- 388				}
- 389
- 390				if justifyContent != "normal" {
- 391					justifyCols(rows, n, state, justifyContent, flexReversed)
- 392				}
- 393				if alignContent != "normal" || alignItems != "normal" {
- 394					alignCols(rows, n, state, alignItems, alignContent, innerSizes)
- 395				}
- 396			}
- 397			if n.Style["height"] == "" && n.Style["min-height"] == "" {
- 398				_, h := getInnerSize(n, state)
- 399				self.Height = h
- 400			}
- 401			(*state)[n.Properties.Id] = self
- 402		},
- 403	}
- 404}
+ 325						height := vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+ 326						if colHeight+height > selfHeight {
+ 327							colHeight = height
+ 328							colIndex++
+ 329							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 330							if colIndex >= len(cols) {
+ 331								cols = append(cols, [][]float32{})
+ 332							}
+ 333							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
+ 334						} else {
+ 335							colHeight += height
+ 336							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 337							if colIndex >= len(cols) {
+ 338								cols = append(cols, [][]float32{})
+ 339							}
+ 340							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
+ 341						}
+ 342					}
+ 343
+ 344					// Find the max total width of all columns
+ 345					var totalMaxWidth float32
+ 346					maxWidths := []float32{}
+ 347					for _, col := range cols {
+ 348						var maxWidth, maxHeight float32
+ 349						for _, element := range col {
+ 350							maxHeight = utils.Max(element[1], maxHeight)
+ 351							maxWidth = utils.Max(element[2], maxWidth)
+ 352						}
+ 353						rows = append(rows, []int{int(col[0][0]), int(col[len(col)-1][0]), int(maxHeight)})
+ 354						totalMaxWidth += maxWidth
+ 355						maxWidths = append(maxWidths, maxWidth)
+ 356					}
+ 357					offset := (selfWidth - totalMaxWidth) / float32(len(cols))
+ 358					// Move the elements into the correct position
+ 359					var xOffset float32
+ 360					for i, col := range cols {
+ 361						// Move the elements into the correct position
+ 362						yOffset := self.Y + self.Border.Width + self.Padding.Top
+ 363						for _, element := range col {
+ 364							vState := s[n.Children[int(element[0])].Properties.Id]
+ 365							xStore := vState.X
+ 366							yStore := vState.Y
+ 367							vState.X = self.X + self.Padding.Left + self.Border.Width + xOffset + vState.Margin.Left + vState.Border.Width
+ 368							vState.Y = yOffset + vState.Margin.Top + vState.Border.Width
+ 369							propagateOffsets(&n.Children[int(element[0])], xStore, yStore, vState.X, vState.Y, state)
+ 370
+ 371							yOffset += vState.Margin.Top + vState.Border.Width + vState.Height + vState.Margin.Bottom + vState.Border.Width
+ 372							(*state)[n.Children[int(element[0])].Properties.Id] = vState
+ 373						}
+ 374						xOffset += maxWidths[i] + offset
+ 375					}
+ 376
+ 377				}
+ 378
+ 379				if flexReversed {
+ 380					colReverse(rows, n, state)
+ 381				}
+ 382
+ 383				justifyCols(rows, n, state, justifyContent, flexReversed)
+ 384			}
+ 385			if n.Style["height"] == "" || n.Style["min-height"] == "" {
+ 386				_, h := getInnerSize(n, state)
+ 387				// fmt.Println(h)
+ 388				self.Height = h
+ 389			}
+ 390			(*state)[n.Properties.Id] = self
+ 391		},
+ 392	}
+ 393}
+ 394
+ 395func applyBlock(n *element.Node, state *map[string]element.State) {
+ 396	if len(n.Children) > 0 {
+ 397		accum := float32(0)
+ 398		inlineOffset := float32(0)
+ 399		s := *state
+ 400		lastHeight := float32(0)
+ 401		baseY := s[n.Children[0].Properties.Id].Y
+ 402		for i := 0; i < len(n.Children); i++ {
+ 403			v := &n.Children[i]
+ 404			vState := s[v.Properties.Id]
@@ -505,40 +505,40 @@
- 406func applyBlock(n *element.Node, state *map[string]element.State) {
- 407	if len(n.Children) > 0 {
- 408		accum := float32(0)
- 409		inlineOffset := float32(0)
- 410		s := *state
- 411		lastHeight := float32(0)
- 412		baseY := s[n.Children[0].Properties.Id].Y
- 413		for i := 0; i < len(n.Children); i++ {
- 414			v := &n.Children[i]
- 415			vState := s[v.Properties.Id]
- 416
- 417			if v.Style["display"] != "block" {
- 418				vState.Y += inlineOffset
- 419				accum = (vState.Y - baseY)
- 420				lastHeight = vState.Height
- 421			} else if v.Style["position"] != "absolute" {
- 422				vState.Y += accum
- 423				inlineOffset += (vState.Height + (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom) + lastHeight
- 424			}
- 425			(*state)[v.Properties.Id] = vState
- 426		}
- 427	}
- 428}
- 429
- 430func deInline(n *element.Node, state *map[string]element.State) {
- 431	s := *state
- 432	// self := s[n.Properties.Id]
- 433	baseX := float32(-1)
- 434	baseY := float32(-1)
- 435	for _, v := range n.Children {
- 436		vState := s[v.Properties.Id]
- 437
- 438		if v.Style["display"] == "inline" {
- 439			if baseX < 0 && baseY < 0 {
- 440				baseX = vState.X
- 441				baseY = vState.Y
- 442			} else {
- 443				vState.X = baseX
- 444				vState.Y = baseY
- 445				(*state)[v.Properties.Id] = vState
+ 406			if v.Style["display"] != "block" {
+ 407				vState.Y += inlineOffset
+ 408				accum = (vState.Y - baseY)
+ 409				lastHeight = vState.Height
+ 410			} else if v.Style["position"] != "absolute" {
+ 411				vState.Y += accum
+ 412				inlineOffset += (vState.Height + (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom) + lastHeight
+ 413			}
+ 414			(*state)[v.Properties.Id] = vState
+ 415		}
+ 416	}
+ 417}
+ 418
+ 419func deInline(n *element.Node, state *map[string]element.State) {
+ 420	s := *state
+ 421	// self := s[n.Properties.Id]
+ 422	baseX := float32(-1)
+ 423	baseY := float32(-1)
+ 424	for _, v := range n.Children {
+ 425		vState := s[v.Properties.Id]
+ 426
+ 427		if v.Style["display"] == "inline" {
+ 428			if baseX < 0 && baseY < 0 {
+ 429				baseX = vState.X
+ 430				baseY = vState.Y
+ 431			} else {
+ 432				vState.X = baseX
+ 433				vState.Y = baseY
+ 434				(*state)[v.Properties.Id] = vState
+ 435
+ 436			}
+ 437		} else {
+ 438			baseX = float32(-1)
+ 439			baseY = float32(-1)
+ 440		}
+ 441
+ 442		if len(v.Children) > 0 {
+ 443			deInline(&v, state)
+ 444		}
+ 445	}
@@ -546,10 +546,10 @@
- 447			}
- 448		} else {
- 449			baseX = float32(-1)
- 450			baseY = float32(-1)
- 451		}
- 452
- 453		if len(v.Children) > 0 {
- 454			deInline(&v, state)
- 455		}
- 456	}
+ 447}
+ 448
+ 449func applyInline(n *element.Node, state *map[string]element.State) {
+ 450	pl := inline.Init()
+ 451	for i := 0; i < len(n.Children); i++ {
+ 452		v := &n.Children[i]
+ 453
+ 454		if len(v.Children) > 0 {
+ 455			applyInline(v, state)
+ 456		}
@@ -557,106 +557,106 @@
- 458}
- 459
- 460func applyInline(n *element.Node, state *map[string]element.State) {
- 461	pl := inline.Init()
- 462	for i := 0; i < len(n.Children); i++ {
- 463		v := &n.Children[i]
- 464
- 465		if len(v.Children) > 0 {
- 466			applyInline(v, state)
- 467		}
- 468
- 469		if pl.Selector(v) {
- 470			pl.Handler(v, state)
- 471		}
- 472	}
- 473}
- 474
- 475func propagateOffsets(n *element.Node, prevx, prevy, newx, newy float32, state *map[string]element.State) {
- 476	s := *state
- 477	for _, v := range n.Children {
- 478		vState := s[v.Properties.Id]
- 479		xStore := (vState.X - prevx) + newx
- 480		yStore := (vState.Y - prevy) + newy
- 481
- 482		if len(v.Children) > 0 {
- 483			propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
- 484		}
- 485		vState.X = xStore
- 486		vState.Y = yStore
- 487		(*state)[v.Properties.Id] = vState
- 488	}
- 489
- 490}
- 491
- 492func countText(n element.Node) int {
- 493	count := 0
- 494	groups := []int{}
- 495	for _, v := range n.Children {
- 496		if v.TagName == "notaspan" {
- 497			count += 1
- 498		}
- 499		if v.Style["display"] == "block" {
- 500			groups = append(groups, count)
- 501			count = 0
- 502		}
- 503		if len(v.Children) > 0 {
- 504			count += countText(v)
- 505		}
- 506	}
- 507	groups = append(groups, count)
- 508
- 509	sort.Slice(groups, func(i, j int) bool {
- 510		return groups[i] > groups[j]
- 511	})
- 512	return groups[0]
- 513}
- 514
- 515func minHeight(n element.Node, state *map[string]element.State, prev float32) float32 {
- 516	s := *state
- 517	self := s[n.Properties.Id]
- 518	if n.Style["min-height"] != "" {
- 519		mw := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
- 520		return utils.Max(prev, mw)
- 521	} else {
- 522		return prev
- 523	}
- 524
- 525}
- 526
- 527func getMinHeight(n *element.Node, state *map[string]element.State) float32 {
- 528	s := *state
- 529	self := s[n.Properties.Id]
- 530	selfHeight := float32(0)
- 531
- 532	if len(n.Children) > 0 {
- 533		for _, v := range n.Children {
- 534			selfHeight = utils.Max(selfHeight, getNodeHeight(&v, state))
- 535		}
- 536	} else {
- 537		selfHeight = self.Height
- 538	}
- 539	if n.Style["min-height"] != "" {
- 540		mh := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
- 541		selfHeight = utils.Max(mh, selfHeight)
- 542	}
- 543
- 544	selfHeight += self.Padding.Top + self.Padding.Bottom
- 545	return selfHeight
- 546}
- 547
- 548func getMinWidth(n *element.Node, state *map[string]element.State) float32 {
- 549	s := *state
- 550	self := s[n.Properties.Id]
- 551	selfWidth := float32(0)
- 552
- 553	if len(n.Children) > 0 {
- 554		for _, v := range n.Children {
- 555			selfWidth = utils.Max(selfWidth, getNodeWidth(&v, state))
- 556		}
- 557	} else {
- 558		selfWidth = self.Width
- 559	}
- 560	if n.Style["min-width"] != "" {
- 561		mw := utils.ConvertToPixels(n.Style["min-width"], self.EM, s[n.Parent.Properties.Id].Width)
- 562		selfWidth = utils.Max(mw, selfWidth)
- 563	}
+ 458		if pl.Selector(v) {
+ 459			pl.Handler(v, state)
+ 460		}
+ 461	}
+ 462}
+ 463
+ 464func propagateOffsets(n *element.Node, prevx, prevy, newx, newy float32, state *map[string]element.State) {
+ 465	s := *state
+ 466	for _, v := range n.Children {
+ 467		vState := s[v.Properties.Id]
+ 468		xStore := (vState.X - prevx) + newx
+ 469		yStore := (vState.Y - prevy) + newy
+ 470
+ 471		if len(v.Children) > 0 {
+ 472			propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
+ 473		}
+ 474		vState.X = xStore
+ 475		vState.Y = yStore
+ 476		(*state)[v.Properties.Id] = vState
+ 477	}
+ 478
+ 479}
+ 480
+ 481func countText(n element.Node) int {
+ 482	count := 0
+ 483	groups := []int{}
+ 484	for _, v := range n.Children {
+ 485		if v.TagName == "notaspan" {
+ 486			count += 1
+ 487		}
+ 488		if v.Style["display"] == "block" {
+ 489			groups = append(groups, count)
+ 490			count = 0
+ 491		}
+ 492		if len(v.Children) > 0 {
+ 493			count += countText(v)
+ 494		}
+ 495	}
+ 496	groups = append(groups, count)
+ 497
+ 498	sort.Slice(groups, func(i, j int) bool {
+ 499		return groups[i] > groups[j]
+ 500	})
+ 501	return groups[0]
+ 502}
+ 503
+ 504func minHeight(n element.Node, state *map[string]element.State, prev float32) float32 {
+ 505	s := *state
+ 506	self := s[n.Properties.Id]
+ 507	if n.Style["min-height"] != "" {
+ 508		mw := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
+ 509		return utils.Max(prev, mw)
+ 510	} else {
+ 511		return prev
+ 512	}
+ 513
+ 514}
+ 515
+ 516func getMinHeight(n *element.Node, state *map[string]element.State) float32 {
+ 517	s := *state
+ 518	self := s[n.Properties.Id]
+ 519	selfHeight := float32(0)
+ 520
+ 521	if len(n.Children) > 0 {
+ 522		for _, v := range n.Children {
+ 523			selfHeight = utils.Max(selfHeight, getNodeHeight(&v, state))
+ 524		}
+ 525	} else {
+ 526		selfHeight = self.Height
+ 527	}
+ 528	if n.Style["min-height"] != "" {
+ 529		mh := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
+ 530		selfHeight = utils.Max(mh, selfHeight)
+ 531	}
+ 532
+ 533	selfHeight += self.Padding.Top + self.Padding.Bottom
+ 534	return selfHeight
+ 535}
+ 536
+ 537func getMinWidth(n *element.Node, state *map[string]element.State) float32 {
+ 538	s := *state
+ 539	self := s[n.Properties.Id]
+ 540	selfWidth := float32(0)
+ 541
+ 542	if len(n.Children) > 0 {
+ 543		for _, v := range n.Children {
+ 544			selfWidth = utils.Max(selfWidth, getNodeWidth(&v, state))
+ 545		}
+ 546	} else {
+ 547		selfWidth = self.Width
+ 548	}
+ 549	if n.Style["min-width"] != "" {
+ 550		mw := utils.ConvertToPixels(n.Style["min-width"], self.EM, s[n.Parent.Properties.Id].Width)
+ 551		selfWidth = utils.Max(mw, selfWidth)
+ 552	}
+ 553
+ 554	selfWidth += self.Padding.Left + self.Padding.Right
+ 555	return selfWidth
+ 556}
+ 557func getMaxWidth(n *element.Node, state *map[string]element.State) float32 {
+ 558	s := *state
+ 559	self := s[n.Properties.Id]
+ 560	selfWidth := float32(0)
+ 561
+ 562	if len(n.Children) > 0 {
+ 563		var maxRowWidth, rowWidth float32
@@ -664,22 +664,22 @@
- 565	selfWidth += self.Padding.Left + self.Padding.Right
- 566	return selfWidth
- 567}
- 568func getMaxWidth(n *element.Node, state *map[string]element.State) float32 {
- 569	s := *state
- 570	self := s[n.Properties.Id]
- 571	selfWidth := float32(0)
- 572
- 573	if len(n.Children) > 0 {
- 574		var maxRowWidth, rowWidth float32
- 575
- 576		for _, v := range n.Children {
- 577			rowWidth += getNodeWidth(&v, state)
- 578			if v.Style["display"] != "inline" {
- 579				maxRowWidth = utils.Max(rowWidth, maxRowWidth)
- 580				rowWidth = 0
- 581			}
- 582		}
- 583		selfWidth = utils.Max(rowWidth, maxRowWidth)
- 584	} else {
- 585		selfWidth = self.Width
- 586	}
+ 565		for _, v := range n.Children {
+ 566			rowWidth += getNodeWidth(&v, state)
+ 567			if v.Style["display"] != "inline" {
+ 568				maxRowWidth = utils.Max(rowWidth, maxRowWidth)
+ 569				rowWidth = 0
+ 570			}
+ 571		}
+ 572		selfWidth = utils.Max(rowWidth, maxRowWidth)
+ 573	} else {
+ 574		selfWidth = self.Width
+ 575	}
+ 576
+ 577	selfWidth += self.Padding.Left + self.Padding.Right
+ 578	return selfWidth
+ 579}
+ 580
+ 581func getNodeWidth(n *element.Node, state *map[string]element.State) float32 {
+ 582	s := *state
+ 583	self := s[n.Properties.Id]
+ 584	w := float32(0)
+ 585	w += self.Padding.Left
+ 586	w += self.Padding.Right
@@ -687,10 +687,10 @@
- 588	selfWidth += self.Padding.Left + self.Padding.Right
- 589	return selfWidth
- 590}
- 591
- 592func getNodeWidth(n *element.Node, state *map[string]element.State) float32 {
- 593	s := *state
- 594	self := s[n.Properties.Id]
- 595	w := float32(0)
- 596	w += self.Padding.Left
- 597	w += self.Padding.Right
+ 588	w += self.Margin.Left
+ 589	w += self.Margin.Right
+ 590
+ 591	w += self.Width
+ 592
+ 593	w += self.Border.Width * 2
+ 594
+ 595	for _, v := range n.Children {
+ 596		w = utils.Max(w, getNodeWidth(&v, state))
+ 597	}
@@ -698,6 +698,6 @@
- 599	w += self.Margin.Left
- 600	w += self.Margin.Right
- 601
- 602	w += self.Width
- 603
- 604	w += self.Border.Width * 2
+ 599	return w
+ 600}
+ 601func getMaxHeight(n *element.Node, state *map[string]element.State) float32 {
+ 602	s := *state
+ 603	self := s[n.Properties.Id]
+ 604	selfHeight := float32(0)
@@ -705,72 +705,72 @@
- 606	for _, v := range n.Children {
- 607		w = utils.Max(w, getNodeWidth(&v, state))
- 608	}
- 609
- 610	return w
- 611}
- 612
- 613// func getMaxHeight(n *element.Node, state *map[string]element.State) float32 {
- 614// 	s := *state
- 615// 	self := s[n.Properties.Id]
- 616// 	selfHeight := float32(0)
- 617
- 618// 	if len(n.Children) > 0 {
- 619// 		var maxRowHeight, rowHeight float32
- 620
- 621// 		for _, v := range n.Children {
- 622// 			rowHeight += getNodeHeight(&v, state)
- 623// 			if v.Style["display"] != "inline" {
- 624// 				maxRowHeight = utils.Max(rowHeight, maxRowHeight)
- 625// 				rowHeight = 0
- 626// 			}
- 627// 		}
- 628// 		selfHeight = utils.Max(rowHeight, maxRowHeight)
- 629// 	} else {
- 630// 		selfHeight = self.Height
- 631// 	}
- 632
- 633// 	selfHeight += self.Padding.Top + self.Padding.Bottom
- 634// 	return selfHeight
- 635// }
- 636
- 637func getNodeHeight(n *element.Node, state *map[string]element.State) float32 {
- 638	s := *state
- 639	self := s[n.Properties.Id]
- 640	h := float32(0)
- 641	h += self.Padding.Top
- 642	h += self.Padding.Bottom
- 643
- 644	h += self.Margin.Top
- 645	h += self.Margin.Bottom
- 646
- 647	h += self.Height
- 648
- 649	h += self.Border.Width * 2
- 650
- 651	for _, v := range n.Children {
- 652		h = utils.Max(h, getNodeHeight(&v, state))
- 653	}
- 654
- 655	return h
- 656}
- 657
- 658func getInnerSize(n *element.Node, state *map[string]element.State) (float32, float32) {
- 659	s := *state
- 660	self := s[n.Properties.Id]
- 661
- 662	minx := float32(10e10)
- 663	maxw := float32(0)
- 664	miny := float32(10e10)
- 665	maxh := float32(0)
- 666	for _, v := range n.Children {
- 667		vState := s[v.Properties.Id]
- 668		minx = utils.Min(vState.X, minx)
- 669		miny = utils.Min(vState.Y-vState.Margin.Top, miny)
- 670		// Don't add the top or left because the x&y values already take that into account
- 671		hOffset := (vState.Border.Width * 2) + vState.Margin.Bottom
- 672		wOffset := (vState.Border.Width * 2) + vState.Margin.Right
- 673		maxw = utils.Max(vState.X+vState.Width+wOffset, maxw)
- 674		maxh = utils.Max(vState.Y+vState.Height+hOffset, maxh)
- 675	}
- 676	w := maxw - minx
- 677	h := maxh - miny
+ 606	if len(n.Children) > 0 {
+ 607		var maxRowHeight, rowHeight float32
+ 608
+ 609		for _, v := range n.Children {
+ 610			rowHeight += getNodeHeight(&v, state)
+ 611			if v.Style["display"] != "inline" {
+ 612				maxRowHeight = utils.Max(rowHeight, maxRowHeight)
+ 613				rowHeight = 0
+ 614			}
+ 615		}
+ 616		selfHeight = utils.Max(rowHeight, maxRowHeight)
+ 617	} else {
+ 618		selfHeight = self.Height
+ 619	}
+ 620
+ 621	selfHeight += self.Padding.Top + self.Padding.Bottom
+ 622	return selfHeight
+ 623}
+ 624
+ 625func getNodeHeight(n *element.Node, state *map[string]element.State) float32 {
+ 626	s := *state
+ 627	self := s[n.Properties.Id]
+ 628	h := float32(0)
+ 629	h += self.Padding.Top
+ 630	h += self.Padding.Bottom
+ 631
+ 632	h += self.Margin.Top
+ 633	h += self.Margin.Bottom
+ 634
+ 635	h += self.Height
+ 636
+ 637	h += self.Border.Width * 2
+ 638
+ 639	for _, v := range n.Children {
+ 640		h = utils.Max(h, getNodeHeight(&v, state))
+ 641	}
+ 642
+ 643	return h
+ 644}
+ 645
+ 646func getInnerSize(n *element.Node, state *map[string]element.State) (float32, float32) {
+ 647	s := *state
+ 648	self := s[n.Properties.Id]
+ 649
+ 650	minx := float32(10e10)
+ 651	maxw := float32(0)
+ 652	miny := float32(10e10)
+ 653	maxh := float32(0)
+ 654	for _, v := range n.Children {
+ 655		vState := s[v.Properties.Id]
+ 656		minx = utils.Min(vState.X, minx)
+ 657		miny = utils.Min(vState.Y-vState.Margin.Top, miny)
+ 658		// Don't add the top or left because the x&y values already take that into account
+ 659		hOffset := (vState.Border.Width * 2) + vState.Margin.Bottom
+ 660		wOffset := (vState.Border.Width * 2) + vState.Margin.Right
+ 661		maxw = utils.Max(vState.X+vState.Width+wOffset, maxw)
+ 662		maxh = utils.Max(vState.Y+vState.Height+hOffset, maxh)
+ 663	}
+ 664	w := maxw - minx
+ 665	h := maxh - miny
+ 666
+ 667	w += self.Padding.Left + self.Padding.Right
+ 668	h += self.Padding.Top + self.Padding.Bottom
+ 669	if n.Style["width"] != "" {
+ 670		w = self.Width
+ 671	}
+ 672	if n.Style["height"] != "" {
+ 673		h = self.Height
+ 674	}
+ 675
+ 676	return w, h
+ 677}
@@ -778,4 +778,4 @@
- 679	w += self.Padding.Left + self.Padding.Right
- 680	h += self.Padding.Top + self.Padding.Bottom
- 681	if n.Style["width"] != "" {
- 682		w = self.Width
+ 679func add2d(arr [][]float32, index int) float32 {
+ 680	var sum float32
+ 681	if len(arr) == 0 {
+ 682		return sum
@@ -783,32 +783,32 @@
- 684	if n.Style["height"] != "" {
- 685		h = self.Height
- 686	}
- 687
- 688	return w, h
- 689}
- 690
- 691func add2d(arr [][]float32, index int) float32 {
- 692	var sum float32
- 693	if len(arr) == 0 {
- 694		return sum
- 695	}
- 696
- 697	for i := 0; i < len(arr); i++ {
- 698		if len(arr[i]) <= index {
- 699			return sum
- 700		}
- 701		sum += arr[i][index]
- 702	}
- 703
- 704	return sum
- 705}
- 706
- 707func colReverse(cols [][]int, n *element.Node, state *map[string]element.State) {
- 708	s := *state
- 709	for _, col := range cols {
- 710		tempNodes := []element.Node{}
- 711		tempStates := []element.State{}
- 712
- 713		for i := col[1]; i >= col[0]; i-- {
- 714			tempNodes = append(tempNodes, n.Children[i])
- 715			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
+ 684
+ 685	for i := 0; i < len(arr); i++ {
+ 686		if len(arr[i]) <= index {
+ 687			return sum
+ 688		}
+ 689		sum += arr[i][index]
+ 690	}
+ 691
+ 692	return sum
+ 693}
+ 694
+ 695func colReverse(cols [][]int, n *element.Node, state *map[string]element.State) {
+ 696	s := *state
+ 697	for _, col := range cols {
+ 698		tempNodes := []element.Node{}
+ 699		tempStates := []element.State{}
+ 700
+ 701		for i := col[1]; i >= col[0]; i-- {
+ 702			tempNodes = append(tempNodes, n.Children[i])
+ 703			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
+ 704		}
+ 705
+ 706		for i := 0; i < len(tempStates); i++ {
+ 707			e := col[0] + i
+ 708			vState := s[n.Children[e].Properties.Id]
+ 709			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
+ 710			vState.Y = tempStates[i].Y
+ 711			(*state)[n.Children[e].Properties.Id] = vState
+ 712		}
+ 713		for i := 0; i < len(tempStates); i++ {
+ 714			e := col[0] + i
+ 715			n.Children[e] = tempNodes[i]
@@ -817,38 +817,38 @@
- 718		for i := 0; i < len(tempStates); i++ {
- 719			e := col[0] + i
- 720			vState := s[n.Children[e].Properties.Id]
- 721			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
- 722			vState.Y = tempStates[i].Y
- 723			(*state)[n.Children[e].Properties.Id] = vState
- 724		}
- 725		for i := 0; i < len(tempStates); i++ {
- 726			e := col[0] + i
- 727			n.Children[e] = tempNodes[i]
- 728		}
- 729
- 730		for i := col[1]; i >= col[0]; i-- {
- 731			vState := s[n.Children[i].Properties.Id]
- 732			var yChng float32
- 733			if i < col[1] {
- 734				sib := s[n.Children[i+1].Properties.Id]
- 735				yChng = sib.Y - (sib.Border.Width + sib.Margin.Top + vState.Margin.Bottom + vState.Border.Width + vState.Height)
- 736			} else {
- 737				parent := s[n.Properties.Id]
- 738				yChng = ((((parent.Y + parent.Height) - parent.Padding.Bottom) - vState.Height) - vState.Margin.Bottom) - (vState.Border.Width)
- 739			}
- 740			propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, yChng, state)
- 741			vState.Y = yChng
- 742			(*state)[n.Children[i].Properties.Id] = vState
- 743		}
- 744	}
- 745}
- 746
- 747func rowReverse(rows [][]int, n *element.Node, state *map[string]element.State) {
- 748	s := *state
- 749	for _, row := range rows {
- 750		tempNodes := []element.Node{}
- 751		tempStates := []element.State{}
- 752
- 753		for i := row[1] - 1; i >= row[0]; i-- {
- 754			tempNodes = append(tempNodes, n.Children[i])
- 755			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
+ 718		for i := col[1]; i >= col[0]; i-- {
+ 719			vState := s[n.Children[i].Properties.Id]
+ 720			var yChng float32
+ 721			if i < col[1] {
+ 722				sib := s[n.Children[i+1].Properties.Id]
+ 723				yChng = sib.Y - (sib.Border.Width + sib.Margin.Top + vState.Margin.Bottom + vState.Border.Width + vState.Height)
+ 724			} else {
+ 725				parent := s[n.Properties.Id]
+ 726				yChng = ((((parent.Y + parent.Height) - parent.Padding.Bottom) - vState.Height) - vState.Margin.Bottom) - (vState.Border.Width)
+ 727			}
+ 728			propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, yChng, state)
+ 729			vState.Y = yChng
+ 730			(*state)[n.Children[i].Properties.Id] = vState
+ 731		}
+ 732	}
+ 733}
+ 734
+ 735func rowReverse(rows [][]int, n *element.Node, state *map[string]element.State) {
+ 736	s := *state
+ 737	for _, row := range rows {
+ 738		tempNodes := []element.Node{}
+ 739		tempStates := []element.State{}
+ 740
+ 741		for i := row[1] - 1; i >= row[0]; i-- {
+ 742			tempNodes = append(tempNodes, n.Children[i])
+ 743			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
+ 744		}
+ 745
+ 746		for i := 0; i < len(tempStates); i++ {
+ 747			e := row[0] + i
+ 748			vState := s[n.Children[e].Properties.Id]
+ 749			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
+ 750			vState.X = tempStates[i].X
+ 751			(*state)[n.Children[e].Properties.Id] = vState
+ 752		}
+ 753		for i := 0; i < len(tempStates); i++ {
+ 754			e := row[0] + i
+ 755			n.Children[e] = tempNodes[i]
@@ -857,21 +857,21 @@
- 758		for i := 0; i < len(tempStates); i++ {
- 759			e := row[0] + i
- 760			vState := s[n.Children[e].Properties.Id]
- 761			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
- 762			vState.X = tempStates[i].X
- 763			(*state)[n.Children[e].Properties.Id] = vState
- 764		}
- 765		for i := 0; i < len(tempStates); i++ {
- 766			e := row[0] + i
- 767			n.Children[e] = tempNodes[i]
- 768		}
- 769
- 770		for i := row[1] - 1; i >= row[0]; i-- {
- 771			vState := s[n.Children[i].Properties.Id]
- 772			var xChng float32
- 773			if i < row[1]-1 {
- 774				sib := s[n.Children[i+1].Properties.Id]
- 775				xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
- 776			} else {
- 777				parent := s[n.Properties.Id]
- 778				xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
+ 758		for i := row[1] - 1; i >= row[0]; i-- {
+ 759			vState := s[n.Children[i].Properties.Id]
+ 760			var xChng float32
+ 761			if i < row[1]-1 {
+ 762				sib := s[n.Children[i+1].Properties.Id]
+ 763				xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
+ 764			} else {
+ 765				parent := s[n.Properties.Id]
+ 766				xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
+ 767
+ 768			}
+ 769			propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+ 770			vState.X = xChng
+ 771			(*state)[n.Children[i].Properties.Id] = vState
+ 772		}
+ 773	}
+ 774}
+ 775
+ 776func justifyRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
+ 777	s := *state
+ 778	for _, row := range rows {
@@ -879,106 +879,106 @@
- 780			}
- 781			propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
- 782			vState.X = xChng
- 783			(*state)[n.Children[i].Properties.Id] = vState
- 784		}
- 785	}
- 786}
- 787
- 788func justifyRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
- 789	s := *state
- 790	for _, row := range rows {
- 791
- 792		if (justify == "flex-end" || justify == "end" || justify == "right") && !reversed {
- 793			for i := row[1] - 1; i >= row[0]; i-- {
- 794				vState := s[n.Children[i].Properties.Id]
- 795				var xChng float32
- 796				if i < row[1]-1 {
- 797					sib := s[n.Children[i+1].Properties.Id]
- 798					xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
- 799				} else {
- 800					parent := s[n.Properties.Id]
- 801					xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
- 802
- 803				}
- 804				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
- 805				vState.X = xChng
- 806				(*state)[n.Children[i].Properties.Id] = vState
- 807			}
- 808		} else if (justify == "flex-end" || justify == "start" || justify == "left" || justify == "normal") && reversed {
- 809			for i := row[0]; i < row[1]; i++ {
- 810				vState := s[n.Children[i].Properties.Id]
- 811				var xChng float32
- 812				if i > row[0] {
- 813					sib := s[n.Children[i-1].Properties.Id]
- 814					xChng = sib.X + sib.Width + (sib.Border.Width * 2) + sib.Margin.Right + vState.Margin.Left + vState.Border.Width
- 815				} else {
- 816					parent := s[n.Properties.Id]
- 817					xChng = parent.X + parent.Padding.Right + vState.Margin.Left + vState.Border.Width + parent.Border.Width
- 818
- 819				}
- 820				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
- 821				vState.X = xChng
- 822				(*state)[n.Children[i].Properties.Id] = vState
- 823			}
- 824		} else if justify == "center" {
- 825			// get width of row then center (by getting last x + w + mr + b)
- 826			f := s[n.Children[row[0]].Properties.Id]
- 827			l := s[n.Children[row[1]-1].Properties.Id]
- 828			parent := s[n.Properties.Id]
- 829			po := parent.X + parent.Border.Width
- 830			offset := (parent.Width - ((f.X - po) + (l.X - po) + l.Width + f.Border.Width + l.Border.Width)) / 2
- 831
- 832			for i := row[0]; i < row[1]; i++ {
- 833				vState := s[n.Children[i].Properties.Id]
- 834
- 835				if !reversed {
- 836					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
- 837					vState.X += offset
- 838				} else {
- 839					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
- 840					vState.X -= offset
- 841				}
- 842				(*state)[n.Children[i].Properties.Id] = vState
- 843			}
- 844
- 845		} else if justify == "space-between" {
- 846			// get width of row then center (by getting last x + w + mr + b)
- 847			f := s[n.Children[row[0]].Properties.Id]
- 848			l := s[n.Children[row[1]-1].Properties.Id]
- 849			parent := s[n.Properties.Id]
- 850			po := parent.Border.Width + parent.Width
- 851			po -= parent.Padding.Left + parent.Padding.Right
- 852
- 853			// make po repersent the total space between elements
- 854			for i := row[0]; i < row[1]; i++ {
- 855				vState := s[n.Children[i].Properties.Id]
- 856				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 857			}
- 858
- 859			po /= float32(((row[1]) - row[0]) - 1)
- 860
- 861			if (row[1]-1)-row[0] > 0 {
- 862				for i := row[0]; i < row[1]; i++ {
- 863					vState := s[n.Children[i].Properties.Id]
- 864					var offset float32
- 865					if i == row[0] {
- 866						offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
- 867					} else if i == row[1]-1 {
- 868						offset = (parent.X + parent.Width) - (l.Margin.Right + l.Border.Width + l.Width + parent.Padding.Right)
- 869					} else {
- 870						if !reversed {
- 871							offset = vState.X + (po * float32(i-row[0]))
- 872						} else {
- 873							offset = vState.X - (po * float32(((row[1]-1)-row[0])-(i-row[0])))
- 874						}
- 875
- 876					}
- 877
- 878					propagateOffsets(&n.Children[i], vState.X, vState.Y, offset, vState.Y, state)
- 879					vState.X = offset
- 880					(*state)[n.Children[i].Properties.Id] = vState
- 881				}
- 882			}
- 883			//  else {
- 884
- 885			// this is/was causing issues, removed and it fixed its self
+ 780		if (justify == "flex-end" || justify == "end" || justify == "right") && !reversed {
+ 781			for i := row[1] - 1; i >= row[0]; i-- {
+ 782				vState := s[n.Children[i].Properties.Id]
+ 783				var xChng float32
+ 784				if i < row[1]-1 {
+ 785					sib := s[n.Children[i+1].Properties.Id]
+ 786					xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
+ 787				} else {
+ 788					parent := s[n.Properties.Id]
+ 789					xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
+ 790
+ 791				}
+ 792				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+ 793				vState.X = xChng
+ 794				(*state)[n.Children[i].Properties.Id] = vState
+ 795			}
+ 796		} else if (justify == "flex-end" || justify == "start" || justify == "left" || justify == "normal") && reversed {
+ 797			for i := row[0]; i < row[1]; i++ {
+ 798				vState := s[n.Children[i].Properties.Id]
+ 799				var xChng float32
+ 800				if i > row[0] {
+ 801					sib := s[n.Children[i-1].Properties.Id]
+ 802					xChng = sib.X + sib.Width + (sib.Border.Width * 2) + sib.Margin.Right + vState.Margin.Left + vState.Border.Width
+ 803				} else {
+ 804					parent := s[n.Properties.Id]
+ 805					xChng = parent.X + parent.Padding.Right + vState.Margin.Left + vState.Border.Width + parent.Border.Width
+ 806
+ 807				}
+ 808				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+ 809				vState.X = xChng
+ 810				(*state)[n.Children[i].Properties.Id] = vState
+ 811			}
+ 812		} else if justify == "center" {
+ 813			// get width of row then center (by getting last x + w + mr + b)
+ 814			f := s[n.Children[row[0]].Properties.Id]
+ 815			l := s[n.Children[row[1]-1].Properties.Id]
+ 816			parent := s[n.Properties.Id]
+ 817			po := parent.X + parent.Border.Width
+ 818			offset := (parent.Width - ((f.X - po) + (l.X - po) + l.Width + f.Border.Width + l.Border.Width)) / 2
+ 819
+ 820			for i := row[0]; i < row[1]; i++ {
+ 821				vState := s[n.Children[i].Properties.Id]
+ 822
+ 823				if !reversed {
+ 824					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+ 825					vState.X += offset
+ 826				} else {
+ 827					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+ 828					vState.X -= offset
+ 829				}
+ 830				(*state)[n.Children[i].Properties.Id] = vState
+ 831			}
+ 832
+ 833		} else if justify == "space-between" {
+ 834			// get width of row then center (by getting last x + w + mr + b)
+ 835			f := s[n.Children[row[0]].Properties.Id]
+ 836			l := s[n.Children[row[1]-1].Properties.Id]
+ 837			parent := s[n.Properties.Id]
+ 838			po := parent.Border.Width + parent.Width
+ 839			po -= parent.Padding.Left + parent.Padding.Right
+ 840
+ 841			// make po repersent the total space between elements
+ 842			for i := row[0]; i < row[1]; i++ {
+ 843				vState := s[n.Children[i].Properties.Id]
+ 844				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 845			}
+ 846
+ 847			po /= float32(((row[1]) - row[0]) - 1)
+ 848
+ 849			if (row[1]-1)-row[0] > 0 {
+ 850				for i := row[0]; i < row[1]; i++ {
+ 851					vState := s[n.Children[i].Properties.Id]
+ 852					var offset float32
+ 853					if i == row[0] {
+ 854						offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
+ 855					} else if i == row[1]-1 {
+ 856						offset = (parent.X + parent.Width) - (l.Margin.Right + l.Border.Width + l.Width + parent.Padding.Right)
+ 857					} else {
+ 858						if !reversed {
+ 859							offset = vState.X + (po * float32(i-row[0]))
+ 860						} else {
+ 861							offset = vState.X - (po * float32(((row[1]-1)-row[0])-(i-row[0])))
+ 862						}
+ 863
+ 864					}
+ 865
+ 866					propagateOffsets(&n.Children[i], vState.X, vState.Y, offset, vState.Y, state)
+ 867					vState.X = offset
+ 868					(*state)[n.Children[i].Properties.Id] = vState
+ 869				}
+ 870			}
+ 871			//  else {
+ 872
+ 873			// this is/was causing issues, removed and it fixed its self
+ 874
+ 875			// if there is one element move left
+ 876			// vState := s[n.Children[(row[1]-1)-row[0]].Properties.Id]
+ 877			// var offset float32
+ 878
+ 879			// if !reversed {
+ 880			// 	offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
+ 881			// 	propagateOffsets(&n.Children[(row[1]-1)-row[0]], vState.X, vState.Y, offset, vState.Y, state)
+ 882			// 	vState.X = offset
+ 883
+ 884			// 	(*state)[n.Children[(row[1]-1)-row[0]].Properties.Id] = vState
+ 885			// }
@@ -986,27 +986,27 @@
- 887			// if there is one element move left
- 888			// vState := s[n.Children[(row[1]-1)-row[0]].Properties.Id]
- 889			// var offset float32
- 890
- 891			// if !reversed {
- 892			// 	offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
- 893			// 	propagateOffsets(&n.Children[(row[1]-1)-row[0]], vState.X, vState.Y, offset, vState.Y, state)
- 894			// 	vState.X = offset
- 895
- 896			// 	(*state)[n.Children[(row[1]-1)-row[0]].Properties.Id] = vState
- 897			// }
- 898
- 899			// }
- 900
- 901		} else if justify == "space-evenly" {
- 902			// get width of row then center (by getting last x + w + mr + b)
- 903			parent := s[n.Properties.Id]
- 904			po := parent.Border.Width + parent.Width
- 905			po -= parent.Padding.Left + parent.Padding.Right
- 906
- 907			// make po repersent the total space between elements
- 908			for i := row[0]; i < row[1]; i++ {
- 909				vState := s[n.Children[i].Properties.Id]
- 910				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 911			}
- 912
- 913			po /= float32(((row[1]) - row[0]) + 1)
+ 887			// }
+ 888
+ 889		} else if justify == "space-evenly" {
+ 890			// get width of row then center (by getting last x + w + mr + b)
+ 891			parent := s[n.Properties.Id]
+ 892			po := parent.Border.Width + parent.Width
+ 893			po -= parent.Padding.Left + parent.Padding.Right
+ 894
+ 895			// make po repersent the total space between elements
+ 896			for i := row[0]; i < row[1]; i++ {
+ 897				vState := s[n.Children[i].Properties.Id]
+ 898				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 899			}
+ 900
+ 901			po /= float32(((row[1]) - row[0]) + 1)
+ 902
+ 903			// get width of row then center (by getting last x + w + mr + b)
+ 904
+ 905			for i := row[0]; i < row[1]; i++ {
+ 906				vState := s[n.Children[i].Properties.Id]
+ 907
+ 908				if !reversed {
+ 909					offset := po * (float32(i-row[0]) + 1)
+ 910					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+ 911					vState.X += offset
+ 912				} else {
+ 913					offset := po * float32(((row[1]-1)-row[0])-((i-row[0])-1))
@@ -1014,11 +1014,11 @@
- 915			// get width of row then center (by getting last x + w + mr + b)
- 916
- 917			for i := row[0]; i < row[1]; i++ {
- 918				vState := s[n.Children[i].Properties.Id]
- 919
- 920				if !reversed {
- 921					offset := po * (float32(i-row[0]) + 1)
- 922					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
- 923					vState.X += offset
- 924				} else {
- 925					offset := po * float32(((row[1]-1)-row[0])-((i-row[0])-1))
+ 915					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+ 916					vState.X -= offset
+ 917				}
+ 918				(*state)[n.Children[i].Properties.Id] = vState
+ 919			}
+ 920
+ 921		} else if justify == "space-around" {
+ 922			// get width of row then center (by getting last x + w + mr + b)
+ 923			parent := s[n.Properties.Id]
+ 924			po := parent.Border.Width + parent.Width
+ 925			po -= parent.Padding.Left + parent.Padding.Right
@@ -1026,4 +1026,4 @@
- 927					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
- 928					vState.X -= offset
- 929				}
- 930				(*state)[n.Children[i].Properties.Id] = vState
+ 927			// make po repersent the total space between elements
+ 928			for i := row[0]; i < row[1]; i++ {
+ 929				vState := s[n.Children[i].Properties.Id]
+ 930				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
@@ -1032,91 +1032,91 @@
- 933		} else if justify == "space-around" {
- 934			// get width of row then center (by getting last x + w + mr + b)
- 935			parent := s[n.Properties.Id]
- 936			po := parent.Border.Width + parent.Width
- 937			po -= parent.Padding.Left + parent.Padding.Right
- 938
- 939			// make po repersent the total space between elements
- 940			for i := row[0]; i < row[1]; i++ {
- 941				vState := s[n.Children[i].Properties.Id]
- 942				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 943			}
- 944
- 945			po /= float32(((row[1]) - row[0]))
- 946
- 947			// get width of row then center (by getting last x + w + mr + b)
- 948
- 949			for i := row[0]; i < row[1]; i++ {
- 950				vState := s[n.Children[i].Properties.Id]
- 951
- 952				if !reversed {
- 953					m := (float32(i-row[0]) + 1)
- 954					if i-row[0] == 0 {
- 955						m = 0.5
- 956					} else {
- 957						m -= 0.5
- 958					}
- 959					offset := po * m
- 960					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
- 961					vState.X += offset
- 962				} else {
- 963					m := float32(((row[1] - 1) - row[0]) - ((i - row[0]) - 1))
- 964					m -= 0.5
- 965					offset := po * m
- 966
- 967					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
- 968					vState.X -= offset
- 969				}
- 970				(*state)[n.Children[i].Properties.Id] = vState
- 971			}
- 972
- 973		}
- 974
- 975	}
- 976}
- 977
- 978func alignRow(rows [][]int, n *element.Node, state *map[string]element.State, align, content string) {
- 979	// !ISSUE: Baseline isn't properly impleamented
- 980
- 981	s := *state
- 982	self := s[n.Properties.Id]
- 983
- 984	maxes := []float32{}
- 985	var maxesTotal float32
- 986	for _, row := range rows {
- 987		var maxH float32
- 988		for i := row[0]; i < row[1]; i++ {
- 989			vState := s[n.Children[i].Properties.Id]
- 990			_, h := getInnerSize(&n.Children[i], state)
- 991			h = minHeight(n.Children[i], state, h)
- 992			vState.Height = h
- 993			h += vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
- 994			maxH = utils.Max(maxH, h)
- 995			(*state)[n.Children[i].Properties.Id] = vState
- 996		}
- 997		maxes = append(maxes, maxH)
- 998		maxesTotal += maxH
- 999	}
-1000
-1001	os := ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
-1002	if os < 0 || content != "normal" {
-1003		os = 0
-1004	}
-1005
-1006	var contentOffset float32
-1007
-1008	if content == "center" {
-1009		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / 2
-1010	} else if content == "end" || content == "flex-end" {
-1011		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal)
-1012	} else if content == "start" || content == "flex-start" || content == "baseline" {
-1013		// This is redundent but it helps keep track
-1014		contentOffset = 0
-1015	} else if content == "space-between" {
-1016		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)-1)
-1017	} else if content == "space-around" {
-1018		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
-1019		contentOffset = os / 2
-1020	} else if content == "space-evenly" {
-1021		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)+1)
-1022		contentOffset = os
-1023	}
+ 933			po /= float32(((row[1]) - row[0]))
+ 934
+ 935			// get width of row then center (by getting last x + w + mr + b)
+ 936
+ 937			for i := row[0]; i < row[1]; i++ {
+ 938				vState := s[n.Children[i].Properties.Id]
+ 939
+ 940				if !reversed {
+ 941					m := (float32(i-row[0]) + 1)
+ 942					if i-row[0] == 0 {
+ 943						m = 0.5
+ 944					} else {
+ 945						m -= 0.5
+ 946					}
+ 947					offset := po * m
+ 948					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+ 949					vState.X += offset
+ 950				} else {
+ 951					m := float32(((row[1] - 1) - row[0]) - ((i - row[0]) - 1))
+ 952					m -= 0.5
+ 953					offset := po * m
+ 954
+ 955					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+ 956					vState.X -= offset
+ 957				}
+ 958				(*state)[n.Children[i].Properties.Id] = vState
+ 959			}
+ 960
+ 961		}
+ 962
+ 963	}
+ 964}
+ 965
+ 966func alignRow(rows [][]int, n *element.Node, state *map[string]element.State, align, content string) {
+ 967	// !ISSUE: Baseline isn't properly impleamented
+ 968
+ 969	s := *state
+ 970	self := s[n.Properties.Id]
+ 971
+ 972	maxes := []float32{}
+ 973	var maxesTotal float32
+ 974	for _, row := range rows {
+ 975		var maxH float32
+ 976		for i := row[0]; i < row[1]; i++ {
+ 977			vState := s[n.Children[i].Properties.Id]
+ 978			_, h := getInnerSize(&n.Children[i], state)
+ 979			h = minHeight(n.Children[i], state, h)
+ 980			vState.Height = h
+ 981			h += vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+ 982			maxH = utils.Max(maxH, h)
+ 983			(*state)[n.Children[i].Properties.Id] = vState
+ 984		}
+ 985		maxes = append(maxes, maxH)
+ 986		maxesTotal += maxH
+ 987	}
+ 988
+ 989	os := ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
+ 990	if os < 0 || content != "normal" {
+ 991		os = 0
+ 992	}
+ 993
+ 994	var contentOffset float32
+ 995
+ 996	if content == "center" {
+ 997		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / 2
+ 998	} else if content == "end" || content == "flex-end" {
+ 999		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal)
+1000	} else if content == "start" || content == "flex-start" || content == "baseline" {
+1001		// This is redundent but it helps keep track
+1002		contentOffset = 0
+1003	} else if content == "space-between" {
+1004		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)-1)
+1005	} else if content == "space-around" {
+1006		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
+1007		contentOffset = os / 2
+1008	} else if content == "space-evenly" {
+1009		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)+1)
+1010		contentOffset = os
+1011	}
+1012
+1013	for c, row := range rows {
+1014		maxH := maxes[c]
+1015		var sum float32
+1016		for i := 0; i < c; i++ {
+1017			sum += maxes[i]
+1018		}
+1019		if align == "start" || align == "flex-start" || align == "self-start" || align == "normal" {
+1020			for i := row[0]; i < row[1]; i++ {
+1021				vState := s[n.Children[i].Properties.Id]
+1022
+1023				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
@@ -1124,11 +1124,11 @@
-1025	for c, row := range rows {
-1026		maxH := maxes[c]
-1027		var sum float32
-1028		for i := 0; i < c; i++ {
-1029			sum += maxes[i]
-1030		}
-1031		if align == "start" || align == "flex-start" || align == "self-start" || align == "normal" {
-1032			for i := row[0]; i < row[1]; i++ {
-1033				vState := s[n.Children[i].Properties.Id]
-1034
-1035				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
+1025				if n.Style["height"] != "" || n.Style["min-height"] != "" {
+1026					offset += ((os) * float32(c))
+1027				}
+1028
+1029				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
+1030				vState.Y = offset
+1031				(*state)[n.Children[i].Properties.Id] = vState
+1032			}
+1033		} else if align == "center" {
+1034			for i := row[0]; i < row[1]; i++ {
+1035				vState := s[n.Children[i].Properties.Id]
@@ -1136,34 +1136,34 @@
-1037				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-1038					offset += ((os) * float32(c))
-1039				}
-1040
-1041				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-1042				vState.Y = offset
-1043				(*state)[n.Children[i].Properties.Id] = vState
-1044			}
-1045		} else if align == "center" {
-1046			for i := row[0]; i < row[1]; i++ {
-1047				vState := s[n.Children[i].Properties.Id]
-1048
-1049				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
-1050
-1051				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-1052					offset += (os * float32(c+1)) - (os / 2)
-1053				}
-1054
-1055				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
-1056					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))) / 2
-1057				}
-1058				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-1059				vState.Y = offset
-1060				(*state)[n.Children[i].Properties.Id] = vState
-1061			}
-1062		} else if align == "end" || align == "flex-end" || align == "self-end" {
-1063			for i := row[0]; i < row[1]; i++ {
-1064				vState := s[n.Children[i].Properties.Id]
-1065
-1066				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
-1067
-1068				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-1069					offset += os * float32(c+1)
-1070				}
+1037				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
+1038
+1039				if n.Style["height"] != "" || n.Style["min-height"] != "" {
+1040					offset += (os * float32(c+1)) - (os / 2)
+1041				}
+1042
+1043				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
+1044					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))) / 2
+1045				}
+1046				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
+1047				vState.Y = offset
+1048				(*state)[n.Children[i].Properties.Id] = vState
+1049			}
+1050		} else if align == "end" || align == "flex-end" || align == "self-end" {
+1051			for i := row[0]; i < row[1]; i++ {
+1052				vState := s[n.Children[i].Properties.Id]
+1053
+1054				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
+1055
+1056				if n.Style["height"] != "" || n.Style["min-height"] != "" {
+1057					offset += os * float32(c+1)
+1058				}
+1059
+1060				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
+1061					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)))
+1062				}
+1063				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
+1064				vState.Y = offset
+1065				(*state)[n.Children[i].Properties.Id] = vState
+1066
+1067			}
+1068		} else if align == "stretch" {
+1069			for i := row[0]; i < row[1]; i++ {
+1070				vState := s[n.Children[i].Properties.Id]
@@ -1171,248 +1171,107 @@
-1072				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
-1073					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)))
-1074				}
-1075				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-1076				vState.Y = offset
-1077				(*state)[n.Children[i].Properties.Id] = vState
-1078
-1079			}
-1080		} else if align == "stretch" {
-1081			for i := row[0]; i < row[1]; i++ {
-1082				vState := s[n.Children[i].Properties.Id]
-1083
-1084				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top
-1085
-1086				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-1087					offset += ((os) * float32(c))
-1088				}
-1089
-1090				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-1091				vState.Y = offset
-1092				vState.Height = maxH - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
-1093				(*state)[n.Children[i].Properties.Id] = vState
-1094
-1095			}
-1096		}
-1097	}
-1098}
-1099
-1100func justifyCols(cols [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
-1101	s := *state
-1102	self := s[n.Properties.Id]
-1103
-1104	selfHeight := (self.Height) - (self.Padding.Top + self.Padding.Bottom)
-1105	for _, col := range cols {
-1106		yCollect := self.Y + self.Padding.Top
-1107		var colHeight float32
-1108		for i := col[0]; i <= col[1]; i++ {
-1109			v := n.Children[i]
-1110			vState := s[v.Properties.Id]
-1111			colHeight += vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
-1112		}
-1113
-1114		if justify == "center" {
-1115			offset := ((selfHeight - colHeight) / 2)
-1116			yCollect += offset
-1117			for i := col[0]; i <= col[1]; i++ {
-1118				v := n.Children[i]
-1119				vState := s[v.Properties.Id]
-1120				yStore := vState.Y
-1121				vState.Y = yCollect + vState.Margin.Top
-1122				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
-1123				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1124				(*state)[v.Properties.Id] = vState
-1125			}
-1126		}
-1127
-1128		if justify == "end" || justify == "flex-end" {
-1129			offset := (selfHeight - colHeight)
-1130			yCollect += offset
-1131			for i := col[0]; i <= col[1]; i++ {
-1132				v := n.Children[i]
-1133				vState := s[v.Properties.Id]
-1134				yStore := vState.Y
-1135				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
-1136				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
-1137				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1138				(*state)[v.Properties.Id] = vState
-1139			}
-1140		}
-1141
-1142		if justify == "space-evenly" {
-1143			offset := (selfHeight - colHeight) / (float32(col[1]-col[0]) + 2)
-1144			for i := col[0]; i <= col[1]; i++ {
-1145				v := n.Children[i]
-1146				vState := s[v.Properties.Id]
-1147				yStore := vState.Y
-1148				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top + offset
-1149				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width + offset
-1150				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1151				(*state)[v.Properties.Id] = vState
-1152			}
-1153		}
-1154
-1155		if justify == "space-between" {
-1156			offset := (selfHeight - colHeight) / (float32(col[1] - col[0]))
-1157			for i := col[0]; i <= col[1]; i++ {
-1158				v := n.Children[i]
-1159				vState := s[v.Properties.Id]
-1160				yStore := vState.Y
-1161				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
-1162				if col[1]-col[0] != 0 {
-1163					vState.Y += offset * float32(i-col[0])
-1164				} else if reversed {
-1165					vState.Y += selfHeight - (vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width)
-1166				}
-1167				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
-1168				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1169				(*state)[v.Properties.Id] = vState
-1170			}
-1171		}
-1172		if justify == "space-around" {
-1173			offset := (selfHeight - colHeight) / (float32(col[1]-col[0]) + 1)
-1174			for i := col[0]; i <= col[1]; i++ {
-1175				v := n.Children[i]
-1176				vState := s[v.Properties.Id]
-1177				yStore := vState.Y
-1178				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
-1179				if col[1]-col[0] == 0 {
-1180					vState.Y += offset / 2
-1181				} else {
-1182					vState.Y += (offset * float32(i-col[0])) + (offset / 2)
-1183				}
-1184				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
-1185				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1186				(*state)[v.Properties.Id] = vState
-1187			}
-1188		}
-1189	}
-1190}
-1191
-1192func alignCols(cols [][]int, n *element.Node, state *map[string]element.State, align, content string, minWidths [][]float32) {
-1193	s := *state
-1194	self := s[n.Properties.Id]
-1195
-1196	selfWidth := (self.Width - self.Padding.Left) - self.Padding.Right
-1197
-1198	var minX, maxX, minX2, maxX2 float32
-1199	minX += 10e9
-1200	minX2 += 10e9
-1201	for _, col := range cols {
-1202		for i := col[0]; i <= col[1]; i++ {
-1203			v := n.Children[i]
-1204			vState := s[v.Properties.Id]
-1205			if v.Style["width"] == "" && v.Style["min-width"] == "" && align != "stretch" {
-1206				vState.Width = minWidths[i][0]
-1207			}
-1208			minX = utils.Min(vState.X-vState.Border.Width-vState.Margin.Left, minX)
-1209			maxX = utils.Max(vState.X+vState.Width+vState.Border.Width+vState.Margin.Right, maxX)
-1210			(*state)[v.Properties.Id] = vState
-1211
-1212		}
-1213	}
-1214	rowWidth := maxX - minX
-1215
-1216	for c, col := range cols {
-1217
-1218		if content == "normal" {
-1219			var offset float32
-1220			if align == "center" {
-1221				offset = ((selfWidth - rowWidth) / 2)
-1222			}
-1223			if align == "end" || align == "flex-end" || align == "self-end" {
-1224				offset = (selfWidth - rowWidth)
-1225			}
-1226			for i := col[0]; i <= col[1]; i++ {
-1227				v := n.Children[i]
-1228				vState := s[v.Properties.Id]
-1229				xStore := vState.X
-1230				vState.X += offset
-1231				propagateOffsets(&n.Children[i], xStore, vState.Y, vState.X, vState.Y, state)
-1232				(*state)[v.Properties.Id] = vState
-1233			}
-1234			if align == "stretch" {
-1235				offset = selfWidth / float32(len(col)+1)
-1236				for i := col[0]; i <= col[1]; i++ {
-1237					v := n.Children[i]
-1238					vState := s[v.Properties.Id]
-1239					xStore := vState.X
-1240					// !ISSUE: Does not account for max/min width
-1241					if v.Style["width"] == "" {
-1242						vState.Width = offset - (vState.Margin.Left + (vState.Border.Width * 2) + vState.Margin.Right)
-1243					}
-1244					propagateOffsets(&n.Children[i], xStore, vState.Y, vState.X, vState.Y, state)
-1245					(*state)[v.Properties.Id] = vState
-1246				}
-1247			}
-1248		} else {
-1249			var width float32
-1250			for i := col[0]; i <= col[1]; i++ {
-1251				v := n.Children[i]
-1252				vState := s[v.Properties.Id]
-1253				width = utils.Max(vState.Width+vState.Margin.Left+vState.Margin.Right, width)
-1254			}
-1255			var offset float32
-1256			if c > 0 {
-1257				sib := s[n.Children[cols[c-1][0]].Properties.Id]
-1258				offset = sib.X + sib.Width + sib.Border.Width + sib.Margin.Right
-1259			}
-1260
-1261			for i := col[0]; i <= col[1]; i++ {
-1262				v := n.Children[i]
-1263				vState := s[v.Properties.Id]
-1264				xStore := vState.X
-1265				vState.Width = width - (vState.Margin.Left + vState.Margin.Right)
-1266				if c > 0 {
-1267					vState.X = offset + vState.Margin.Left + vState.Border.Width
-1268				}
-1269				propagateOffsets(&n.Children[i], xStore, vState.Y, vState.X, vState.Y, state)
-1270				minX2 = utils.Min(vState.X-vState.Border.Width-vState.Margin.Left, minX2)
-1271				maxX2 = utils.Max(vState.X+vState.Width+vState.Border.Width+vState.Margin.Right, maxX2)
-1272				(*state)[v.Properties.Id] = vState
-1273			}
-1274		}
-1275	}
-1276
-1277	if content != "normal" {
-1278		rowWidth2 := maxX2 - minX2
-1279		var offset float32
-1280		if content == "center" {
-1281			offset = ((selfWidth - rowWidth2) / 2)
-1282		}
-1283		if content == "end" || content == "flex-end" {
-1284			offset = (selfWidth - rowWidth2)
-1285		}
-1286		if content == "space-evenly" {
-1287			offset = (selfWidth - rowWidth2) / (float32(len(cols) + 1))
-1288		}
-1289		if content == "space-between" {
-1290			offset = (selfWidth - rowWidth2) / (float32(len(cols) - 1))
-1291		}
-1292		if content == "space-around" {
-1293			offset = (selfWidth - rowWidth2) / (float32(len(cols)))
-1294		}
-1295		for c, col := range cols {
-1296
-1297			for i := col[0]; i <= col[1]; i++ {
-1298				v := n.Children[i]
-1299				vState := s[v.Properties.Id]
-1300				xStore := vState.X
-1301				if content == "center" || content == "end" || content == "flex-end" {
-1302					vState.X += offset
-1303				} else if content == "space-evenly" {
-1304					vState.X += offset * float32(c+1)
-1305				} else if content == "space-between" {
-1306					vState.X += offset * float32(c)
-1307				} else if content == "space-around" {
-1308					if c == 0 {
-1309						vState.X += offset / 2
-1310					} else {
-1311						vState.X += (offset * float32(c)) + (offset / 2)
-1312					}
-1313				}
-1314				propagateOffsets(&n.Children[i], xStore, vState.Y, vState.X, vState.Y, state)
-1315				(*state)[v.Properties.Id] = vState
-1316			}
-1317		}
-1318	}
-1319}
+1072				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top
+1073
+1074				if n.Style["height"] != "" || n.Style["min-height"] != "" {
+1075					offset += ((os) * float32(c))
+1076				}
+1077
+1078				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
+1079				vState.Y = offset
+1080				vState.Height = maxH - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
+1081				(*state)[n.Children[i].Properties.Id] = vState
+1082
+1083			}
+1084		}
+1085	}
+1086}
+1087
+1088func justifyCols(cols [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
+1089	s := *state
+1090	self := s[n.Properties.Id]
+1091
+1092	selfHeight := (self.Height) - (self.Padding.Top + self.Padding.Bottom)
+1093	for _, col := range cols {
+1094		yCollect := self.Y + self.Padding.Top
+1095		var colHeight float32
+1096		for i := col[0]; i <= col[1]; i++ {
+1097			v := n.Children[i]
+1098			vState := s[v.Properties.Id]
+1099			colHeight += vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+1100		}
+1101
+1102		if justify == "center" {
+1103			offset := ((selfHeight - colHeight) / 2)
+1104			yCollect += offset
+1105			for i := col[0]; i <= col[1]; i++ {
+1106				v := n.Children[i]
+1107				vState := s[v.Properties.Id]
+1108				yStore := vState.Y
+1109				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
+1110				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
+1111				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
+1112				(*state)[v.Properties.Id] = vState
+1113			}
+1114		}
+1115
+1116		if justify == "end" || justify == "flex-end" {
+1117			offset := (selfHeight - colHeight)
+1118			yCollect += offset
+1119			for i := col[0]; i <= col[1]; i++ {
+1120				v := n.Children[i]
+1121				vState := s[v.Properties.Id]
+1122				yStore := vState.Y
+1123				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
+1124				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
+1125				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
+1126				(*state)[v.Properties.Id] = vState
+1127			}
+1128		}
+1129
+1130		if justify == "space-evenly" {
+1131			offset := (selfHeight - colHeight) / (float32(col[1]-col[0]) + 2)
+1132			for i := col[0]; i <= col[1]; i++ {
+1133				v := n.Children[i]
+1134				vState := s[v.Properties.Id]
+1135				yStore := vState.Y
+1136				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top + offset
+1137				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width + offset
+1138				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
+1139				(*state)[v.Properties.Id] = vState
+1140			}
+1141		}
+1142
+1143		if justify == "space-between" {
+1144			offset := (selfHeight - colHeight) / (float32(col[1] - col[0]))
+1145			for i := col[0]; i <= col[1]; i++ {
+1146				v := n.Children[i]
+1147				vState := s[v.Properties.Id]
+1148				yStore := vState.Y
+1149				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
+1150				if col[1]-col[0] != 0 {
+1151					vState.Y += offset * float32(i-col[0])
+1152				} else if reversed {
+1153					vState.Y += selfHeight - (vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width)
+1154				}
+1155				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
+1156				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
+1157				(*state)[v.Properties.Id] = vState
+1158			}
+1159		}
+1160		if justify == "space-around" {
+1161			offset := (selfHeight - colHeight) / (float32(col[1]-col[0]) + 1)
+1162			for i := col[0]; i <= col[1]; i++ {
+1163				v := n.Children[i]
+1164				vState := s[v.Properties.Id]
+1165				yStore := vState.Y
+1166				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
+1167				if col[1]-col[0] == 0 {
+1168					vState.Y += offset / 2
+1169				} else {
+1170					vState.Y += (offset * float32(i-col[0])) + (offset / 2)
+1171				}
+1172				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
+1173				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
+1174				(*state)[v.Properties.Id] = vState
+1175			}
+1176		}
+1177	}
+1178}


    
        
        
        
        
        GRIM UI 
        
        
        
        
    
    
        
        

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	"fmt"
   5	"gui/cstyle"
   6	"gui/cstyle/plugins/inline"
   7	"gui/element"
   8	"gui/utils"
   9	"sort"
  10	"strings"
  11)
  12
  13func Init() cstyle.Plugin {
  14	return cstyle.Plugin{
  15		Selector: func(n *element.Node) bool {
  16			styles := map[string]string{
  17				"display": "flex",
  18			}
  19			matches := true
  20			for name, value := range styles {
  21				if (n.Style[name] != value || n.Style[name] == "") && !(value == "*") {
  22					matches = false
  23				}
  24			}
  25			return matches
  26		},
  27		Level: 3,
  28		Handler: func(n *element.Node, state *map[string]element.State) {
  29			s := *state
  30			self := s[n.Properties.Id]
  31
  32			verbs := strings.Split(n.Style["flex-direction"], "-")
  33			flexDirection := verbs[0]
  34			if flexDirection == "" {
  35				flexDirection = "row"
  36			}
  37			flexReversed := false
  38			if len(verbs) > 1 {
  39				flexReversed = true
  40			}
  41
  42			var flexWrapped bool
  43			if n.Style["flex-wrap"] == "wrap" {
  44				flexWrapped = true
  45			} else {
  46				flexWrapped = false
  47			}
  48
  49			alignContent := n.Style["align-content"]
  50			if alignContent == "" {
  51				alignContent = "normal"
  52			}
  53			alignItems := n.Style["align-items"]
  54			if alignItems == "" {
  55				alignItems = "normal"
  56			}
  57			justifyItems := n.Style["justify-items"]
  58			if justifyItems == "" {
  59				justifyItems = "normal"
  60			}
  61
  62			justifyContent := n.Style["justify-content"]
  63			if justifyContent == "" {
  64				justifyContent = "normal"
  65			}
  66			// fmt.Println(flexDirection, flexReversed, flexWrapped, hAlign, vAlign, justifyItems, justifyContent)
  67			rows := [][]int{}
  68			maxH := float32(0)
  69			// maxW := float32(0)
  70
  71			// Get inital sizing
  72			textTotal := 0
  73			textCounts := []int{}
  74			widths := []float32{}
  75			// heights := []float32{}
  76			innerSizes := [][]float32{}
  77			minWidths := []float32{}
  78			minHeights := []float32{}
  79			maxWidths := []float32{}
  80			// maxHeights := []float32{}
  81			for _, v := range n.Children {
  82				count := countText(v)
  83				textTotal += count
  84				textCounts = append(textCounts, count)
  85
  86				minw := getMinWidth(&v, state)
  87				minWidths = append(minWidths, minw)
  88
  89				maxw := getMaxWidth(&v, state)
  90				maxWidths = append(maxWidths, maxw)
  91
  92				w, h := getInnerSize(&v, state)
  93
  94				minh := getMinHeight(&v, state)
  95				minHeights = append(minHeights, minh)
  96
  97				// maxh := getMaxHeight(&v, state)
  98				// maxHeights = append(maxHeights, maxh)
  99				innerSizes = append(innerSizes, []float32{w, h})
 100			}
 101			selfWidth := (self.Width - self.Padding.Left) - self.Padding.Right
 102			selfHeight := (self.Height - self.Padding.Top) - self.Padding.Bottom
 103
 104			if flexDirection == "row" {
 105				// if the elements are less than the size of the parent, don't change widths. Just set mins
 106				if !flexWrapped {
 107					if add2d(innerSizes, 0) < selfWidth {
 108						fmt.Println("here")
 109						for i := range innerSizes {
 110							// for i, _ := range n.Children {
 111							// vState := s[v.Properties.Id]
 112
 113							w := innerSizes[i][0]
 114							// w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 115							widths = append(widths, w)
 116						}
 117					} else {
 118						// Modifiy the widths so they aren't under the mins
 119						for i, v := range n.Children {
 120							vState := s[v.Properties.Id]
 121
 122							w := ((selfWidth / float32(textTotal)) * float32(textCounts[i]))
 123							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 124
 125							if w < minWidths[i] {
 126								selfWidth -= minWidths[i] + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 127								textTotal -= textCounts[i]
 128								textCounts[i] = 0
 129							}
 130
 131						}
 132						for i, v := range n.Children {
 133							vState := s[v.Properties.Id]
 134
 135							w := ((selfWidth / float32(textTotal)) * float32(textCounts[i]))
 136							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 137							// (w!=w) is of NaN
 138							if w < minWidths[i] || (w != w) {
 139								w = minWidths[i]
 140							}
 141							widths = append(widths, w)
 142						}
 143					}
 144					// Apply the new widths
 145					fState := s[n.Children[0].Properties.Id]
 146					for i, v := range n.Children {
 147						vState := s[v.Properties.Id]
 148
 149						vState.Width = widths[i]
 150						xStore := vState.X
 151						if i > 0 {
 152							sState := s[n.Children[i-1].Properties.Id]
 153							vState.X = sState.X + sState.Width + sState.Margin.Right + vState.Margin.Left + sState.Border.Width + vState.Border.Width
 154							propagateOffsets(&v, xStore, vState.Y, vState.X, fState.Y+vState.Margin.Top, state)
 155						}
 156
 157						vState.Y = fState.Y + vState.Margin.Top
 158
 159						(*state)[v.Properties.Id] = vState
 160						deInline(&v, state)
 161						applyInline(&v, state)
 162						applyBlock(&v, state)
 163						_, h := getInnerSize(&v, state)
 164						h = utils.Max(h, vState.Height)
 165						maxH = utils.Max(maxH, h)
 166					}
 167					// When not wrapping everything will be on the same row
 168					rows = append(rows, []int{0, len(n.Children), int(maxH)})
 169				} else {
 170					// Flex Wrapped
 171					sum := innerSizes[0][0]
 172					for i := 0; i < len(n.Children); i++ {
 173						v := n.Children[i]
 174						vState := s[v.Properties.Id]
 175
 176						// if the next plus current will break then
 177						w := innerSizes[i][0]
 178						if i > 0 {
 179							sib := s[n.Children[i-1].Properties.Id]
 180							if maxWidths[i] > selfWidth {
 181								w = selfWidth - vState.Margin.Left - vState.Margin.Right - (vState.Border.Width * 2)
 182							}
 183							if w+sum > selfWidth {
 184								sum = w + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 185							} else {
 186								propagateOffsets(&v, vState.X, vState.Y, vState.X, sib.Y, state)
 187								vState.Y = sib.Y
 188								(*state)[v.Properties.Id] = vState
 189								sum += w + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 190							}
 191						}
 192
 193						widths = append(widths, w)
 194					}
 195
 196					// Move the elements into the correct position
 197					start := 0
 198					var prevOffset float32
 199					for i := 0; i < len(n.Children); i++ {
 200						v := n.Children[i]
 201						vState := s[v.Properties.Id]
 202
 203						vState.Width = widths[i]
 204						xStore := vState.X
 205						yStore := vState.Y
 206
 207						if i > 0 {
 208							sib := s[n.Children[i-1].Properties.Id]
 209							if vState.Y+prevOffset == sib.Y {
 210								yStore += prevOffset
 211
 212								if vState.Height < sib.Height {
 213									vState.Height = minHeight(v, state, sib.Height)
 214								}
 215								// Shift right if on a row with sibling
 216								xStore = sib.X + sib.Width + sib.Margin.Right + sib.Border.Width + vState.Margin.Left + vState.Border.Width
 217							} else {
 218								// Shift under sibling
 219								yStore = sib.Y + sib.Height + sib.Margin.Top + sib.Margin.Bottom + sib.Border.Width*2
 220								prevOffset = yStore - vState.Y
 221								rows = append(rows, []int{start, i, int(maxH)})
 222								start = i
 223								maxH = 0
 224							}
 225							propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
 226						}
 227						vState.X = xStore
 228						vState.Y = yStore
 229
 230						(*state)[v.Properties.Id] = vState
 231						deInline(&v, state)
 232						applyInline(&v, state)
 233						applyBlock(&v, state)
 234						_, h := getInnerSize(&v, state)
 235						h = utils.Max(h, vState.Height)
 236						maxH = utils.Max(maxH, h)
 237						vState.Height = minHeight(v, state, h)
 238						(*state)[v.Properties.Id] = vState
 239					}
 240					if start < len(n.Children) {
 241						rows = append(rows, []int{start, len(n.Children), int(maxH)})
 242					}
 243				}
 244
 245				for _, v := range rows {
 246					for i := v[0]; i < v[1]; i++ {
 247						vState := s[n.Children[i].Properties.Id]
 248						// height := float32(v[2])
 249						if (n.Style["height"] != "" && n.Style["min-height"] != "") && !flexWrapped {
 250							height := self.Height - self.Padding.Top - self.Padding.Bottom - vState.Margin.Top - vState.Margin.Bottom - (vState.Border.Width * 2)
 251							vState.Height = minHeight(n.Children[i], state, height)
 252						}
 253						(*state)[n.Children[i].Properties.Id] = vState
 254					}
 255				}
 256				// Reverse elements
 257				if flexReversed {
 258					rowReverse(rows, n, state)
 259				}
 260
 261				if justifyContent != "" && justifyContent != "normal" {
 262					justifyRow(rows, n, state, justifyContent, flexReversed)
 263				}
 264
 265				if alignContent != "normal" && flexWrapped {
 266					alignRow(rows, n, state, alignItems, alignContent)
 267				}
 268
 269			}
 270
 271			if flexDirection == "column" {
 272				if !flexWrapped {
 273					// if the container has a size restriction
 274					var totalHeight, maxH float32
 275					var fixedHeightElements int
 276					for i, v := range n.Children {
 277						vState := s[v.Properties.Id]
 278						if v.Style["min-height"] != "" {
 279							selfHeight -= vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
 280							fixedHeightElements++
 281							maxH = utils.Max(maxH, vState.Height)
 282						} else {
 283							// accoutn for element min height
 284							totalHeight += minHeights[i] + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
 285							maxH = utils.Max(maxH, minHeights[i])
 286						}
 287					}
 288
 289					heightDelta := selfHeight - totalHeight
 290					if heightDelta < 0 {
 291						heightDelta = -heightDelta
 292					}
 293					heightAdj := heightDelta / float32(len(n.Children)-fixedHeightElements)
 294					if heightAdj < 0 {
 295						heightAdj = -heightAdj
 296					}
 297					// We are calculating the amount a element needs to shrink because of its siblings
 298					for i, v := range n.Children {
 299						vState := s[v.Properties.Id]
 300						yStore := vState.Y
 301						if v.Style["min-height"] == "" {
 302							vState.Height = minHeights[i] - heightAdj
 303							if vState.Height < minHeights[i] {
 304								vState.Height = minHeights[i]
 305							}
 306
 307						}
 308						if i > 0 {
 309							sib := s[n.Children[i-1].Properties.Id]
 310
 311							vState.Y = sib.Y + sib.Height + sib.Margin.Bottom + sib.Border.Width + vState.Margin.Top + vState.Border.Width
 312						}
 313						propagateOffsets(&v, vState.X, yStore, vState.X, vState.Y, state)
 314
 315						(*state)[v.Properties.Id] = vState
 316					}
 317
 318					rows = append(rows, []int{0, len(n.Children) - 1, int(maxH)})
 319
 320				} else {
 321					var colHeight float32
 322					var colIndex int
 323					cols := [][][]float32{}
 324
 325					// Map elements to columns
 326					for i, v := range n.Children {
 327						vState := s[v.Properties.Id]
 328
 329						height := vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
 330						if colHeight+height > selfHeight {
 331							colHeight = height
 332							colIndex++
 333							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 334							if colIndex >= len(cols) {
 335								cols = append(cols, [][]float32{})
 336							}
 337							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
 338						} else {
 339							colHeight += height
 340							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 341							if colIndex >= len(cols) {
 342								cols = append(cols, [][]float32{})
 343							}
 344							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
 345						}
 346					}
 347
 348					// Find the max total width of all columns
 349					var totalMaxWidth float32
 350					maxWidths := []float32{}
 351					for _, col := range cols {
 352						var maxWidth, maxHeight float32
 353						for _, element := range col {
 354							maxHeight = utils.Max(element[1], maxHeight)
 355							maxWidth = utils.Max(element[2], maxWidth)
 356						}
 357						rows = append(rows, []int{int(col[0][0]), int(col[len(col)-1][0]), int(maxHeight)})
 358						totalMaxWidth += maxWidth
 359						maxWidths = append(maxWidths, maxWidth)
 360					}
 361					offset := (selfWidth - totalMaxWidth) / float32(len(cols))
 362					// Move the elements into the correct position
 363					var xOffset float32
 364					for i, col := range cols {
 365						// Move the elements into the correct position
 366						yOffset := self.Y + self.Border.Width + self.Padding.Top
 367						for _, element := range col {
 368							vState := s[n.Children[int(element[0])].Properties.Id]
 369							xStore := vState.X
 370							yStore := vState.Y
 371							vState.X = self.X + self.Padding.Left + self.Border.Width + xOffset + vState.Margin.Left
 372							vState.Y = yOffset + vState.Margin.Top + vState.Border.Width
 373							propagateOffsets(&n.Children[int(element[0])], xStore, yStore, vState.X, vState.Y, state)
 374							// vState.Width = element[2] - (vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2))
 375							fmt.Println(vState.Width, element[2])
 376							// vState.Width = 120
 377
 378							yOffset += vState.Margin.Top + vState.Border.Width + vState.Height + vState.Margin.Bottom + vState.Border.Width
 379							(*state)[n.Children[int(element[0])].Properties.Id] = vState
 380						}
 381						xOffset += maxWidths[i] + offset
 382					}
 383
 384				}
 385
 386				if flexReversed {
 387					colReverse(rows, n, state)
 388				}
 389
 390				if justifyContent != "normal" {
 391					justifyCols(rows, n, state, justifyContent, flexReversed)
 392				}
 393				if alignContent != "normal" || alignItems != "normal" {
 394					alignCols(rows, n, state, alignItems, alignContent, innerSizes)
 395				}
 396			}
 397			if n.Style["height"] == "" && n.Style["min-height"] == "" {
 398				_, h := getInnerSize(n, state)
 399				self.Height = h
 400			}
 401			(*state)[n.Properties.Id] = self
 402		},
 403	}
 404}
 405
 406func applyBlock(n *element.Node, state *map[string]element.State) {
 407	if len(n.Children) > 0 {
 408		accum := float32(0)
 409		inlineOffset := float32(0)
 410		s := *state
 411		lastHeight := float32(0)
 412		baseY := s[n.Children[0].Properties.Id].Y
 413		for i := 0; i < len(n.Children); i++ {
 414			v := &n.Children[i]
 415			vState := s[v.Properties.Id]
 416
 417			if v.Style["display"] != "block" {
 418				vState.Y += inlineOffset
 419				accum = (vState.Y - baseY)
 420				lastHeight = vState.Height
 421			} else if v.Style["position"] != "absolute" {
 422				vState.Y += accum
 423				inlineOffset += (vState.Height + (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom) + lastHeight
 424			}
 425			(*state)[v.Properties.Id] = vState
 426		}
 427	}
 428}
 429
 430func deInline(n *element.Node, state *map[string]element.State) {
 431	s := *state
 432	// self := s[n.Properties.Id]
 433	baseX := float32(-1)
 434	baseY := float32(-1)
 435	for _, v := range n.Children {
 436		vState := s[v.Properties.Id]
 437
 438		if v.Style["display"] == "inline" {
 439			if baseX < 0 && baseY < 0 {
 440				baseX = vState.X
 441				baseY = vState.Y
 442			} else {
 443				vState.X = baseX
 444				vState.Y = baseY
 445				(*state)[v.Properties.Id] = vState
 446
 447			}
 448		} else {
 449			baseX = float32(-1)
 450			baseY = float32(-1)
 451		}
 452
 453		if len(v.Children) > 0 {
 454			deInline(&v, state)
 455		}
 456	}
 457
 458}
 459
 460func applyInline(n *element.Node, state *map[string]element.State) {
 461	pl := inline.Init()
 462	for i := 0; i < len(n.Children); i++ {
 463		v := &n.Children[i]
 464
 465		if len(v.Children) > 0 {
 466			applyInline(v, state)
 467		}
 468
 469		if pl.Selector(v) {
 470			pl.Handler(v, state)
 471		}
 472	}
 473}
 474
 475func propagateOffsets(n *element.Node, prevx, prevy, newx, newy float32, state *map[string]element.State) {
 476	s := *state
 477	for _, v := range n.Children {
 478		vState := s[v.Properties.Id]
 479		xStore := (vState.X - prevx) + newx
 480		yStore := (vState.Y - prevy) + newy
 481
 482		if len(v.Children) > 0 {
 483			propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
 484		}
 485		vState.X = xStore
 486		vState.Y = yStore
 487		(*state)[v.Properties.Id] = vState
 488	}
 489
 490}
 491
 492func countText(n element.Node) int {
 493	count := 0
 494	groups := []int{}
 495	for _, v := range n.Children {
 496		if v.TagName == "notaspan" {
 497			count += 1
 498		}
 499		if v.Style["display"] == "block" {
 500			groups = append(groups, count)
 501			count = 0
 502		}
 503		if len(v.Children) > 0 {
 504			count += countText(v)
 505		}
 506	}
 507	groups = append(groups, count)
 508
 509	sort.Slice(groups, func(i, j int) bool {
 510		return groups[i] > groups[j]
 511	})
 512	return groups[0]
 513}
 514
 515func minHeight(n element.Node, state *map[string]element.State, prev float32) float32 {
 516	s := *state
 517	self := s[n.Properties.Id]
 518	if n.Style["min-height"] != "" {
 519		mw := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
 520		return utils.Max(prev, mw)
 521	} else {
 522		return prev
 523	}
 524
 525}
 526
 527func getMinHeight(n *element.Node, state *map[string]element.State) float32 {
 528	s := *state
 529	self := s[n.Properties.Id]
 530	selfHeight := float32(0)
 531
 532	if len(n.Children) > 0 {
 533		for _, v := range n.Children {
 534			selfHeight = utils.Max(selfHeight, getNodeHeight(&v, state))
 535		}
 536	} else {
 537		selfHeight = self.Height
 538	}
 539	if n.Style["min-height"] != "" {
 540		mh := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
 541		selfHeight = utils.Max(mh, selfHeight)
 542	}
 543
 544	selfHeight += self.Padding.Top + self.Padding.Bottom
 545	return selfHeight
 546}
 547
 548func getMinWidth(n *element.Node, state *map[string]element.State) float32 {
 549	s := *state
 550	self := s[n.Properties.Id]
 551	selfWidth := float32(0)
 552
 553	if len(n.Children) > 0 {
 554		for _, v := range n.Children {
 555			selfWidth = utils.Max(selfWidth, getNodeWidth(&v, state))
 556		}
 557	} else {
 558		selfWidth = self.Width
 559	}
 560	if n.Style["min-width"] != "" {
 561		mw := utils.ConvertToPixels(n.Style["min-width"], self.EM, s[n.Parent.Properties.Id].Width)
 562		selfWidth = utils.Max(mw, selfWidth)
 563	}
 564
 565	selfWidth += self.Padding.Left + self.Padding.Right
 566	return selfWidth
 567}
 568func getMaxWidth(n *element.Node, state *map[string]element.State) float32 {
 569	s := *state
 570	self := s[n.Properties.Id]
 571	selfWidth := float32(0)
 572
 573	if len(n.Children) > 0 {
 574		var maxRowWidth, rowWidth float32
 575
 576		for _, v := range n.Children {
 577			rowWidth += getNodeWidth(&v, state)
 578			if v.Style["display"] != "inline" {
 579				maxRowWidth = utils.Max(rowWidth, maxRowWidth)
 580				rowWidth = 0
 581			}
 582		}
 583		selfWidth = utils.Max(rowWidth, maxRowWidth)
 584	} else {
 585		selfWidth = self.Width
 586	}
 587
 588	selfWidth += self.Padding.Left + self.Padding.Right
 589	return selfWidth
 590}
 591
 592func getNodeWidth(n *element.Node, state *map[string]element.State) float32 {
 593	s := *state
 594	self := s[n.Properties.Id]
 595	w := float32(0)
 596	w += self.Padding.Left
 597	w += self.Padding.Right
 598
 599	w += self.Margin.Left
 600	w += self.Margin.Right
 601
 602	w += self.Width
 603
 604	w += self.Border.Width * 2
 605
 606	for _, v := range n.Children {
 607		w = utils.Max(w, getNodeWidth(&v, state))
 608	}
 609
 610	return w
 611}
 612
 613// func getMaxHeight(n *element.Node, state *map[string]element.State) float32 {
 614// 	s := *state
 615// 	self := s[n.Properties.Id]
 616// 	selfHeight := float32(0)
 617
 618// 	if len(n.Children) > 0 {
 619// 		var maxRowHeight, rowHeight float32
 620
 621// 		for _, v := range n.Children {
 622// 			rowHeight += getNodeHeight(&v, state)
 623// 			if v.Style["display"] != "inline" {
 624// 				maxRowHeight = utils.Max(rowHeight, maxRowHeight)
 625// 				rowHeight = 0
 626// 			}
 627// 		}
 628// 		selfHeight = utils.Max(rowHeight, maxRowHeight)
 629// 	} else {
 630// 		selfHeight = self.Height
 631// 	}
 632
 633// 	selfHeight += self.Padding.Top + self.Padding.Bottom
 634// 	return selfHeight
 635// }
 636
 637func getNodeHeight(n *element.Node, state *map[string]element.State) float32 {
 638	s := *state
 639	self := s[n.Properties.Id]
 640	h := float32(0)
 641	h += self.Padding.Top
 642	h += self.Padding.Bottom
 643
 644	h += self.Margin.Top
 645	h += self.Margin.Bottom
 646
 647	h += self.Height
 648
 649	h += self.Border.Width * 2
 650
 651	for _, v := range n.Children {
 652		h = utils.Max(h, getNodeHeight(&v, state))
 653	}
 654
 655	return h
 656}
 657
 658func getInnerSize(n *element.Node, state *map[string]element.State) (float32, float32) {
 659	s := *state
 660	self := s[n.Properties.Id]
 661
 662	minx := float32(10e10)
 663	maxw := float32(0)
 664	miny := float32(10e10)
 665	maxh := float32(0)
 666	for _, v := range n.Children {
 667		vState := s[v.Properties.Id]
 668		minx = utils.Min(vState.X, minx)
 669		miny = utils.Min(vState.Y-vState.Margin.Top, miny)
 670		// Don't add the top or left because the x&y values already take that into account
 671		hOffset := (vState.Border.Width * 2) + vState.Margin.Bottom
 672		wOffset := (vState.Border.Width * 2) + vState.Margin.Right
 673		maxw = utils.Max(vState.X+vState.Width+wOffset, maxw)
 674		maxh = utils.Max(vState.Y+vState.Height+hOffset, maxh)
 675	}
 676	w := maxw - minx
 677	h := maxh - miny
 678
 679	w += self.Padding.Left + self.Padding.Right
 680	h += self.Padding.Top + self.Padding.Bottom
 681	if n.Style["width"] != "" {
 682		w = self.Width
 683	}
 684	if n.Style["height"] != "" {
 685		h = self.Height
 686	}
 687
 688	return w, h
 689}
 690
 691func add2d(arr [][]float32, index int) float32 {
 692	var sum float32
 693	if len(arr) == 0 {
 694		return sum
 695	}
 696
 697	for i := 0; i < len(arr); i++ {
 698		if len(arr[i]) <= index {
 699			return sum
 700		}
 701		sum += arr[i][index]
 702	}
 703
 704	return sum
 705}
 706
 707func colReverse(cols [][]int, n *element.Node, state *map[string]element.State) {
 708	s := *state
 709	for _, col := range cols {
 710		tempNodes := []element.Node{}
 711		tempStates := []element.State{}
 712
 713		for i := col[1]; i >= col[0]; i-- {
 714			tempNodes = append(tempNodes, n.Children[i])
 715			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
 716		}
 717
 718		for i := 0; i < len(tempStates); i++ {
 719			e := col[0] + i
 720			vState := s[n.Children[e].Properties.Id]
 721			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
 722			vState.Y = tempStates[i].Y
 723			(*state)[n.Children[e].Properties.Id] = vState
 724		}
 725		for i := 0; i < len(tempStates); i++ {
 726			e := col[0] + i
 727			n.Children[e] = tempNodes[i]
 728		}
 729
 730		for i := col[1]; i >= col[0]; i-- {
 731			vState := s[n.Children[i].Properties.Id]
 732			var yChng float32
 733			if i < col[1] {
 734				sib := s[n.Children[i+1].Properties.Id]
 735				yChng = sib.Y - (sib.Border.Width + sib.Margin.Top + vState.Margin.Bottom + vState.Border.Width + vState.Height)
 736			} else {
 737				parent := s[n.Properties.Id]
 738				yChng = ((((parent.Y + parent.Height) - parent.Padding.Bottom) - vState.Height) - vState.Margin.Bottom) - (vState.Border.Width)
 739			}
 740			propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, yChng, state)
 741			vState.Y = yChng
 742			(*state)[n.Children[i].Properties.Id] = vState
 743		}
 744	}
 745}
 746
 747func rowReverse(rows [][]int, n *element.Node, state *map[string]element.State) {
 748	s := *state
 749	for _, row := range rows {
 750		tempNodes := []element.Node{}
 751		tempStates := []element.State{}
 752
 753		for i := row[1] - 1; i >= row[0]; i-- {
 754			tempNodes = append(tempNodes, n.Children[i])
 755			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
 756		}
 757
 758		for i := 0; i < len(tempStates); i++ {
 759			e := row[0] + i
 760			vState := s[n.Children[e].Properties.Id]
 761			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
 762			vState.X = tempStates[i].X
 763			(*state)[n.Children[e].Properties.Id] = vState
 764		}
 765		for i := 0; i < len(tempStates); i++ {
 766			e := row[0] + i
 767			n.Children[e] = tempNodes[i]
 768		}
 769
 770		for i := row[1] - 1; i >= row[0]; i-- {
 771			vState := s[n.Children[i].Properties.Id]
 772			var xChng float32
 773			if i < row[1]-1 {
 774				sib := s[n.Children[i+1].Properties.Id]
 775				xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
 776			} else {
 777				parent := s[n.Properties.Id]
 778				xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
 779
 780			}
 781			propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
 782			vState.X = xChng
 783			(*state)[n.Children[i].Properties.Id] = vState
 784		}
 785	}
 786}
 787
 788func justifyRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
 789	s := *state
 790	for _, row := range rows {
 791
 792		if (justify == "flex-end" || justify == "end" || justify == "right") && !reversed {
 793			for i := row[1] - 1; i >= row[0]; i-- {
 794				vState := s[n.Children[i].Properties.Id]
 795				var xChng float32
 796				if i < row[1]-1 {
 797					sib := s[n.Children[i+1].Properties.Id]
 798					xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
 799				} else {
 800					parent := s[n.Properties.Id]
 801					xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
 802
 803				}
 804				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
 805				vState.X = xChng
 806				(*state)[n.Children[i].Properties.Id] = vState
 807			}
 808		} else if (justify == "flex-end" || justify == "start" || justify == "left" || justify == "normal") && reversed {
 809			for i := row[0]; i < row[1]; i++ {
 810				vState := s[n.Children[i].Properties.Id]
 811				var xChng float32
 812				if i > row[0] {
 813					sib := s[n.Children[i-1].Properties.Id]
 814					xChng = sib.X + sib.Width + (sib.Border.Width * 2) + sib.Margin.Right + vState.Margin.Left + vState.Border.Width
 815				} else {
 816					parent := s[n.Properties.Id]
 817					xChng = parent.X + parent.Padding.Right + vState.Margin.Left + vState.Border.Width + parent.Border.Width
 818
 819				}
 820				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
 821				vState.X = xChng
 822				(*state)[n.Children[i].Properties.Id] = vState
 823			}
 824		} else if justify == "center" {
 825			// get width of row then center (by getting last x + w + mr + b)
 826			f := s[n.Children[row[0]].Properties.Id]
 827			l := s[n.Children[row[1]-1].Properties.Id]
 828			parent := s[n.Properties.Id]
 829			po := parent.X + parent.Border.Width
 830			offset := (parent.Width - ((f.X - po) + (l.X - po) + l.Width + f.Border.Width + l.Border.Width)) / 2
 831
 832			for i := row[0]; i < row[1]; i++ {
 833				vState := s[n.Children[i].Properties.Id]
 834
 835				if !reversed {
 836					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
 837					vState.X += offset
 838				} else {
 839					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
 840					vState.X -= offset
 841				}
 842				(*state)[n.Children[i].Properties.Id] = vState
 843			}
 844
 845		} else if justify == "space-between" {
 846			// get width of row then center (by getting last x + w + mr + b)
 847			f := s[n.Children[row[0]].Properties.Id]
 848			l := s[n.Children[row[1]-1].Properties.Id]
 849			parent := s[n.Properties.Id]
 850			po := parent.Border.Width + parent.Width
 851			po -= parent.Padding.Left + parent.Padding.Right
 852
 853			// make po repersent the total space between elements
 854			for i := row[0]; i < row[1]; i++ {
 855				vState := s[n.Children[i].Properties.Id]
 856				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 857			}
 858
 859			po /= float32(((row[1]) - row[0]) - 1)
 860
 861			if (row[1]-1)-row[0] > 0 {
 862				for i := row[0]; i < row[1]; i++ {
 863					vState := s[n.Children[i].Properties.Id]
 864					var offset float32
 865					if i == row[0] {
 866						offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
 867					} else if i == row[1]-1 {
 868						offset = (parent.X + parent.Width) - (l.Margin.Right + l.Border.Width + l.Width + parent.Padding.Right)
 869					} else {
 870						if !reversed {
 871							offset = vState.X + (po * float32(i-row[0]))
 872						} else {
 873							offset = vState.X - (po * float32(((row[1]-1)-row[0])-(i-row[0])))
 874						}
 875
 876					}
 877
 878					propagateOffsets(&n.Children[i], vState.X, vState.Y, offset, vState.Y, state)
 879					vState.X = offset
 880					(*state)[n.Children[i].Properties.Id] = vState
 881				}
 882			}
 883			//  else {
 884
 885			// this is/was causing issues, removed and it fixed its self
 886
 887			// if there is one element move left
 888			// vState := s[n.Children[(row[1]-1)-row[0]].Properties.Id]
 889			// var offset float32
 890
 891			// if !reversed {
 892			// 	offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
 893			// 	propagateOffsets(&n.Children[(row[1]-1)-row[0]], vState.X, vState.Y, offset, vState.Y, state)
 894			// 	vState.X = offset
 895
 896			// 	(*state)[n.Children[(row[1]-1)-row[0]].Properties.Id] = vState
 897			// }
 898
 899			// }
 900
 901		} else if justify == "space-evenly" {
 902			// get width of row then center (by getting last x + w + mr + b)
 903			parent := s[n.Properties.Id]
 904			po := parent.Border.Width + parent.Width
 905			po -= parent.Padding.Left + parent.Padding.Right
 906
 907			// make po repersent the total space between elements
 908			for i := row[0]; i < row[1]; i++ {
 909				vState := s[n.Children[i].Properties.Id]
 910				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 911			}
 912
 913			po /= float32(((row[1]) - row[0]) + 1)
 914
 915			// get width of row then center (by getting last x + w + mr + b)
 916
 917			for i := row[0]; i < row[1]; i++ {
 918				vState := s[n.Children[i].Properties.Id]
 919
 920				if !reversed {
 921					offset := po * (float32(i-row[0]) + 1)
 922					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
 923					vState.X += offset
 924				} else {
 925					offset := po * float32(((row[1]-1)-row[0])-((i-row[0])-1))
 926
 927					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
 928					vState.X -= offset
 929				}
 930				(*state)[n.Children[i].Properties.Id] = vState
 931			}
 932
 933		} else if justify == "space-around" {
 934			// get width of row then center (by getting last x + w + mr + b)
 935			parent := s[n.Properties.Id]
 936			po := parent.Border.Width + parent.Width
 937			po -= parent.Padding.Left + parent.Padding.Right
 938
 939			// make po repersent the total space between elements
 940			for i := row[0]; i < row[1]; i++ {
 941				vState := s[n.Children[i].Properties.Id]
 942				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
 943			}
 944
 945			po /= float32(((row[1]) - row[0]))
 946
 947			// get width of row then center (by getting last x + w + mr + b)
 948
 949			for i := row[0]; i < row[1]; i++ {
 950				vState := s[n.Children[i].Properties.Id]
 951
 952				if !reversed {
 953					m := (float32(i-row[0]) + 1)
 954					if i-row[0] == 0 {
 955						m = 0.5
 956					} else {
 957						m -= 0.5
 958					}
 959					offset := po * m
 960					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
 961					vState.X += offset
 962				} else {
 963					m := float32(((row[1] - 1) - row[0]) - ((i - row[0]) - 1))
 964					m -= 0.5
 965					offset := po * m
 966
 967					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
 968					vState.X -= offset
 969				}
 970				(*state)[n.Children[i].Properties.Id] = vState
 971			}
 972
 973		}
 974
 975	}
 976}
 977
 978func alignRow(rows [][]int, n *element.Node, state *map[string]element.State, align, content string) {
 979	// !ISSUE: Baseline isn't properly impleamented
 980
 981	s := *state
 982	self := s[n.Properties.Id]
 983
 984	maxes := []float32{}
 985	var maxesTotal float32
 986	for _, row := range rows {
 987		var maxH float32
 988		for i := row[0]; i < row[1]; i++ {
 989			vState := s[n.Children[i].Properties.Id]
 990			_, h := getInnerSize(&n.Children[i], state)
 991			h = minHeight(n.Children[i], state, h)
 992			vState.Height = h
 993			h += vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
 994			maxH = utils.Max(maxH, h)
 995			(*state)[n.Children[i].Properties.Id] = vState
 996		}
 997		maxes = append(maxes, maxH)
 998		maxesTotal += maxH
 999	}
1000
1001	os := ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
1002	if os < 0 || content != "normal" {
1003		os = 0
1004	}
1005
1006	var contentOffset float32
1007
1008	if content == "center" {
1009		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / 2
1010	} else if content == "end" || content == "flex-end" {
1011		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal)
1012	} else if content == "start" || content == "flex-start" || content == "baseline" {
1013		// This is redundent but it helps keep track
1014		contentOffset = 0
1015	} else if content == "space-between" {
1016		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)-1)
1017	} else if content == "space-around" {
1018		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
1019		contentOffset = os / 2
1020	} else if content == "space-evenly" {
1021		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)+1)
1022		contentOffset = os
1023	}
1024
1025	for c, row := range rows {
1026		maxH := maxes[c]
1027		var sum float32
1028		for i := 0; i < c; i++ {
1029			sum += maxes[i]
1030		}
1031		if align == "start" || align == "flex-start" || align == "self-start" || align == "normal" {
1032			for i := row[0]; i < row[1]; i++ {
1033				vState := s[n.Children[i].Properties.Id]
1034
1035				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
1036
1037				if n.Style["height"] != "" || n.Style["min-height"] != "" {
1038					offset += ((os) * float32(c))
1039				}
1040
1041				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
1042				vState.Y = offset
1043				(*state)[n.Children[i].Properties.Id] = vState
1044			}
1045		} else if align == "center" {
1046			for i := row[0]; i < row[1]; i++ {
1047				vState := s[n.Children[i].Properties.Id]
1048
1049				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
1050
1051				if n.Style["height"] != "" || n.Style["min-height"] != "" {
1052					offset += (os * float32(c+1)) - (os / 2)
1053				}
1054
1055				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
1056					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))) / 2
1057				}
1058				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
1059				vState.Y = offset
1060				(*state)[n.Children[i].Properties.Id] = vState
1061			}
1062		} else if align == "end" || align == "flex-end" || align == "self-end" {
1063			for i := row[0]; i < row[1]; i++ {
1064				vState := s[n.Children[i].Properties.Id]
1065
1066				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
1067
1068				if n.Style["height"] != "" || n.Style["min-height"] != "" {
1069					offset += os * float32(c+1)
1070				}
1071
1072				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
1073					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)))
1074				}
1075				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
1076				vState.Y = offset
1077				(*state)[n.Children[i].Properties.Id] = vState
1078
1079			}
1080		} else if align == "stretch" {
1081			for i := row[0]; i < row[1]; i++ {
1082				vState := s[n.Children[i].Properties.Id]
1083
1084				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top
1085
1086				if n.Style["height"] != "" || n.Style["min-height"] != "" {
1087					offset += ((os) * float32(c))
1088				}
1089
1090				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
1091				vState.Y = offset
1092				vState.Height = maxH - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
1093				(*state)[n.Children[i].Properties.Id] = vState
1094
1095			}
1096		}
1097	}
1098}
1099
1100func justifyCols(cols [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
1101	s := *state
1102	self := s[n.Properties.Id]
1103
1104	selfHeight := (self.Height) - (self.Padding.Top + self.Padding.Bottom)
1105	for _, col := range cols {
1106		yCollect := self.Y + self.Padding.Top
1107		var colHeight float32
1108		for i := col[0]; i <= col[1]; i++ {
1109			v := n.Children[i]
1110			vState := s[v.Properties.Id]
1111			colHeight += vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
1112		}
1113
1114		if justify == "center" {
1115			offset := ((selfHeight - colHeight) / 2)
1116			yCollect += offset
1117			for i := col[0]; i <= col[1]; i++ {
1118				v := n.Children[i]
1119				vState := s[v.Properties.Id]
1120				yStore := vState.Y
1121				vState.Y = yCollect + vState.Margin.Top
1122				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
1123				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
1124				(*state)[v.Properties.Id] = vState
1125			}
1126		}
1127
1128		if justify == "end" || justify == "flex-end" {
1129			offset := (selfHeight - colHeight)
1130			yCollect += offset
1131			for i := col[0]; i <= col[1]; i++ {
1132				v := n.Children[i]
1133				vState := s[v.Properties.Id]
1134				yStore := vState.Y
1135				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
1136				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
1137				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
1138				(*state)[v.Properties.Id] = vState
1139			}
1140		}
1141
1142		if justify == "space-evenly" {
1143			offset := (selfHeight - colHeight) / (float32(col[1]-col[0]) + 2)
1144			for i := col[0]; i <= col[1]; i++ {
1145				v := n.Children[i]
1146				vState := s[v.Properties.Id]
1147				yStore := vState.Y
1148				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top + offset
1149				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width + offset
1150				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
1151				(*state)[v.Properties.Id] = vState
1152			}
1153		}
1154
1155		if justify == "space-between" {
1156			offset := (selfHeight - colHeight) / (float32(col[1] - col[0]))
1157			for i := col[0]; i <= col[1]; i++ {
1158				v := n.Children[i]
1159				vState := s[v.Properties.Id]
1160				yStore := vState.Y
1161				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
1162				if col[1]-col[0] != 0 {
1163					vState.Y += offset * float32(i-col[0])
1164				} else if reversed {
1165					vState.Y += selfHeight - (vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width)
1166				}
1167				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
1168				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
1169				(*state)[v.Properties.Id] = vState
1170			}
1171		}
1172		if justify == "space-around" {
1173			offset := (selfHeight - colHeight) / (float32(col[1]-col[0]) + 1)
1174			for i := col[0]; i <= col[1]; i++ {
1175				v := n.Children[i]
1176				vState := s[v.Properties.Id]
1177				yStore := vState.Y
1178				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
1179				if col[1]-col[0] == 0 {
1180					vState.Y += offset / 2
1181				} else {
1182					vState.Y += (offset * float32(i-col[0])) + (offset / 2)
1183				}
1184				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
1185				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
1186				(*state)[v.Properties.Id] = vState
1187			}
1188		}
1189	}
1190}
1191
1192func alignCols(cols [][]int, n *element.Node, state *map[string]element.State, align, content string, minWidths [][]float32) {
1193	s := *state
1194	self := s[n.Properties.Id]
1195
1196	selfWidth := (self.Width - self.Padding.Left) - self.Padding.Right
1197
1198	var minX, maxX, minX2, maxX2 float32
1199	minX += 10e9
1200	minX2 += 10e9
1201	for _, col := range cols {
1202		for i := col[0]; i <= col[1]; i++ {
1203			v := n.Children[i]
1204			vState := s[v.Properties.Id]
1205			if v.Style["width"] == "" && v.Style["min-width"] == "" && align != "stretch" {
1206				vState.Width = minWidths[i][0]
1207			}
1208			minX = utils.Min(vState.X-vState.Border.Width-vState.Margin.Left, minX)
1209			maxX = utils.Max(vState.X+vState.Width+vState.Border.Width+vState.Margin.Right, maxX)
1210			(*state)[v.Properties.Id] = vState
1211
1212		}
1213	}
1214	rowWidth := maxX - minX
1215
1216	for c, col := range cols {
1217
1218		if content == "normal" {
1219			var offset float32
1220			if align == "center" {
1221				offset = ((selfWidth - rowWidth) / 2)
1222			}
1223			if align == "end" || align == "flex-end" || align == "self-end" {
1224				offset = (selfWidth - rowWidth)
1225			}
1226			for i := col[0]; i <= col[1]; i++ {
1227				v := n.Children[i]
1228				vState := s[v.Properties.Id]
1229				xStore := vState.X
1230				vState.X += offset
1231				propagateOffsets(&n.Children[i], xStore, vState.Y, vState.X, vState.Y, state)
1232				(*state)[v.Properties.Id] = vState
1233			}
1234			if align == "stretch" {
1235				offset = selfWidth / float32(len(col)+1)
1236				for i := col[0]; i <= col[1]; i++ {
1237					v := n.Children[i]
1238					vState := s[v.Properties.Id]
1239					xStore := vState.X
1240					// !ISSUE: Does not account for max/min width
1241					if v.Style["width"] == "" {
1242						vState.Width = offset - (vState.Margin.Left + (vState.Border.Width * 2) + vState.Margin.Right)
1243					}
1244					propagateOffsets(&n.Children[i], xStore, vState.Y, vState.X, vState.Y, state)
1245					(*state)[v.Properties.Id] = vState
1246				}
1247			}
1248		} else {
1249			var width float32
1250			for i := col[0]; i <= col[1]; i++ {
1251				v := n.Children[i]
1252				vState := s[v.Properties.Id]
1253				width = utils.Max(vState.Width+vState.Margin.Left+vState.Margin.Right, width)
1254			}
1255			var offset float32
1256			if c > 0 {
1257				sib := s[n.Children[cols[c-1][0]].Properties.Id]
1258				offset = sib.X + sib.Width + sib.Border.Width + sib.Margin.Right
1259			}
1260
1261			for i := col[0]; i <= col[1]; i++ {
1262				v := n.Children[i]
1263				vState := s[v.Properties.Id]
1264				xStore := vState.X
1265				vState.Width = width - (vState.Margin.Left + vState.Margin.Right)
1266				if c > 0 {
1267					vState.X = offset + vState.Margin.Left + vState.Border.Width
1268				}
1269				propagateOffsets(&n.Children[i], xStore, vState.Y, vState.X, vState.Y, state)
1270				minX2 = utils.Min(vState.X-vState.Border.Width-vState.Margin.Left, minX2)
1271				maxX2 = utils.Max(vState.X+vState.Width+vState.Border.Width+vState.Margin.Right, maxX2)
1272				(*state)[v.Properties.Id] = vState
1273			}
1274		}
1275	}
1276
1277	if content != "normal" {
1278		rowWidth2 := maxX2 - minX2
1279		var offset float32
1280		if content == "center" {
1281			offset = ((selfWidth - rowWidth2) / 2)
1282		}
1283		if content == "end" || content == "flex-end" {
1284			offset = (selfWidth - rowWidth2)
1285		}
1286		if content == "space-evenly" {
1287			offset = (selfWidth - rowWidth2) / (float32(len(cols) + 1))
1288		}
1289		if content == "space-between" {
1290			offset = (selfWidth - rowWidth2) / (float32(len(cols) - 1))
1291		}
1292		if content == "space-around" {
1293			offset = (selfWidth - rowWidth2) / (float32(len(cols)))
1294		}
1295		for c, col := range cols {
1296
1297			for i := col[0]; i <= col[1]; i++ {
1298				v := n.Children[i]
1299				vState := s[v.Properties.Id]
1300				xStore := vState.X
1301				if content == "center" || content == "end" || content == "flex-end" {
1302					vState.X += offset
1303				} else if content == "space-evenly" {
1304					vState.X += offset * float32(c+1)
1305				} else if content == "space-between" {
1306					vState.X += offset * float32(c)
1307				} else if content == "space-around" {
1308					if c == 0 {
1309						vState.X += offset / 2
1310					} else {
1311						vState.X += (offset * float32(c)) + (offset / 2)
1312					}
1313				}
1314				propagateOffsets(&n.Children[i], xStore, vState.Y, vState.X, vState.Y, state)
1315				(*state)[v.Properties.Id] = vState
1316			}
1317		}
1318	}
1319}