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


    
        
        
        
        
        GRIM UI 
        
        
        
        
    
    
        
        

Flexbox

Flexbox is a high level positioning plugin that allows for dynamic positioning of elements based apon container sizing. To learn more about flexbox refer to this MDN article, in this document we will go into the impleamentation of flexbox rather than the usage of it.

"display": "flex", "justify-content": "*", "align-content": "*", "align-items": "*", "flex-wrap": "*", "flex-direction": "*",

# Flex Properties

justify-content align-content align-items flex-wrap flex-direction
normal normal normal nowrap row
center center center wrap column
flex-start flex-start flex-start row-reverse
flex-end flex-end flex-end column-reverse
space-between space-between stretch
space-around space-around baseline
space-evenly stretch

# order?(go)

asd

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