Author: LakeFox
Email: [email protected]
Date: Wed, 19 Jun 2024 16:34:49 -0600
docs/cstyle/plugins/flex/index.html
flex align-content done, starting column
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 ec88482..b52785a 100644
--- a/docs/cstyle/plugins/flex/index.html
+++ b/docs/cstyle/plugins/flex/index.html
@@ -111,27 +111,27 @@
- 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
+ 12// !ISSUES: Text disapearing (i think its the inline plugin)
+ 13// + widths
+ 14// + wrpa wraps too soon
+ 15
+ 16func Init() cstyle.Plugin {
+ 17	return cstyle.Plugin{
+ 18		Selector: func(n *element.Node) bool {
+ 19			styles := map[string]string{
+ 20				"display": "flex",
+ 21			}
+ 22			matches := true
+ 23			for name, value := range styles {
+ 24				if (n.Style[name] != value || n.Style[name] == "") && !(value == "*") {
+ 25					matches = false
+ 26				}
+ 27			}
+ 28			return matches
+ 29		},
+ 30		Level: 3,
+ 31		Handler: func(n *element.Node, state *map[string]element.State) {
+ 32			s := *state
+ 33			self := s[n.Properties.Id]
+ 34
+ 35			verbs := strings.Split(n.Style["flex-direction"], "-")
+ 36			flexDirection := verbs[0]
+ 37			if flexDirection == "" {
+ 38				flexDirection = "row"
@@ -139,15 +139,15 @@
- 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"
+ 40			flexReversed := false
+ 41			if len(verbs) > 1 {
+ 42				flexReversed = true
+ 43			}
+ 44
+ 45			var flexWrapped bool
+ 46			if n.Style["flex-wrap"] == "wrap" {
+ 47				flexWrapped = true
+ 48			} else {
+ 49				flexWrapped = false
+ 50			}
+ 51
+ 52			hAlign := n.Style["align-content"]
+ 53			if hAlign == "" {
+ 54				hAlign = "normal"
@@ -155,3 +155,3 @@
- 56			justifyItems := n.Style["justify-items"]
- 57			if justifyItems == "" {
- 58				justifyItems = "normal"
+ 56			vAlign := n.Style["align-items"]
+ 57			if vAlign == "" {
+ 58				vAlign = "normal"
@@ -159,27 +159,27 @@
- 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)
+ 60			justifyItems := n.Style["justify-items"]
+ 61			if justifyItems == "" {
+ 62				justifyItems = "normal"
+ 63			}
+ 64
+ 65			justifyContent := n.Style["justify-content"]
+ 66			if justifyContent == "" {
+ 67				justifyContent = "normal"
+ 68			}
+ 69			// fmt.Println(flexDirection, flexReversed, flexWrapped, hAlign, vAlign, justifyItems, justifyContent)
+ 70
+ 71			if flexDirection == "row" {
+ 72
+ 73				rows := [][]int{}
+ 74				maxH := float32(0)
+ 75
+ 76				// Get inital sizing
+ 77				textTotal := 0
+ 78				textCounts := []int{}
+ 79				widths := []float32{}
+ 80				innerSizes := [][]float32{}
+ 81				minWidths := []float32{}
+ 82				maxWidths := []float32{}
+ 83				for _, v := range n.Children {
+ 84					count := countText(v)
+ 85					textTotal += count
+ 86					textCounts = append(textCounts, count)
@@ -187,2 +187,2 @@
- 88				maxw := getMaxWidth(&v, state)
- 89				maxWidths = append(maxWidths, maxw)
+ 88					minw := getMinWidth(&v, state)
+ 89					minWidths = append(minWidths, minw)
@@ -190,30 +190,30 @@
- 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)
+ 91					maxw := getMaxWidth(&v, state)
+ 92					maxWidths = append(maxWidths, maxw)
+ 93
+ 94					w, h := getInnerSize(&v, state)
+ 95					innerSizes = append(innerSizes, []float32{w, h})
+ 96				}
+ 97				selfWidth := (self.Width - self.Padding.Left) - self.Padding.Right
+ 98				// if the elements are less than the size of the parent, don't change widths. Just set mins
+ 99				if !flexWrapped {
+100					if add2d(innerSizes, 0) < selfWidth {
+101						for i, v := range n.Children {
+102							vState := s[v.Properties.Id]
+103
+104							w := innerSizes[i][0]
+105							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+106							widths = append(widths, w)
+107						}
+108					} else {
+109						// Modifiy the widths so they aren't under the mins
+110						for i, v := range n.Children {
+111							vState := s[v.Properties.Id]
+112
+113							w := ((selfWidth / float32(textTotal)) * float32(textCounts[i]))
+114							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+115
+116							if w < minWidths[i] {
+117								selfWidth -= minWidths[i] + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+118								textTotal -= textCounts[i]
+119								textCounts[i] = 0
+120							}
@@ -221,143 +221,143 @@
-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					}
-192
-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)})
-239					}
-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			}
+122						}
+123						for i, v := range n.Children {
+124							vState := s[v.Properties.Id]
+125
+126							w := ((selfWidth / float32(textTotal)) * float32(textCounts[i]))
+127							w -= vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+128							// (w!=w) is of NaN
+129							if w < minWidths[i] || (w != w) {
+130								w = minWidths[i]
+131							}
+132							widths = append(widths, w)
+133						}
+134					}
+135					// Apply the new widths
+136					fState := s[n.Children[0].Properties.Id]
+137					for i, v := range n.Children {
+138						vState := s[v.Properties.Id]
+139
+140						vState.Width = widths[i]
+141						xStore := vState.X
+142						if i > 0 {
+143							sState := s[n.Children[i-1].Properties.Id]
+144							vState.X = sState.X + sState.Width + sState.Margin.Right + vState.Margin.Left + sState.Border.Width + vState.Border.Width
+145							propagateOffsets(&v, xStore, vState.Y, vState.X, fState.Y, state)
+146						}
+147
+148						vState.Y = fState.Y
+149
+150						(*state)[v.Properties.Id] = vState
+151						deInline(&v, state)
+152						applyInline(&v, state)
+153						applyBlock(&v, state)
+154						_, h := getInnerSize(&v, state)
+155						h = utils.Max(h, vState.Height)
+156						maxH = utils.Max(maxH, h)
+157					}
+158					// When not wrapping everything will be on the same row
+159					rows = append(rows, []int{0, len(n.Children), int(maxH)})
+160				} else {
+161					// Flex Wrapped
+162					sum := innerSizes[0][0]
+163					for i := 0; i < len(n.Children); i++ {
+164						v := n.Children[i]
+165						vState := s[v.Properties.Id]
+166
+167						// if the next plus current will break then
+168						w := innerSizes[i][0]
+169						if i > 0 {
+170							sib := s[n.Children[i-1].Properties.Id]
+171							if maxWidths[i] > selfWidth {
+172								w = selfWidth - vState.Margin.Left - vState.Margin.Right - (vState.Border.Width * 2)
+173							}
+174							if w+sum > selfWidth {
+175								sum = w + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+176							} else {
+177								propagateOffsets(&v, vState.X, vState.Y, vState.X, sib.Y, state)
+178								vState.Y = sib.Y
+179								(*state)[v.Properties.Id] = vState
+180								sum += w + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+181							}
+182						}
+183
+184						widths = append(widths, w)
+185					}
+186
+187					// Move the elements into the correct position
+188					start := 0
+189					var prevOffset float32
+190					for i := 0; i < len(n.Children); i++ {
+191						v := n.Children[i]
+192						vState := s[v.Properties.Id]
+193
+194						vState.Width = widths[i]
+195						xStore := vState.X
+196						yStore := vState.Y
+197
+198						if i > 0 {
+199							sib := s[n.Children[i-1].Properties.Id]
+200							if vState.Y+prevOffset == sib.Y {
+201								yStore += prevOffset
+202
+203								if vState.Height < sib.Height {
+204									vState.Height = sib.Height
+205								}
+206								// Shift right if on a row with sibling
+207								xStore = sib.X + sib.Width + sib.Margin.Right + sib.Border.Width + vState.Margin.Left + vState.Border.Width
+208							} else {
+209								// Shift under sibling
+210								yStore = sib.Y + sib.Height + sib.Margin.Top + sib.Margin.Bottom + sib.Border.Width*2
+211								prevOffset = yStore - vState.Y
+212								rows = append(rows, []int{start, i, int(maxH)})
+213								start = i
+214								maxH = 0
+215							}
+216							propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
+217						}
+218						vState.X = xStore
+219						vState.Y = yStore
+220
+221						(*state)[v.Properties.Id] = vState
+222						deInline(&v, state)
+223						applyInline(&v, state)
+224						applyBlock(&v, state)
+225						_, h := getInnerSize(&v, state)
+226						h = utils.Max(h, vState.Height)
+227						maxH = utils.Max(maxH, h)
+228						vState.Height = h
+229						(*state)[v.Properties.Id] = vState
+230					}
+231					if start < len(n.Children) {
+232						rows = append(rows, []int{start, len(n.Children), int(maxH)})
+233					}
+234				}
+235
+236				for _, v := range rows {
+237					for i := v[0]; i < v[1]; i++ {
+238						vState := s[n.Children[i].Properties.Id]
+239						vState.Height = float32(v[2])
+240						(*state)[n.Children[i].Properties.Id] = vState
+241					}
+242				}
+243				// Reverse elements
+244				if flexReversed {
+245					rowReverse(rows, n, state)
+246				}
+247
+248				if justifyContent != "" && justifyContent != "normal" {
+249					justifyRow(rows, n, state, justifyContent, flexReversed)
+250				}
+251			}
+252
+253			// Column doesn't really need a lot done bc it is basically block styling rn
+254			if flexDirection == "column" && flexReversed {
+255				colReverse(n, state)
+256			}
+257			if n.Style["height"] == "" {
+258				_, h := getInnerSize(n, state)
+259				self.Height = h
+260			}
+261			(*state)[n.Properties.Id] = self
+262		},
+263	}
+264}
@@ -365,56 +365,56 @@
-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 n.Style["height"] != "" || n.Style["min-height"] != "" {
-270						h := selfHeight / float32(len(n.Children))
-271						for i, v := range n.Children {
-272							vState := s[v.Properties.Id]
-273							yStore := vState.Y
-274							adjH := h - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
-275							if adjH < vState.Height {
-276
-277								if minHeights[i] > adjH {
-278									vState.Height = minHeights[i]
-279									if i > 0 {
-280										sib := s[n.Children[i-1].Properties.Id]
-281										vState.Y = sib.Y + sib.Height + sib.Margin.Bottom + sib.Border.Width + vState.Margin.Top + vState.Border.Width
-282									}
-283								} else {
-284									vState.Height = adjH
-285									vState.Y = self.Y + self.Padding.Top + self.Border.Width + (h * float32(i)) + vState.Margin.Top
-286								}
-287								propagateOffsets(&v, vState.X, yStore, vState.X, vState.Y, state)
-288								(*state)[v.Properties.Id] = vState
-289							}
-290						}
-291					}
-292					for i, v := range n.Children {
-293						vState := s[v.Properties.Id]
-294						rows = append(rows, []int{i, i + 1, int(vState.Height)})
-295					}
-296
-297				}
-298				if flexReversed {
-299					colReverse(n, state)
-300				}
-301			}
-302			if n.Style["height"] == "" || n.Style["min-height"] == "" {
-303				_, h := getInnerSize(n, state)
-304				// fmt.Println(h)
-305				self.Height = h
-306			}
-307			(*state)[n.Properties.Id] = self
-308		},
-309	}
-310}
-311
-312func applyBlock(n *element.Node, state *map[string]element.State) {
-313	if len(n.Children) > 0 {
-314		accum := float32(0)
-315		inlineOffset := float32(0)
-316		s := *state
-317		lastHeight := float32(0)
-318		baseY := s[n.Children[0].Properties.Id].Y
-319		for i := 0; i < len(n.Children); i++ {
-320			v := &n.Children[i]
-321			vState := s[v.Properties.Id]
+266func applyBlock(n *element.Node, state *map[string]element.State) {
+267	accum := float32(0)
+268	inlineOffset := float32(0)
+269	s := *state
+270	lastHeight := float32(0)
+271	baseY := s[n.Children[0].Properties.Id].Y
+272	for i := 0; i < len(n.Children); i++ {
+273		v := &n.Children[i]
+274		vState := s[v.Properties.Id]
+275
+276		if v.Style["display"] != "block" {
+277			vState.Y += inlineOffset
+278			accum = (vState.Y - baseY)
+279			lastHeight = vState.Height
+280		} else if v.Style["position"] != "absolute" {
+281			vState.Y += accum
+282			inlineOffset += (vState.Height + (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom) + lastHeight
+283		}
+284		(*state)[v.Properties.Id] = vState
+285	}
+286}
+287
+288func deInline(n *element.Node, state *map[string]element.State) {
+289	s := *state
+290	// self := s[n.Properties.Id]
+291	baseX := float32(-1)
+292	baseY := float32(-1)
+293	for _, v := range n.Children {
+294		vState := s[v.Properties.Id]
+295
+296		if v.Style["display"] == "inline" {
+297			if baseX < 0 && baseY < 0 {
+298				baseX = vState.X
+299				baseY = vState.Y
+300			} else {
+301				vState.X = baseX
+302				vState.Y = baseY
+303				(*state)[v.Properties.Id] = vState
+304
+305			}
+306		} else {
+307			baseX = float32(-1)
+308			baseY = float32(-1)
+309		}
+310
+311		if len(v.Children) > 0 {
+312			deInline(&v, state)
+313		}
+314	}
+315
+316}
+317
+318func applyInline(n *element.Node, state *map[string]element.State) {
+319	pl := inline.Init()
+320	for i := 0; i < len(n.Children); i++ {
+321		v := &n.Children[i]
@@ -422,107 +422,107 @@
-323			if v.Style["display"] != "block" {
-324				vState.Y += inlineOffset
-325				accum = (vState.Y - baseY)
-326				lastHeight = vState.Height
-327			} else if v.Style["position"] != "absolute" {
-328				vState.Y += accum
-329				inlineOffset += (vState.Height + (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom) + lastHeight
-330			}
-331			(*state)[v.Properties.Id] = vState
-332		}
-333	}
-334}
-335
-336func deInline(n *element.Node, state *map[string]element.State) {
-337	s := *state
-338	// self := s[n.Properties.Id]
-339	baseX := float32(-1)
-340	baseY := float32(-1)
-341	for _, v := range n.Children {
-342		vState := s[v.Properties.Id]
-343
-344		if v.Style["display"] == "inline" {
-345			if baseX < 0 && baseY < 0 {
-346				baseX = vState.X
-347				baseY = vState.Y
-348			} else {
-349				vState.X = baseX
-350				vState.Y = baseY
-351				(*state)[v.Properties.Id] = vState
-352
-353			}
-354		} else {
-355			baseX = float32(-1)
-356			baseY = float32(-1)
-357		}
-358
-359		if len(v.Children) > 0 {
-360			deInline(&v, state)
-361		}
-362	}
-363
-364}
-365
-366func applyInline(n *element.Node, state *map[string]element.State) {
-367	pl := inline.Init()
-368	for i := 0; i < len(n.Children); i++ {
-369		v := &n.Children[i]
-370
-371		if len(v.Children) > 0 {
-372			applyInline(v, state)
-373		}
-374
-375		if pl.Selector(v) {
-376			pl.Handler(v, state)
-377		}
-378	}
-379}
-380
-381func propagateOffsets(n *element.Node, prevx, prevy, newx, newy float32, state *map[string]element.State) {
-382	s := *state
-383	for _, v := range n.Children {
-384		vState := s[v.Properties.Id]
-385		xStore := (vState.X - prevx) + newx
-386		yStore := (vState.Y - prevy) + newy
-387
-388		if len(v.Children) > 0 {
-389			propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
-390		}
-391		vState.X = xStore
-392		vState.Y = yStore
-393		(*state)[v.Properties.Id] = vState
-394	}
-395
-396}
-397
-398func countText(n element.Node) int {
-399	count := 0
-400	groups := []int{}
-401	for _, v := range n.Children {
-402		if v.TagName == "notaspan" {
-403			count += 1
-404		}
-405		if v.Style["display"] == "block" {
-406			groups = append(groups, count)
-407			count = 0
-408		}
-409		if len(v.Children) > 0 {
-410			count += countText(v)
-411		}
-412	}
-413	groups = append(groups, count)
-414
-415	sort.Slice(groups, func(i, j int) bool {
-416		return groups[i] > groups[j]
-417	})
-418	return groups[0]
-419}
-420
-421func minHeight(n element.Node, state *map[string]element.State, prev float32) float32 {
-422	s := *state
-423	self := s[n.Properties.Id]
-424	if n.Style["min-height"] != "" {
-425		mw := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
-426		return utils.Max(prev, mw)
-427	} else {
-428		return prev
-429	}
+323		if len(v.Children) > 0 {
+324			applyInline(v, state)
+325		}
+326
+327		if pl.Selector(v) {
+328			pl.Handler(v, state)
+329		}
+330	}
+331}
+332
+333func propagateOffsets(n *element.Node, prevx, prevy, newx, newy float32, state *map[string]element.State) {
+334	s := *state
+335	for _, v := range n.Children {
+336		vState := s[v.Properties.Id]
+337		xStore := (vState.X - prevx) + newx
+338		yStore := (vState.Y - prevy) + newy
+339
+340		if len(v.Children) > 0 {
+341			propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
+342		}
+343		vState.X = xStore
+344		vState.Y = yStore
+345		(*state)[v.Properties.Id] = vState
+346	}
+347
+348}
+349
+350func countText(n element.Node) int {
+351	count := 0
+352	groups := []int{}
+353	for _, v := range n.Children {
+354		if v.TagName == "notaspan" {
+355			count += 1
+356		}
+357		if v.Style["display"] == "block" {
+358			groups = append(groups, count)
+359			count = 0
+360		}
+361		if len(v.Children) > 0 {
+362			count += countText(v)
+363		}
+364	}
+365	groups = append(groups, count)
+366
+367	sort.Slice(groups, func(i, j int) bool {
+368		return groups[i] > groups[j]
+369	})
+370	return groups[0]
+371}
+372
+373func getMinWidth(n *element.Node, state *map[string]element.State) float32 {
+374	s := *state
+375	self := s[n.Properties.Id]
+376	selfWidth := float32(0)
+377
+378	if len(n.Children) > 0 {
+379		for _, v := range n.Children {
+380			selfWidth = utils.Max(selfWidth, getNodeWidth(&v, state))
+381		}
+382	} else {
+383		selfWidth = self.Width
+384	}
+385
+386	selfWidth += self.Padding.Left + self.Padding.Right
+387	return selfWidth
+388}
+389func getMaxWidth(n *element.Node, state *map[string]element.State) float32 {
+390	s := *state
+391	self := s[n.Properties.Id]
+392	selfWidth := float32(0)
+393
+394	if len(n.Children) > 0 {
+395		for _, v := range n.Children {
+396			selfWidth += getNodeWidth(&v, state)
+397		}
+398	} else {
+399		selfWidth = self.Width
+400	}
+401
+402	selfWidth += self.Padding.Left + self.Padding.Right
+403	return selfWidth
+404}
+405
+406func getNodeWidth(n *element.Node, state *map[string]element.State) float32 {
+407	s := *state
+408	self := s[n.Properties.Id]
+409	w := float32(0)
+410	w += self.Padding.Left
+411	w += self.Padding.Right
+412
+413	w += self.Margin.Left
+414	w += self.Margin.Right
+415
+416	w += self.Width
+417
+418	w += self.Border.Width * 2
+419
+420	for _, v := range n.Children {
+421		w = utils.Max(w, getNodeWidth(&v, state))
+422	}
+423
+424	return w
+425}
+426
+427func getInnerSize(n *element.Node, state *map[string]element.State) (float32, float32) {
+428	s := *state
+429	self := s[n.Properties.Id]
@@ -530,27 +530,27 @@
-431}
-432
-433func getMinHeight(n *element.Node, state *map[string]element.State) float32 {
-434	s := *state
-435	self := s[n.Properties.Id]
-436	selfHeight := float32(0)
-437
-438	if len(n.Children) > 0 {
-439		for _, v := range n.Children {
-440			selfHeight = utils.Max(selfHeight, getNodeHeight(&v, state))
-441		}
-442	} else {
-443		selfHeight = self.Height
-444	}
-445	if n.Style["min-height"] != "" {
-446		mh := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
-447		selfHeight = utils.Max(mh, selfHeight)
-448	}
-449
-450	selfHeight += self.Padding.Top + self.Padding.Bottom
-451	return selfHeight
-452}
-453
-454func getMinWidth(n *element.Node, state *map[string]element.State) float32 {
-455	s := *state
-456	self := s[n.Properties.Id]
-457	selfWidth := float32(0)
+431	minx := float32(10e10)
+432	maxw := float32(0)
+433	miny := float32(10e10)
+434	maxh := float32(0)
+435	for _, v := range n.Children {
+436		vState := s[v.Properties.Id]
+437		minx = utils.Min(vState.X, minx)
+438		miny = utils.Min(vState.Y, miny)
+439		hOffset := (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom
+440		wOffset := (vState.Border.Width * 2) + vState.Margin.Left + vState.Margin.Right
+441		maxw = utils.Max(vState.X+vState.Width+wOffset, maxw)
+442		maxh = utils.Max(vState.Y+vState.Height+hOffset, maxh)
+443	}
+444	w := maxw - minx
+445	h := maxh - miny
+446
+447	// !ISSUE: this is a hack to get things moving adding 13 is random
+448	w += self.Padding.Left + self.Padding.Right + 13
+449	h += self.Padding.Top + self.Padding.Bottom
+450	if n.Style["width"] != "" {
+451		w = self.Width
+452	}
+453	if n.Style["height"] != "" {
+454		h = self.Height
+455	}
+456	return w, h
+457}
@@ -558,14 +558,14 @@
-459	if len(n.Children) > 0 {
-460		for _, v := range n.Children {
-461			selfWidth = utils.Max(selfWidth, getNodeWidth(&v, state))
-462		}
-463	} else {
-464		selfWidth = self.Width
-465	}
-466	if n.Style["min-width"] != "" {
-467		mw := utils.ConvertToPixels(n.Style["min-width"], self.EM, s[n.Parent.Properties.Id].Width)
-468		selfWidth = utils.Max(mw, selfWidth)
-469	}
-470
-471	selfWidth += self.Padding.Left + self.Padding.Right
-472	return selfWidth
+459func add2d(arr [][]float32, index int) float32 {
+460	var sum float32
+461	if len(arr) == 0 {
+462		return sum
+463	}
+464
+465	for i := 0; i < len(arr); i++ {
+466		if len(arr[i]) <= index {
+467			return sum
+468		}
+469		sum += arr[i][index]
+470	}
+471
+472	return sum
@@ -573,19 +573,19 @@
-474func getMaxWidth(n *element.Node, state *map[string]element.State) float32 {
-475	s := *state
-476	self := s[n.Properties.Id]
-477	selfWidth := float32(0)
-478
-479	if len(n.Children) > 0 {
-480		var maxRowWidth, rowWidth float32
-481
-482		for _, v := range n.Children {
-483			rowWidth += getNodeWidth(&v, state)
-484			if v.Style["display"] != "inline" {
-485				maxRowWidth = utils.Max(rowWidth, maxRowWidth)
-486				rowWidth = 0
-487			}
-488		}
-489		selfWidth = utils.Max(rowWidth, maxRowWidth)
-490	} else {
-491		selfWidth = self.Width
-492	}
+474
+475func colReverse(n *element.Node, state *map[string]element.State) {
+476	s := *state
+477	tempNodes := []element.Node{}
+478	tempStates := []element.State{}
+479	for i := len(n.Children) - 1; i >= 0; i-- {
+480		tempNodes = append(tempNodes, n.Children[i])
+481		tempStates = append(tempStates, s[n.Children[i].Properties.Id])
+482	}
+483
+484	for i := 0; i < len(tempStates); i++ {
+485		vState := s[n.Children[i].Properties.Id]
+486		propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, tempStates[i].Y, state)
+487		vState.Y = tempStates[i].Y
+488		(*state)[n.Children[i].Properties.Id] = vState
+489	}
+490
+491	n.Children = tempNodes
+492}
@@ -593,10 +593,10 @@
-494	selfWidth += self.Padding.Left + self.Padding.Right
-495	return selfWidth
-496}
-497
-498func getNodeWidth(n *element.Node, state *map[string]element.State) float32 {
-499	s := *state
-500	self := s[n.Properties.Id]
-501	w := float32(0)
-502	w += self.Padding.Left
-503	w += self.Padding.Right
+494func rowReverse(rows [][]int, n *element.Node, state *map[string]element.State) {
+495	s := *state
+496	for _, row := range rows {
+497		tempNodes := []element.Node{}
+498		tempStates := []element.State{}
+499
+500		for i := row[1] - 1; i >= row[0]; i-- {
+501			tempNodes = append(tempNodes, n.Children[i])
+502			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
+503		}
@@ -604,136 +604,136 @@
-505	w += self.Margin.Left
-506	w += self.Margin.Right
-507
-508	w += self.Width
-509
-510	w += self.Border.Width * 2
-511
-512	for _, v := range n.Children {
-513		w = utils.Max(w, getNodeWidth(&v, state))
-514	}
-515
-516	return w
-517}
-518func getMaxHeight(n *element.Node, state *map[string]element.State) float32 {
-519	s := *state
-520	self := s[n.Properties.Id]
-521	selfHeight := float32(0)
-522
-523	if len(n.Children) > 0 {
-524		var maxRowHeight, rowHeight float32
-525
-526		for _, v := range n.Children {
-527			rowHeight += getNodeHeight(&v, state)
-528			if v.Style["display"] != "inline" {
-529				maxRowHeight = utils.Max(rowHeight, maxRowHeight)
-530				rowHeight = 0
-531			}
-532		}
-533		selfHeight = utils.Max(rowHeight, maxRowHeight)
-534	} else {
-535		selfHeight = self.Height
-536	}
-537
-538	selfHeight += self.Padding.Top + self.Padding.Bottom
-539	return selfHeight
-540}
-541
-542func getNodeHeight(n *element.Node, state *map[string]element.State) float32 {
-543	s := *state
-544	self := s[n.Properties.Id]
-545	h := float32(0)
-546	h += self.Padding.Top
-547	h += self.Padding.Bottom
-548
-549	h += self.Margin.Top
-550	h += self.Margin.Bottom
-551
-552	h += self.Height
-553
-554	h += self.Border.Width * 2
-555
-556	for _, v := range n.Children {
-557		h = utils.Max(h, getNodeHeight(&v, state))
-558	}
-559
-560	return h
-561}
-562
-563func getInnerSize(n *element.Node, state *map[string]element.State) (float32, float32) {
-564	s := *state
-565	self := s[n.Properties.Id]
-566
-567	minx := float32(10e10)
-568	maxw := float32(0)
-569	miny := float32(10e10)
-570	maxh := float32(0)
-571	for _, v := range n.Children {
-572		vState := s[v.Properties.Id]
-573		minx = utils.Min(vState.X, minx)
-574		miny = utils.Min(vState.Y-vState.Margin.Top, miny)
-575		// Don't add the top or left because the x&y values already take that into account
-576		hOffset := (vState.Border.Width * 2) + vState.Margin.Bottom
-577		wOffset := (vState.Border.Width * 2) + vState.Margin.Right
-578		maxw = utils.Max(vState.X+vState.Width+wOffset, maxw)
-579		maxh = utils.Max(vState.Y+vState.Height+hOffset, maxh)
-580	}
-581	w := maxw - minx
-582	h := maxh - miny
-583
-584	w += self.Padding.Left + self.Padding.Right
-585	h += self.Padding.Top + self.Padding.Bottom
-586	if n.Style["width"] != "" {
-587		w = self.Width
-588	}
-589	if n.Style["height"] != "" {
-590		h = self.Height
-591	}
-592
-593	return w, h
-594}
-595
-596func add2d(arr [][]float32, index int) float32 {
-597	var sum float32
-598	if len(arr) == 0 {
-599		return sum
-600	}
-601
-602	for i := 0; i < len(arr); i++ {
-603		if len(arr[i]) <= index {
-604			return sum
-605		}
-606		sum += arr[i][index]
-607	}
-608
-609	return sum
-610}
-611
-612func colReverse(n *element.Node, state *map[string]element.State) {
-613	s := *state
-614	tempNodes := []element.Node{}
-615	tempStates := []element.State{}
-616	for i := len(n.Children) - 1; i >= 0; i-- {
-617		tempNodes = append(tempNodes, n.Children[i])
-618		tempStates = append(tempStates, s[n.Children[i].Properties.Id])
-619	}
-620
-621	for i := 0; i < len(tempStates); i++ {
-622		vState := s[n.Children[i].Properties.Id]
-623		propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, tempStates[i].Y, state)
-624		vState.Y = tempStates[i].Y
-625		(*state)[n.Children[i].Properties.Id] = vState
-626	}
-627
-628	n.Children = tempNodes
-629}
-630
-631func rowReverse(rows [][]int, n *element.Node, state *map[string]element.State) {
-632	s := *state
-633	for _, row := range rows {
-634		tempNodes := []element.Node{}
-635		tempStates := []element.State{}
-636
-637		for i := row[1] - 1; i >= row[0]; i-- {
-638			tempNodes = append(tempNodes, n.Children[i])
-639			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
-640		}
+505		for i := 0; i < len(tempStates); i++ {
+506			e := row[0] + i
+507			vState := s[n.Children[e].Properties.Id]
+508			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
+509			vState.X = tempStates[i].X
+510			(*state)[n.Children[e].Properties.Id] = vState
+511		}
+512		for i := 0; i < len(tempStates); i++ {
+513			e := row[0] + i
+514			n.Children[e] = tempNodes[i]
+515		}
+516
+517		for i := row[1] - 1; i >= row[0]; i-- {
+518			vState := s[n.Children[i].Properties.Id]
+519			var xChng float32
+520			if i < row[1]-1 {
+521				sib := s[n.Children[i+1].Properties.Id]
+522				xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
+523			} else {
+524				parent := s[n.Properties.Id]
+525				xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
+526
+527			}
+528			propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+529			vState.X = xChng
+530			(*state)[n.Children[i].Properties.Id] = vState
+531		}
+532	}
+533}
+534
+535func justifyRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
+536	s := *state
+537	for _, row := range rows {
+538
+539		if (justify == "flex-end" || justify == "end" || justify == "right") && !reversed {
+540			for i := row[1] - 1; i >= row[0]; i-- {
+541				vState := s[n.Children[i].Properties.Id]
+542				var xChng float32
+543				if i < row[1]-1 {
+544					sib := s[n.Children[i+1].Properties.Id]
+545					xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
+546				} else {
+547					parent := s[n.Properties.Id]
+548					xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
+549
+550				}
+551				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+552				vState.X = xChng
+553				(*state)[n.Children[i].Properties.Id] = vState
+554			}
+555		} else if (justify == "flex-end" || justify == "start" || justify == "left" || justify == "normal") && reversed {
+556			for i := row[0]; i < row[1]; i++ {
+557				vState := s[n.Children[i].Properties.Id]
+558				var xChng float32
+559				if i > row[0] {
+560					sib := s[n.Children[i-1].Properties.Id]
+561					xChng = sib.X + sib.Width + (sib.Border.Width * 2) + sib.Margin.Right + vState.Margin.Left + vState.Border.Width
+562				} else {
+563					parent := s[n.Properties.Id]
+564					xChng = parent.X + parent.Padding.Right + vState.Margin.Left + vState.Border.Width + parent.Border.Width
+565
+566				}
+567				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+568				vState.X = xChng
+569				(*state)[n.Children[i].Properties.Id] = vState
+570			}
+571		} else if justify == "center" {
+572			// get width of row then center (by getting last x + w + mr + b)
+573			f := s[n.Children[row[0]].Properties.Id]
+574			l := s[n.Children[row[1]-1].Properties.Id]
+575			parent := s[n.Properties.Id]
+576			po := parent.X + parent.Border.Width
+577			offset := (parent.Width - ((f.X - po) + (l.X - po) + l.Width + f.Border.Width + l.Border.Width)) / 2
+578
+579			for i := row[0]; i < row[1]; i++ {
+580				vState := s[n.Children[i].Properties.Id]
+581
+582				if !reversed {
+583					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+584					vState.X += offset
+585				} else {
+586					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+587					vState.X -= offset
+588				}
+589				(*state)[n.Children[i].Properties.Id] = vState
+590			}
+591
+592		} else if justify == "space-between" {
+593			// get width of row then center (by getting last x + w + mr + b)
+594			f := s[n.Children[row[0]].Properties.Id]
+595			l := s[n.Children[row[1]-1].Properties.Id]
+596			parent := s[n.Properties.Id]
+597			po := parent.Border.Width + parent.Width
+598			po -= parent.Padding.Left + parent.Padding.Right
+599
+600			// make po repersent the total space between elements
+601			for i := row[0]; i < row[1]; i++ {
+602				vState := s[n.Children[i].Properties.Id]
+603				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+604			}
+605
+606			po /= float32(((row[1]) - row[0]) - 1)
+607
+608			if (row[1]-1)-row[0] > 0 {
+609				for i := row[0]; i < row[1]; i++ {
+610					vState := s[n.Children[i].Properties.Id]
+611					var offset float32
+612					if i == row[0] {
+613						offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
+614					} else if i == row[1]-1 {
+615						offset = (parent.X + parent.Width) - (l.Margin.Right + l.Border.Width + l.Width + parent.Padding.Right)
+616					} else {
+617						if !reversed {
+618							offset = vState.X + (po * float32(i-row[0]))
+619						} else {
+620							offset = vState.X - (po * float32(((row[1]-1)-row[0])-(i-row[0])))
+621						}
+622
+623					}
+624
+625					propagateOffsets(&n.Children[i], vState.X, vState.Y, offset, vState.Y, state)
+626					vState.X = offset
+627					(*state)[n.Children[i].Properties.Id] = vState
+628				}
+629			} else {
+630				// if there is one element move left
+631				vState := s[n.Children[(row[1]-1)-row[0]].Properties.Id]
+632				var offset float32
+633
+634				if !reversed {
+635					offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
+636					propagateOffsets(&n.Children[(row[1]-1)-row[0]], vState.X, vState.Y, offset, vState.Y, state)
+637					vState.X = offset
+638
+639					(*state)[n.Children[(row[1]-1)-row[0]].Properties.Id] = vState
+640				}
@@ -741,33 +741,33 @@
-642		for i := 0; i < len(tempStates); i++ {
-643			e := row[0] + i
-644			vState := s[n.Children[e].Properties.Id]
-645			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
-646			vState.X = tempStates[i].X
-647			(*state)[n.Children[e].Properties.Id] = vState
-648		}
-649		for i := 0; i < len(tempStates); i++ {
-650			e := row[0] + i
-651			n.Children[e] = tempNodes[i]
-652		}
-653
-654		for i := row[1] - 1; i >= row[0]; i-- {
-655			vState := s[n.Children[i].Properties.Id]
-656			var xChng float32
-657			if i < row[1]-1 {
-658				sib := s[n.Children[i+1].Properties.Id]
-659				xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
-660			} else {
-661				parent := s[n.Properties.Id]
-662				xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
-663
-664			}
-665			propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
-666			vState.X = xChng
-667			(*state)[n.Children[i].Properties.Id] = vState
-668		}
-669	}
-670}
-671
-672func justifyRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
-673	s := *state
-674	for _, row := range rows {
+642			}
+643
+644		} else if justify == "space-evenly" {
+645			// get width of row then center (by getting last x + w + mr + b)
+646			parent := s[n.Properties.Id]
+647			po := parent.Border.Width + parent.Width
+648			po -= parent.Padding.Left + parent.Padding.Right
+649
+650			// make po repersent the total space between elements
+651			for i := row[0]; i < row[1]; i++ {
+652				vState := s[n.Children[i].Properties.Id]
+653				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+654			}
+655
+656			po /= float32(((row[1]) - row[0]) + 1)
+657
+658			// get width of row then center (by getting last x + w + mr + b)
+659
+660			for i := row[0]; i < row[1]; i++ {
+661				vState := s[n.Children[i].Properties.Id]
+662
+663				if !reversed {
+664					offset := po * (float32(i-row[0]) + 1)
+665					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+666					vState.X += offset
+667				} else {
+668					offset := po * float32(((row[1]-1)-row[0])-((i-row[0])-1))
+669
+670					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+671					vState.X -= offset
+672				}
+673				(*state)[n.Children[i].Properties.Id] = vState
+674			}
@@ -775,39 +775,39 @@
-676		if (justify == "flex-end" || justify == "end" || justify == "right") && !reversed {
-677			for i := row[1] - 1; i >= row[0]; i-- {
-678				vState := s[n.Children[i].Properties.Id]
-679				var xChng float32
-680				if i < row[1]-1 {
-681					sib := s[n.Children[i+1].Properties.Id]
-682					xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
-683				} else {
-684					parent := s[n.Properties.Id]
-685					xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
-686
-687				}
-688				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
-689				vState.X = xChng
-690				(*state)[n.Children[i].Properties.Id] = vState
-691			}
-692		} else if (justify == "flex-end" || justify == "start" || justify == "left" || justify == "normal") && reversed {
-693			for i := row[0]; i < row[1]; i++ {
-694				vState := s[n.Children[i].Properties.Id]
-695				var xChng float32
-696				if i > row[0] {
-697					sib := s[n.Children[i-1].Properties.Id]
-698					xChng = sib.X + sib.Width + (sib.Border.Width * 2) + sib.Margin.Right + vState.Margin.Left + vState.Border.Width
-699				} else {
-700					parent := s[n.Properties.Id]
-701					xChng = parent.X + parent.Padding.Right + vState.Margin.Left + vState.Border.Width + parent.Border.Width
-702
-703				}
-704				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
-705				vState.X = xChng
-706				(*state)[n.Children[i].Properties.Id] = vState
-707			}
-708		} else if justify == "center" {
-709			// get width of row then center (by getting last x + w + mr + b)
-710			f := s[n.Children[row[0]].Properties.Id]
-711			l := s[n.Children[row[1]-1].Properties.Id]
-712			parent := s[n.Properties.Id]
-713			po := parent.X + parent.Border.Width
-714			offset := (parent.Width - ((f.X - po) + (l.X - po) + l.Width + f.Border.Width + l.Border.Width)) / 2
+676		} else if justify == "space-around" {
+677			// get width of row then center (by getting last x + w + mr + b)
+678			parent := s[n.Properties.Id]
+679			po := parent.Border.Width + parent.Width
+680			po -= parent.Padding.Left + parent.Padding.Right
+681
+682			// make po repersent the total space between elements
+683			for i := row[0]; i < row[1]; i++ {
+684				vState := s[n.Children[i].Properties.Id]
+685				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+686			}
+687
+688			po /= float32(((row[1]) - row[0]))
+689
+690			// get width of row then center (by getting last x + w + mr + b)
+691
+692			for i := row[0]; i < row[1]; i++ {
+693				vState := s[n.Children[i].Properties.Id]
+694
+695				if !reversed {
+696					m := (float32(i-row[0]) + 1)
+697					if i-row[0] == 0 {
+698						m = 0.5
+699					} else {
+700						m -= 0.5
+701					}
+702					offset := po * m
+703					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+704					vState.X += offset
+705				} else {
+706					m := float32(((row[1] - 1) - row[0]) - ((i - row[0]) - 1))
+707					m -= 0.5
+708					offset := po * m
+709
+710					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+711					vState.X -= offset
+712				}
+713				(*state)[n.Children[i].Properties.Id] = vState
+714			}
@@ -815,267 +815,8 @@
-716			for i := row[0]; i < row[1]; i++ {
-717				vState := s[n.Children[i].Properties.Id]
-718
-719				if !reversed {
-720					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
-721					vState.X += offset
-722				} else {
-723					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
-724					vState.X -= offset
-725				}
-726				(*state)[n.Children[i].Properties.Id] = vState
-727			}
-728
-729		} else if justify == "space-between" {
-730			// get width of row then center (by getting last x + w + mr + b)
-731			f := s[n.Children[row[0]].Properties.Id]
-732			l := s[n.Children[row[1]-1].Properties.Id]
-733			parent := s[n.Properties.Id]
-734			po := parent.Border.Width + parent.Width
-735			po -= parent.Padding.Left + parent.Padding.Right
-736
-737			// make po repersent the total space between elements
-738			for i := row[0]; i < row[1]; i++ {
-739				vState := s[n.Children[i].Properties.Id]
-740				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
-741			}
-742
-743			po /= float32(((row[1]) - row[0]) - 1)
-744
-745			if (row[1]-1)-row[0] > 0 {
-746				for i := row[0]; i < row[1]; i++ {
-747					vState := s[n.Children[i].Properties.Id]
-748					var offset float32
-749					if i == row[0] {
-750						offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
-751					} else if i == row[1]-1 {
-752						offset = (parent.X + parent.Width) - (l.Margin.Right + l.Border.Width + l.Width + parent.Padding.Right)
-753					} else {
-754						if !reversed {
-755							offset = vState.X + (po * float32(i-row[0]))
-756						} else {
-757							offset = vState.X - (po * float32(((row[1]-1)-row[0])-(i-row[0])))
-758						}
-759
-760					}
-761
-762					propagateOffsets(&n.Children[i], vState.X, vState.Y, offset, vState.Y, state)
-763					vState.X = offset
-764					(*state)[n.Children[i].Properties.Id] = vState
-765				}
-766			}
-767			//  else {
-768
-769			// this is/was causing issues, removed and it fixed its self
-770
-771			// if there is one element move left
-772			// vState := s[n.Children[(row[1]-1)-row[0]].Properties.Id]
-773			// var offset float32
-774
-775			// if !reversed {
-776			// 	offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
-777			// 	propagateOffsets(&n.Children[(row[1]-1)-row[0]], vState.X, vState.Y, offset, vState.Y, state)
-778			// 	vState.X = offset
-779
-780			// 	(*state)[n.Children[(row[1]-1)-row[0]].Properties.Id] = vState
-781			// }
-782
-783			// }
-784
-785		} else if justify == "space-evenly" {
-786			// get width of row then center (by getting last x + w + mr + b)
-787			parent := s[n.Properties.Id]
-788			po := parent.Border.Width + parent.Width
-789			po -= parent.Padding.Left + parent.Padding.Right
-790
-791			// make po repersent the total space between elements
-792			for i := row[0]; i < row[1]; i++ {
-793				vState := s[n.Children[i].Properties.Id]
-794				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
-795			}
-796
-797			po /= float32(((row[1]) - row[0]) + 1)
-798
-799			// get width of row then center (by getting last x + w + mr + b)
-800
-801			for i := row[0]; i < row[1]; i++ {
-802				vState := s[n.Children[i].Properties.Id]
-803
-804				if !reversed {
-805					offset := po * (float32(i-row[0]) + 1)
-806					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
-807					vState.X += offset
-808				} else {
-809					offset := po * float32(((row[1]-1)-row[0])-((i-row[0])-1))
-810
-811					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
-812					vState.X -= offset
-813				}
-814				(*state)[n.Children[i].Properties.Id] = vState
-815			}
-816
-817		} else if justify == "space-around" {
-818			// get width of row then center (by getting last x + w + mr + b)
-819			parent := s[n.Properties.Id]
-820			po := parent.Border.Width + parent.Width
-821			po -= parent.Padding.Left + parent.Padding.Right
-822
-823			// make po repersent the total space between elements
-824			for i := row[0]; i < row[1]; i++ {
-825				vState := s[n.Children[i].Properties.Id]
-826				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
-827			}
-828
-829			po /= float32(((row[1]) - row[0]))
-830
-831			// get width of row then center (by getting last x + w + mr + b)
-832
-833			for i := row[0]; i < row[1]; i++ {
-834				vState := s[n.Children[i].Properties.Id]
-835
-836				if !reversed {
-837					m := (float32(i-row[0]) + 1)
-838					if i-row[0] == 0 {
-839						m = 0.5
-840					} else {
-841						m -= 0.5
-842					}
-843					offset := po * m
-844					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
-845					vState.X += offset
-846				} else {
-847					m := float32(((row[1] - 1) - row[0]) - ((i - row[0]) - 1))
-848					m -= 0.5
-849					offset := po * m
-850
-851					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
-852					vState.X -= offset
-853				}
-854				(*state)[n.Children[i].Properties.Id] = vState
-855			}
-856
-857		}
-858
-859	}
-860}
-861
-862func alignRow(rows [][]int, n *element.Node, state *map[string]element.State, align, content string) {
-863	// !ISSUE: Baseline isn't properly impleamented
-864
-865	s := *state
-866	self := s[n.Properties.Id]
-867
-868	maxes := []float32{}
-869	var maxesTotal float32
-870	for _, row := range rows {
-871		var maxH float32
-872		for i := row[0]; i < row[1]; i++ {
-873			vState := s[n.Children[i].Properties.Id]
-874			_, h := getInnerSize(&n.Children[i], state)
-875			h = minHeight(n.Children[i], state, h)
-876			vState.Height = h
-877			h += vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
-878			maxH = utils.Max(maxH, h)
-879			(*state)[n.Children[i].Properties.Id] = vState
-880		}
-881		maxes = append(maxes, maxH)
-882		maxesTotal += maxH
-883	}
-884
-885	os := ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
-886	if os < 0 || content != "normal" {
-887		os = 0
-888	}
-889
-890	var contentOffset float32
-891
-892	if content == "center" {
-893		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / 2
-894	} else if content == "end" || content == "flex-end" {
-895		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal)
-896	} else if content == "start" || content == "flex-start" || content == "baseline" {
-897		// This is redundent but it helps keep track
-898		contentOffset = 0
-899	} else if content == "space-between" {
-900		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)-1)
-901	} else if content == "space-around" {
-902		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
-903		contentOffset = os / 2
-904	} else if content == "space-evenly" {
-905		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)+1)
-906		contentOffset = os
-907	}
-908
-909	for c, row := range rows {
-910		maxH := maxes[c]
-911		var sum float32
-912		for i := 0; i < c; i++ {
-913			sum += maxes[i]
-914		}
-915		if align == "start" || align == "flex-start" || align == "self-start" || align == "normal" {
-916			for i := row[0]; i < row[1]; i++ {
-917				vState := s[n.Children[i].Properties.Id]
-918
-919				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
-920
-921				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-922					offset += ((os) * float32(c))
-923				}
-924
-925				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-926				vState.Y = offset
-927				(*state)[n.Children[i].Properties.Id] = vState
-928			}
-929		} else if align == "center" {
-930			for i := row[0]; i < row[1]; i++ {
-931				vState := s[n.Children[i].Properties.Id]
-932
-933				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
-934
-935				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-936					offset += (os * float32(c+1)) - (os / 2)
-937				}
-938
-939				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
-940					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))) / 2
-941				}
-942				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-943				vState.Y = offset
-944				(*state)[n.Children[i].Properties.Id] = vState
-945			}
-946		} else if align == "end" || align == "flex-end" || align == "self-end" {
-947			for i := row[0]; i < row[1]; i++ {
-948				vState := s[n.Children[i].Properties.Id]
-949
-950				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
-951
-952				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-953					offset += os * float32(c+1)
-954				}
-955
-956				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
-957					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)))
-958				}
-959				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-960				vState.Y = offset
-961				(*state)[n.Children[i].Properties.Id] = vState
-962
-963			}
-964		} else if align == "stretch" {
-965			for i := row[0]; i < row[1]; i++ {
-966				vState := s[n.Children[i].Properties.Id]
-967
-968				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top
-969
-970				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-971					offset += ((os) * float32(c))
-972				}
-973
-974				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-975				vState.Y = offset
-976				vState.Height = maxH - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
-977				(*state)[n.Children[i].Properties.Id] = vState
-978
-979			}
-980		}
-981	}
-982}
+716		}
+717
+718	}
+719}
+720
+721func alignItemsRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
+722
+723}


    
        
        
        
        
        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	"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)
121
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					}
192
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)})
239					}
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 n.Style["height"] != "" || n.Style["min-height"] != "" {
270						h := selfHeight / float32(len(n.Children))
271						for i, v := range n.Children {
272							vState := s[v.Properties.Id]
273							yStore := vState.Y
274							adjH := h - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
275							if adjH < vState.Height {
276
277								if minHeights[i] > adjH {
278									vState.Height = minHeights[i]
279									if i > 0 {
280										sib := s[n.Children[i-1].Properties.Id]
281										vState.Y = sib.Y + sib.Height + sib.Margin.Bottom + sib.Border.Width + vState.Margin.Top + vState.Border.Width
282									}
283								} else {
284									vState.Height = adjH
285									vState.Y = self.Y + self.Padding.Top + self.Border.Width + (h * float32(i)) + vState.Margin.Top
286								}
287								propagateOffsets(&v, vState.X, yStore, vState.X, vState.Y, state)
288								(*state)[v.Properties.Id] = vState
289							}
290						}
291					}
292					for i, v := range n.Children {
293						vState := s[v.Properties.Id]
294						rows = append(rows, []int{i, i + 1, int(vState.Height)})
295					}
296
297				}
298				if flexReversed {
299					colReverse(n, state)
300				}
301			}
302			if n.Style["height"] == "" || n.Style["min-height"] == "" {
303				_, h := getInnerSize(n, state)
304				// fmt.Println(h)
305				self.Height = h
306			}
307			(*state)[n.Properties.Id] = self
308		},
309	}
310}
311
312func applyBlock(n *element.Node, state *map[string]element.State) {
313	if len(n.Children) > 0 {
314		accum := float32(0)
315		inlineOffset := float32(0)
316		s := *state
317		lastHeight := float32(0)
318		baseY := s[n.Children[0].Properties.Id].Y
319		for i := 0; i < len(n.Children); i++ {
320			v := &n.Children[i]
321			vState := s[v.Properties.Id]
322
323			if v.Style["display"] != "block" {
324				vState.Y += inlineOffset
325				accum = (vState.Y - baseY)
326				lastHeight = vState.Height
327			} else if v.Style["position"] != "absolute" {
328				vState.Y += accum
329				inlineOffset += (vState.Height + (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom) + lastHeight
330			}
331			(*state)[v.Properties.Id] = vState
332		}
333	}
334}
335
336func deInline(n *element.Node, state *map[string]element.State) {
337	s := *state
338	// self := s[n.Properties.Id]
339	baseX := float32(-1)
340	baseY := float32(-1)
341	for _, v := range n.Children {
342		vState := s[v.Properties.Id]
343
344		if v.Style["display"] == "inline" {
345			if baseX < 0 && baseY < 0 {
346				baseX = vState.X
347				baseY = vState.Y
348			} else {
349				vState.X = baseX
350				vState.Y = baseY
351				(*state)[v.Properties.Id] = vState
352
353			}
354		} else {
355			baseX = float32(-1)
356			baseY = float32(-1)
357		}
358
359		if len(v.Children) > 0 {
360			deInline(&v, state)
361		}
362	}
363
364}
365
366func applyInline(n *element.Node, state *map[string]element.State) {
367	pl := inline.Init()
368	for i := 0; i < len(n.Children); i++ {
369		v := &n.Children[i]
370
371		if len(v.Children) > 0 {
372			applyInline(v, state)
373		}
374
375		if pl.Selector(v) {
376			pl.Handler(v, state)
377		}
378	}
379}
380
381func propagateOffsets(n *element.Node, prevx, prevy, newx, newy float32, state *map[string]element.State) {
382	s := *state
383	for _, v := range n.Children {
384		vState := s[v.Properties.Id]
385		xStore := (vState.X - prevx) + newx
386		yStore := (vState.Y - prevy) + newy
387
388		if len(v.Children) > 0 {
389			propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
390		}
391		vState.X = xStore
392		vState.Y = yStore
393		(*state)[v.Properties.Id] = vState
394	}
395
396}
397
398func countText(n element.Node) int {
399	count := 0
400	groups := []int{}
401	for _, v := range n.Children {
402		if v.TagName == "notaspan" {
403			count += 1
404		}
405		if v.Style["display"] == "block" {
406			groups = append(groups, count)
407			count = 0
408		}
409		if len(v.Children) > 0 {
410			count += countText(v)
411		}
412	}
413	groups = append(groups, count)
414
415	sort.Slice(groups, func(i, j int) bool {
416		return groups[i] > groups[j]
417	})
418	return groups[0]
419}
420
421func minHeight(n element.Node, state *map[string]element.State, prev float32) float32 {
422	s := *state
423	self := s[n.Properties.Id]
424	if n.Style["min-height"] != "" {
425		mw := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
426		return utils.Max(prev, mw)
427	} else {
428		return prev
429	}
430
431}
432
433func getMinHeight(n *element.Node, state *map[string]element.State) float32 {
434	s := *state
435	self := s[n.Properties.Id]
436	selfHeight := float32(0)
437
438	if len(n.Children) > 0 {
439		for _, v := range n.Children {
440			selfHeight = utils.Max(selfHeight, getNodeHeight(&v, state))
441		}
442	} else {
443		selfHeight = self.Height
444	}
445	if n.Style["min-height"] != "" {
446		mh := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
447		selfHeight = utils.Max(mh, selfHeight)
448	}
449
450	selfHeight += self.Padding.Top + self.Padding.Bottom
451	return selfHeight
452}
453
454func getMinWidth(n *element.Node, state *map[string]element.State) float32 {
455	s := *state
456	self := s[n.Properties.Id]
457	selfWidth := float32(0)
458
459	if len(n.Children) > 0 {
460		for _, v := range n.Children {
461			selfWidth = utils.Max(selfWidth, getNodeWidth(&v, state))
462		}
463	} else {
464		selfWidth = self.Width
465	}
466	if n.Style["min-width"] != "" {
467		mw := utils.ConvertToPixels(n.Style["min-width"], self.EM, s[n.Parent.Properties.Id].Width)
468		selfWidth = utils.Max(mw, selfWidth)
469	}
470
471	selfWidth += self.Padding.Left + self.Padding.Right
472	return selfWidth
473}
474func getMaxWidth(n *element.Node, state *map[string]element.State) float32 {
475	s := *state
476	self := s[n.Properties.Id]
477	selfWidth := float32(0)
478
479	if len(n.Children) > 0 {
480		var maxRowWidth, rowWidth float32
481
482		for _, v := range n.Children {
483			rowWidth += getNodeWidth(&v, state)
484			if v.Style["display"] != "inline" {
485				maxRowWidth = utils.Max(rowWidth, maxRowWidth)
486				rowWidth = 0
487			}
488		}
489		selfWidth = utils.Max(rowWidth, maxRowWidth)
490	} else {
491		selfWidth = self.Width
492	}
493
494	selfWidth += self.Padding.Left + self.Padding.Right
495	return selfWidth
496}
497
498func getNodeWidth(n *element.Node, state *map[string]element.State) float32 {
499	s := *state
500	self := s[n.Properties.Id]
501	w := float32(0)
502	w += self.Padding.Left
503	w += self.Padding.Right
504
505	w += self.Margin.Left
506	w += self.Margin.Right
507
508	w += self.Width
509
510	w += self.Border.Width * 2
511
512	for _, v := range n.Children {
513		w = utils.Max(w, getNodeWidth(&v, state))
514	}
515
516	return w
517}
518func getMaxHeight(n *element.Node, state *map[string]element.State) float32 {
519	s := *state
520	self := s[n.Properties.Id]
521	selfHeight := float32(0)
522
523	if len(n.Children) > 0 {
524		var maxRowHeight, rowHeight float32
525
526		for _, v := range n.Children {
527			rowHeight += getNodeHeight(&v, state)
528			if v.Style["display"] != "inline" {
529				maxRowHeight = utils.Max(rowHeight, maxRowHeight)
530				rowHeight = 0
531			}
532		}
533		selfHeight = utils.Max(rowHeight, maxRowHeight)
534	} else {
535		selfHeight = self.Height
536	}
537
538	selfHeight += self.Padding.Top + self.Padding.Bottom
539	return selfHeight
540}
541
542func getNodeHeight(n *element.Node, state *map[string]element.State) float32 {
543	s := *state
544	self := s[n.Properties.Id]
545	h := float32(0)
546	h += self.Padding.Top
547	h += self.Padding.Bottom
548
549	h += self.Margin.Top
550	h += self.Margin.Bottom
551
552	h += self.Height
553
554	h += self.Border.Width * 2
555
556	for _, v := range n.Children {
557		h = utils.Max(h, getNodeHeight(&v, state))
558	}
559
560	return h
561}
562
563func getInnerSize(n *element.Node, state *map[string]element.State) (float32, float32) {
564	s := *state
565	self := s[n.Properties.Id]
566
567	minx := float32(10e10)
568	maxw := float32(0)
569	miny := float32(10e10)
570	maxh := float32(0)
571	for _, v := range n.Children {
572		vState := s[v.Properties.Id]
573		minx = utils.Min(vState.X, minx)
574		miny = utils.Min(vState.Y-vState.Margin.Top, miny)
575		// Don't add the top or left because the x&y values already take that into account
576		hOffset := (vState.Border.Width * 2) + vState.Margin.Bottom
577		wOffset := (vState.Border.Width * 2) + vState.Margin.Right
578		maxw = utils.Max(vState.X+vState.Width+wOffset, maxw)
579		maxh = utils.Max(vState.Y+vState.Height+hOffset, maxh)
580	}
581	w := maxw - minx
582	h := maxh - miny
583
584	w += self.Padding.Left + self.Padding.Right
585	h += self.Padding.Top + self.Padding.Bottom
586	if n.Style["width"] != "" {
587		w = self.Width
588	}
589	if n.Style["height"] != "" {
590		h = self.Height
591	}
592
593	return w, h
594}
595
596func add2d(arr [][]float32, index int) float32 {
597	var sum float32
598	if len(arr) == 0 {
599		return sum
600	}
601
602	for i := 0; i < len(arr); i++ {
603		if len(arr[i]) <= index {
604			return sum
605		}
606		sum += arr[i][index]
607	}
608
609	return sum
610}
611
612func colReverse(n *element.Node, state *map[string]element.State) {
613	s := *state
614	tempNodes := []element.Node{}
615	tempStates := []element.State{}
616	for i := len(n.Children) - 1; i >= 0; i-- {
617		tempNodes = append(tempNodes, n.Children[i])
618		tempStates = append(tempStates, s[n.Children[i].Properties.Id])
619	}
620
621	for i := 0; i < len(tempStates); i++ {
622		vState := s[n.Children[i].Properties.Id]
623		propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, tempStates[i].Y, state)
624		vState.Y = tempStates[i].Y
625		(*state)[n.Children[i].Properties.Id] = vState
626	}
627
628	n.Children = tempNodes
629}
630
631func rowReverse(rows [][]int, n *element.Node, state *map[string]element.State) {
632	s := *state
633	for _, row := range rows {
634		tempNodes := []element.Node{}
635		tempStates := []element.State{}
636
637		for i := row[1] - 1; i >= row[0]; i-- {
638			tempNodes = append(tempNodes, n.Children[i])
639			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
640		}
641
642		for i := 0; i < len(tempStates); i++ {
643			e := row[0] + i
644			vState := s[n.Children[e].Properties.Id]
645			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
646			vState.X = tempStates[i].X
647			(*state)[n.Children[e].Properties.Id] = vState
648		}
649		for i := 0; i < len(tempStates); i++ {
650			e := row[0] + i
651			n.Children[e] = tempNodes[i]
652		}
653
654		for i := row[1] - 1; i >= row[0]; i-- {
655			vState := s[n.Children[i].Properties.Id]
656			var xChng float32
657			if i < row[1]-1 {
658				sib := s[n.Children[i+1].Properties.Id]
659				xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
660			} else {
661				parent := s[n.Properties.Id]
662				xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
663
664			}
665			propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
666			vState.X = xChng
667			(*state)[n.Children[i].Properties.Id] = vState
668		}
669	}
670}
671
672func justifyRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
673	s := *state
674	for _, row := range rows {
675
676		if (justify == "flex-end" || justify == "end" || justify == "right") && !reversed {
677			for i := row[1] - 1; i >= row[0]; i-- {
678				vState := s[n.Children[i].Properties.Id]
679				var xChng float32
680				if i < row[1]-1 {
681					sib := s[n.Children[i+1].Properties.Id]
682					xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
683				} else {
684					parent := s[n.Properties.Id]
685					xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
686
687				}
688				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
689				vState.X = xChng
690				(*state)[n.Children[i].Properties.Id] = vState
691			}
692		} else if (justify == "flex-end" || justify == "start" || justify == "left" || justify == "normal") && reversed {
693			for i := row[0]; i < row[1]; i++ {
694				vState := s[n.Children[i].Properties.Id]
695				var xChng float32
696				if i > row[0] {
697					sib := s[n.Children[i-1].Properties.Id]
698					xChng = sib.X + sib.Width + (sib.Border.Width * 2) + sib.Margin.Right + vState.Margin.Left + vState.Border.Width
699				} else {
700					parent := s[n.Properties.Id]
701					xChng = parent.X + parent.Padding.Right + vState.Margin.Left + vState.Border.Width + parent.Border.Width
702
703				}
704				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
705				vState.X = xChng
706				(*state)[n.Children[i].Properties.Id] = vState
707			}
708		} else if justify == "center" {
709			// get width of row then center (by getting last x + w + mr + b)
710			f := s[n.Children[row[0]].Properties.Id]
711			l := s[n.Children[row[1]-1].Properties.Id]
712			parent := s[n.Properties.Id]
713			po := parent.X + parent.Border.Width
714			offset := (parent.Width - ((f.X - po) + (l.X - po) + l.Width + f.Border.Width + l.Border.Width)) / 2
715
716			for i := row[0]; i < row[1]; i++ {
717				vState := s[n.Children[i].Properties.Id]
718
719				if !reversed {
720					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
721					vState.X += offset
722				} else {
723					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
724					vState.X -= offset
725				}
726				(*state)[n.Children[i].Properties.Id] = vState
727			}
728
729		} else if justify == "space-between" {
730			// get width of row then center (by getting last x + w + mr + b)
731			f := s[n.Children[row[0]].Properties.Id]
732			l := s[n.Children[row[1]-1].Properties.Id]
733			parent := s[n.Properties.Id]
734			po := parent.Border.Width + parent.Width
735			po -= parent.Padding.Left + parent.Padding.Right
736
737			// make po repersent the total space between elements
738			for i := row[0]; i < row[1]; i++ {
739				vState := s[n.Children[i].Properties.Id]
740				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
741			}
742
743			po /= float32(((row[1]) - row[0]) - 1)
744
745			if (row[1]-1)-row[0] > 0 {
746				for i := row[0]; i < row[1]; i++ {
747					vState := s[n.Children[i].Properties.Id]
748					var offset float32
749					if i == row[0] {
750						offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
751					} else if i == row[1]-1 {
752						offset = (parent.X + parent.Width) - (l.Margin.Right + l.Border.Width + l.Width + parent.Padding.Right)
753					} else {
754						if !reversed {
755							offset = vState.X + (po * float32(i-row[0]))
756						} else {
757							offset = vState.X - (po * float32(((row[1]-1)-row[0])-(i-row[0])))
758						}
759
760					}
761
762					propagateOffsets(&n.Children[i], vState.X, vState.Y, offset, vState.Y, state)
763					vState.X = offset
764					(*state)[n.Children[i].Properties.Id] = vState
765				}
766			}
767			//  else {
768
769			// this is/was causing issues, removed and it fixed its self
770
771			// if there is one element move left
772			// vState := s[n.Children[(row[1]-1)-row[0]].Properties.Id]
773			// var offset float32
774
775			// if !reversed {
776			// 	offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
777			// 	propagateOffsets(&n.Children[(row[1]-1)-row[0]], vState.X, vState.Y, offset, vState.Y, state)
778			// 	vState.X = offset
779
780			// 	(*state)[n.Children[(row[1]-1)-row[0]].Properties.Id] = vState
781			// }
782
783			// }
784
785		} else if justify == "space-evenly" {
786			// get width of row then center (by getting last x + w + mr + b)
787			parent := s[n.Properties.Id]
788			po := parent.Border.Width + parent.Width
789			po -= parent.Padding.Left + parent.Padding.Right
790
791			// make po repersent the total space between elements
792			for i := row[0]; i < row[1]; i++ {
793				vState := s[n.Children[i].Properties.Id]
794				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
795			}
796
797			po /= float32(((row[1]) - row[0]) + 1)
798
799			// get width of row then center (by getting last x + w + mr + b)
800
801			for i := row[0]; i < row[1]; i++ {
802				vState := s[n.Children[i].Properties.Id]
803
804				if !reversed {
805					offset := po * (float32(i-row[0]) + 1)
806					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
807					vState.X += offset
808				} else {
809					offset := po * float32(((row[1]-1)-row[0])-((i-row[0])-1))
810
811					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
812					vState.X -= offset
813				}
814				(*state)[n.Children[i].Properties.Id] = vState
815			}
816
817		} else if justify == "space-around" {
818			// get width of row then center (by getting last x + w + mr + b)
819			parent := s[n.Properties.Id]
820			po := parent.Border.Width + parent.Width
821			po -= parent.Padding.Left + parent.Padding.Right
822
823			// make po repersent the total space between elements
824			for i := row[0]; i < row[1]; i++ {
825				vState := s[n.Children[i].Properties.Id]
826				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
827			}
828
829			po /= float32(((row[1]) - row[0]))
830
831			// get width of row then center (by getting last x + w + mr + b)
832
833			for i := row[0]; i < row[1]; i++ {
834				vState := s[n.Children[i].Properties.Id]
835
836				if !reversed {
837					m := (float32(i-row[0]) + 1)
838					if i-row[0] == 0 {
839						m = 0.5
840					} else {
841						m -= 0.5
842					}
843					offset := po * m
844					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
845					vState.X += offset
846				} else {
847					m := float32(((row[1] - 1) - row[0]) - ((i - row[0]) - 1))
848					m -= 0.5
849					offset := po * m
850
851					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
852					vState.X -= offset
853				}
854				(*state)[n.Children[i].Properties.Id] = vState
855			}
856
857		}
858
859	}
860}
861
862func alignRow(rows [][]int, n *element.Node, state *map[string]element.State, align, content string) {
863	// !ISSUE: Baseline isn't properly impleamented
864
865	s := *state
866	self := s[n.Properties.Id]
867
868	maxes := []float32{}
869	var maxesTotal float32
870	for _, row := range rows {
871		var maxH float32
872		for i := row[0]; i < row[1]; i++ {
873			vState := s[n.Children[i].Properties.Id]
874			_, h := getInnerSize(&n.Children[i], state)
875			h = minHeight(n.Children[i], state, h)
876			vState.Height = h
877			h += vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
878			maxH = utils.Max(maxH, h)
879			(*state)[n.Children[i].Properties.Id] = vState
880		}
881		maxes = append(maxes, maxH)
882		maxesTotal += maxH
883	}
884
885	os := ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
886	if os < 0 || content != "normal" {
887		os = 0
888	}
889
890	var contentOffset float32
891
892	if content == "center" {
893		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / 2
894	} else if content == "end" || content == "flex-end" {
895		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal)
896	} else if content == "start" || content == "flex-start" || content == "baseline" {
897		// This is redundent but it helps keep track
898		contentOffset = 0
899	} else if content == "space-between" {
900		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)-1)
901	} else if content == "space-around" {
902		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
903		contentOffset = os / 2
904	} else if content == "space-evenly" {
905		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)+1)
906		contentOffset = os
907	}
908
909	for c, row := range rows {
910		maxH := maxes[c]
911		var sum float32
912		for i := 0; i < c; i++ {
913			sum += maxes[i]
914		}
915		if align == "start" || align == "flex-start" || align == "self-start" || align == "normal" {
916			for i := row[0]; i < row[1]; i++ {
917				vState := s[n.Children[i].Properties.Id]
918
919				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
920
921				if n.Style["height"] != "" || n.Style["min-height"] != "" {
922					offset += ((os) * float32(c))
923				}
924
925				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
926				vState.Y = offset
927				(*state)[n.Children[i].Properties.Id] = vState
928			}
929		} else if align == "center" {
930			for i := row[0]; i < row[1]; i++ {
931				vState := s[n.Children[i].Properties.Id]
932
933				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
934
935				if n.Style["height"] != "" || n.Style["min-height"] != "" {
936					offset += (os * float32(c+1)) - (os / 2)
937				}
938
939				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
940					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))) / 2
941				}
942				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
943				vState.Y = offset
944				(*state)[n.Children[i].Properties.Id] = vState
945			}
946		} else if align == "end" || align == "flex-end" || align == "self-end" {
947			for i := row[0]; i < row[1]; i++ {
948				vState := s[n.Children[i].Properties.Id]
949
950				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
951
952				if n.Style["height"] != "" || n.Style["min-height"] != "" {
953					offset += os * float32(c+1)
954				}
955
956				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
957					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)))
958				}
959				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
960				vState.Y = offset
961				(*state)[n.Children[i].Properties.Id] = vState
962
963			}
964		} else if align == "stretch" {
965			for i := row[0]; i < row[1]; i++ {
966				vState := s[n.Children[i].Properties.Id]
967
968				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top
969
970				if n.Style["height"] != "" || n.Style["min-height"] != "" {
971					offset += ((os) * float32(c))
972				}
973
974				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
975				vState.Y = offset
976				vState.Height = maxH - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
977				(*state)[n.Children[i].Properties.Id] = vState
978
979			}
980		}
981	}
982}