Author: LakeFox
Email: [email protected]
Date: Sat, 22 Jun 2024 18:12:21 -0600
docs/cstyle/plugins/flex/index.html
column & reverse justify-content
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 e00d24c..6e0cc04 100644
--- a/docs/cstyle/plugins/flex/index.html
+++ b/docs/cstyle/plugins/flex/index.html
@@ -369,12 +369,12 @@
- 270					var totalHeight, maxH float32
- 271					var fixedHeightElements int
- 272					for i, v := range n.Children {
- 273						vState := s[v.Properties.Id]
- 274						if v.Style["min-height"] != "" {
- 275							selfHeight -= vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
- 276							fixedHeightElements++
- 277							maxH = utils.Max(maxH, vState.Height)
- 278						} else {
- 279							// accoutn for element min height
- 280							totalHeight += minHeights[i] + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
- 281							maxH = utils.Max(maxH, minHeights[i])
+ 270					if n.Style["height"] != "" {
+ 271						var totalHeight float32
+ 272						var fixedHeightElements int
+ 273						for _, v := range n.Children {
+ 274							vState := s[v.Properties.Id]
+ 275							if v.Style["min-height"] != "" {
+ 276								selfHeight -= vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+ 277								fixedHeightElements++
+ 278							} else {
+ 279								// accoutn for element min height
+ 280								totalHeight += vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+ 281							}
@@ -382,29 +382,29 @@
- 283					}
- 284
- 285					heightDelta := selfHeight - totalHeight
- 286					if heightDelta < 0 {
- 287						heightDelta = -heightDelta
- 288					}
- 289					heightAdj := heightDelta / float32(len(n.Children)-fixedHeightElements)
- 290					if heightAdj < 0 {
- 291						heightAdj = -heightAdj
- 292					}
- 293					// We are calculating the amount a element needs to shrink because of its siblings
- 294					for i, v := range n.Children {
- 295						vState := s[v.Properties.Id]
- 296						yStore := vState.Y
- 297						if v.Style["min-height"] == "" {
- 298							vState.Height = minHeights[i] - heightAdj
- 299							if vState.Height < minHeights[i] {
- 300								vState.Height = minHeights[i]
- 301							}
- 302
- 303						}
- 304						if i > 0 {
- 305							sib := s[n.Children[i-1].Properties.Id]
- 306
- 307							vState.Y = sib.Y + sib.Height + sib.Margin.Bottom + sib.Border.Width + vState.Margin.Top + vState.Border.Width
- 308						}
- 309						propagateOffsets(&v, vState.X, yStore, vState.X, vState.Y, state)
- 310
- 311						(*state)[v.Properties.Id] = vState
+ 283
+ 284						heightDelta := selfHeight - totalHeight
+ 285						if heightDelta < 0 {
+ 286							heightDelta = -heightDelta
+ 287						}
+ 288						heightAdj := heightDelta / float32(len(n.Children)-fixedHeightElements)
+ 289						if heightAdj < 0 {
+ 290							heightAdj = -heightAdj
+ 291						}
+ 292						// We are calculating the amount a element needs to shrink because of its siblings
+ 293						for i, v := range n.Children {
+ 294							vState := s[v.Properties.Id]
+ 295							if v.Style["min-height"] == "" {
+ 296								vState.Height -= heightAdj
+ 297								yStore := vState.Y
+ 298								if vState.Height < minHeights[i] {
+ 299									vState.Height = minHeights[i]
+ 300								}
+ 301								if i > 0 {
+ 302									sib := s[n.Children[i-1].Properties.Id]
+ 303
+ 304									vState.Y = sib.Y + sib.Height + sib.Margin.Bottom + sib.Border.Width + vState.Margin.Top + vState.Border.Width
+ 305								}
+ 306								propagateOffsets(&v, vState.X, yStore, vState.X, vState.Y, state)
+ 307
+ 308								(*state)[v.Properties.Id] = vState
+ 309							}
+ 310						}
+ 311
@@ -412,41 +412,41 @@
- 313
- 314					rows = append(rows, []int{0, len(n.Children) - 1, int(maxH)})
- 315
- 316				} else {
- 317					var colHeight float32
- 318					var colIndex int
- 319					cols := [][][]float32{}
- 320
- 321					// Map elements to columns
- 322					for i, v := range n.Children {
- 323						vState := s[v.Properties.Id]
- 324
- 325						height := vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
- 326						if colHeight+height > selfHeight {
- 327							colHeight = height
- 328							colIndex++
- 329							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 330							if colIndex >= len(cols) {
- 331								cols = append(cols, [][]float32{})
- 332							}
- 333							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
- 334						} else {
- 335							colHeight += height
- 336							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 337							if colIndex >= len(cols) {
- 338								cols = append(cols, [][]float32{})
- 339							}
- 340							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
- 341						}
- 342					}
- 343
- 344					// Find the max total width of all columns
- 345					var totalMaxWidth float32
- 346					maxWidths := []float32{}
- 347					for _, col := range cols {
- 348						var maxWidth, maxHeight float32
- 349						for _, element := range col {
- 350							maxHeight = utils.Max(element[1], maxHeight)
- 351							maxWidth = utils.Max(element[2], maxWidth)
- 352						}
- 353						rows = append(rows, []int{int(col[0][0]), int(col[len(col)-1][0]), int(maxHeight)})
+ 313					for i, v := range n.Children {
+ 314						vState := s[v.Properties.Id]
+ 315						rows = append(rows, []int{i, i + 1, int(vState.Height)})
+ 316					}
+ 317
+ 318				} else {
+ 319					var colHeight float32
+ 320					var colIndex int
+ 321					cols := [][][]float32{}
+ 322
+ 323					// Map elements to columns
+ 324					for i, v := range n.Children {
+ 325						vState := s[v.Properties.Id]
+ 326
+ 327						height := vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+ 328						if colHeight+height > selfHeight {
+ 329							colHeight = height
+ 330							colIndex++
+ 331							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 332							if colIndex >= len(cols) {
+ 333								cols = append(cols, [][]float32{})
+ 334							}
+ 335							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
+ 336						} else {
+ 337							colHeight += height
+ 338							width := vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 339							if colIndex >= len(cols) {
+ 340								cols = append(cols, [][]float32{})
+ 341							}
+ 342							cols[colIndex] = append(cols[colIndex], []float32{float32(i), height, width})
+ 343						}
+ 344					}
+ 345
+ 346					// Find the max total width of all columns
+ 347					var totalMaxWidth float32
+ 348					maxWidths := []float32{}
+ 349					for _, col := range cols {
+ 350						var maxWidth float32
+ 351						for _, element := range col {
+ 352							maxWidth = utils.Max(element[2], maxWidth)
+ 353						}
@@ -477,113 +477,113 @@
- 378
- 379				if flexReversed {
- 380					colReverse(rows, n, state)
- 381				}
- 382
- 383				justifyCols(rows, n, state, justifyContent, flexReversed)
- 384			}
- 385			if n.Style["height"] == "" || n.Style["min-height"] == "" {
- 386				_, h := getInnerSize(n, state)
- 387				// fmt.Println(h)
- 388				self.Height = h
- 389			}
- 390			(*state)[n.Properties.Id] = self
- 391		},
- 392	}
- 393}
- 394
- 395func applyBlock(n *element.Node, state *map[string]element.State) {
- 396	if len(n.Children) > 0 {
- 397		accum := float32(0)
- 398		inlineOffset := float32(0)
- 399		s := *state
- 400		lastHeight := float32(0)
- 401		baseY := s[n.Children[0].Properties.Id].Y
- 402		for i := 0; i < len(n.Children); i++ {
- 403			v := &n.Children[i]
- 404			vState := s[v.Properties.Id]
- 405
- 406			if v.Style["display"] != "block" {
- 407				vState.Y += inlineOffset
- 408				accum = (vState.Y - baseY)
- 409				lastHeight = vState.Height
- 410			} else if v.Style["position"] != "absolute" {
- 411				vState.Y += accum
- 412				inlineOffset += (vState.Height + (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom) + lastHeight
- 413			}
- 414			(*state)[v.Properties.Id] = vState
- 415		}
- 416	}
- 417}
- 418
- 419func deInline(n *element.Node, state *map[string]element.State) {
- 420	s := *state
- 421	// self := s[n.Properties.Id]
- 422	baseX := float32(-1)
- 423	baseY := float32(-1)
- 424	for _, v := range n.Children {
- 425		vState := s[v.Properties.Id]
- 426
- 427		if v.Style["display"] == "inline" {
- 428			if baseX < 0 && baseY < 0 {
- 429				baseX = vState.X
- 430				baseY = vState.Y
- 431			} else {
- 432				vState.X = baseX
- 433				vState.Y = baseY
- 434				(*state)[v.Properties.Id] = vState
- 435
- 436			}
- 437		} else {
- 438			baseX = float32(-1)
- 439			baseY = float32(-1)
- 440		}
- 441
- 442		if len(v.Children) > 0 {
- 443			deInline(&v, state)
- 444		}
- 445	}
- 446
- 447}
- 448
- 449func applyInline(n *element.Node, state *map[string]element.State) {
- 450	pl := inline.Init()
- 451	for i := 0; i < len(n.Children); i++ {
- 452		v := &n.Children[i]
- 453
- 454		if len(v.Children) > 0 {
- 455			applyInline(v, state)
- 456		}
- 457
- 458		if pl.Selector(v) {
- 459			pl.Handler(v, state)
- 460		}
- 461	}
- 462}
- 463
- 464func propagateOffsets(n *element.Node, prevx, prevy, newx, newy float32, state *map[string]element.State) {
- 465	s := *state
- 466	for _, v := range n.Children {
- 467		vState := s[v.Properties.Id]
- 468		xStore := (vState.X - prevx) + newx
- 469		yStore := (vState.Y - prevy) + newy
- 470
- 471		if len(v.Children) > 0 {
- 472			propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
- 473		}
- 474		vState.X = xStore
- 475		vState.Y = yStore
- 476		(*state)[v.Properties.Id] = vState
- 477	}
- 478
- 479}
- 480
- 481func countText(n element.Node) int {
- 482	count := 0
- 483	groups := []int{}
- 484	for _, v := range n.Children {
- 485		if v.TagName == "notaspan" {
- 486			count += 1
- 487		}
- 488		if v.Style["display"] == "block" {
- 489			groups = append(groups, count)
- 490			count = 0
+ 378				if flexReversed {
+ 379					colReverse(n, state)
+ 380				}
+ 381			}
+ 382			if n.Style["height"] == "" || n.Style["min-height"] == "" {
+ 383				_, h := getInnerSize(n, state)
+ 384				// fmt.Println(h)
+ 385				self.Height = h
+ 386			}
+ 387			(*state)[n.Properties.Id] = self
+ 388		},
+ 389	}
+ 390}
+ 391
+ 392func applyBlock(n *element.Node, state *map[string]element.State) {
+ 393	if len(n.Children) > 0 {
+ 394		accum := float32(0)
+ 395		inlineOffset := float32(0)
+ 396		s := *state
+ 397		lastHeight := float32(0)
+ 398		baseY := s[n.Children[0].Properties.Id].Y
+ 399		for i := 0; i < len(n.Children); i++ {
+ 400			v := &n.Children[i]
+ 401			vState := s[v.Properties.Id]
+ 402
+ 403			if v.Style["display"] != "block" {
+ 404				vState.Y += inlineOffset
+ 405				accum = (vState.Y - baseY)
+ 406				lastHeight = vState.Height
+ 407			} else if v.Style["position"] != "absolute" {
+ 408				vState.Y += accum
+ 409				inlineOffset += (vState.Height + (vState.Border.Width * 2) + vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom) + lastHeight
+ 410			}
+ 411			(*state)[v.Properties.Id] = vState
+ 412		}
+ 413	}
+ 414}
+ 415
+ 416func deInline(n *element.Node, state *map[string]element.State) {
+ 417	s := *state
+ 418	// self := s[n.Properties.Id]
+ 419	baseX := float32(-1)
+ 420	baseY := float32(-1)
+ 421	for _, v := range n.Children {
+ 422		vState := s[v.Properties.Id]
+ 423
+ 424		if v.Style["display"] == "inline" {
+ 425			if baseX < 0 && baseY < 0 {
+ 426				baseX = vState.X
+ 427				baseY = vState.Y
+ 428			} else {
+ 429				vState.X = baseX
+ 430				vState.Y = baseY
+ 431				(*state)[v.Properties.Id] = vState
+ 432
+ 433			}
+ 434		} else {
+ 435			baseX = float32(-1)
+ 436			baseY = float32(-1)
+ 437		}
+ 438
+ 439		if len(v.Children) > 0 {
+ 440			deInline(&v, state)
+ 441		}
+ 442	}
+ 443
+ 444}
+ 445
+ 446func applyInline(n *element.Node, state *map[string]element.State) {
+ 447	pl := inline.Init()
+ 448	for i := 0; i < len(n.Children); i++ {
+ 449		v := &n.Children[i]
+ 450
+ 451		if len(v.Children) > 0 {
+ 452			applyInline(v, state)
+ 453		}
+ 454
+ 455		if pl.Selector(v) {
+ 456			pl.Handler(v, state)
+ 457		}
+ 458	}
+ 459}
+ 460
+ 461func propagateOffsets(n *element.Node, prevx, prevy, newx, newy float32, state *map[string]element.State) {
+ 462	s := *state
+ 463	for _, v := range n.Children {
+ 464		vState := s[v.Properties.Id]
+ 465		xStore := (vState.X - prevx) + newx
+ 466		yStore := (vState.Y - prevy) + newy
+ 467
+ 468		if len(v.Children) > 0 {
+ 469			propagateOffsets(&v, vState.X, vState.Y, xStore, yStore, state)
+ 470		}
+ 471		vState.X = xStore
+ 472		vState.Y = yStore
+ 473		(*state)[v.Properties.Id] = vState
+ 474	}
+ 475
+ 476}
+ 477
+ 478func countText(n element.Node) int {
+ 479	count := 0
+ 480	groups := []int{}
+ 481	for _, v := range n.Children {
+ 482		if v.TagName == "notaspan" {
+ 483			count += 1
+ 484		}
+ 485		if v.Style["display"] == "block" {
+ 486			groups = append(groups, count)
+ 487			count = 0
+ 488		}
+ 489		if len(v.Children) > 0 {
+ 490			count += countText(v)
@@ -591,69 +591,69 @@
- 492		if len(v.Children) > 0 {
- 493			count += countText(v)
- 494		}
- 495	}
- 496	groups = append(groups, count)
- 497
- 498	sort.Slice(groups, func(i, j int) bool {
- 499		return groups[i] > groups[j]
- 500	})
- 501	return groups[0]
- 502}
- 503
- 504func minHeight(n element.Node, state *map[string]element.State, prev float32) float32 {
- 505	s := *state
- 506	self := s[n.Properties.Id]
- 507	if n.Style["min-height"] != "" {
- 508		mw := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
- 509		return utils.Max(prev, mw)
- 510	} else {
- 511		return prev
- 512	}
- 513
- 514}
- 515
- 516func getMinHeight(n *element.Node, state *map[string]element.State) float32 {
- 517	s := *state
- 518	self := s[n.Properties.Id]
- 519	selfHeight := float32(0)
- 520
- 521	if len(n.Children) > 0 {
- 522		for _, v := range n.Children {
- 523			selfHeight = utils.Max(selfHeight, getNodeHeight(&v, state))
- 524		}
- 525	} else {
- 526		selfHeight = self.Height
- 527	}
- 528	if n.Style["min-height"] != "" {
- 529		mh := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
- 530		selfHeight = utils.Max(mh, selfHeight)
- 531	}
- 532
- 533	selfHeight += self.Padding.Top + self.Padding.Bottom
- 534	return selfHeight
- 535}
- 536
- 537func getMinWidth(n *element.Node, state *map[string]element.State) float32 {
- 538	s := *state
- 539	self := s[n.Properties.Id]
- 540	selfWidth := float32(0)
- 541
- 542	if len(n.Children) > 0 {
- 543		for _, v := range n.Children {
- 544			selfWidth = utils.Max(selfWidth, getNodeWidth(&v, state))
- 545		}
- 546	} else {
- 547		selfWidth = self.Width
- 548	}
- 549	if n.Style["min-width"] != "" {
- 550		mw := utils.ConvertToPixels(n.Style["min-width"], self.EM, s[n.Parent.Properties.Id].Width)
- 551		selfWidth = utils.Max(mw, selfWidth)
- 552	}
- 553
- 554	selfWidth += self.Padding.Left + self.Padding.Right
- 555	return selfWidth
- 556}
- 557func getMaxWidth(n *element.Node, state *map[string]element.State) float32 {
- 558	s := *state
- 559	self := s[n.Properties.Id]
- 560	selfWidth := float32(0)
+ 492	}
+ 493	groups = append(groups, count)
+ 494
+ 495	sort.Slice(groups, func(i, j int) bool {
+ 496		return groups[i] > groups[j]
+ 497	})
+ 498	return groups[0]
+ 499}
+ 500
+ 501func minHeight(n element.Node, state *map[string]element.State, prev float32) float32 {
+ 502	s := *state
+ 503	self := s[n.Properties.Id]
+ 504	if n.Style["min-height"] != "" {
+ 505		mw := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
+ 506		return utils.Max(prev, mw)
+ 507	} else {
+ 508		return prev
+ 509	}
+ 510
+ 511}
+ 512
+ 513func getMinHeight(n *element.Node, state *map[string]element.State) float32 {
+ 514	s := *state
+ 515	self := s[n.Properties.Id]
+ 516	selfHeight := float32(0)
+ 517
+ 518	if len(n.Children) > 0 {
+ 519		for _, v := range n.Children {
+ 520			selfHeight = utils.Max(selfHeight, getNodeHeight(&v, state))
+ 521		}
+ 522	} else {
+ 523		selfHeight = self.Height
+ 524	}
+ 525	if n.Style["min-height"] != "" {
+ 526		mh := utils.ConvertToPixels(n.Style["min-height"], self.EM, s[n.Parent.Properties.Id].Width)
+ 527		selfHeight = utils.Max(mh, selfHeight)
+ 528	}
+ 529
+ 530	selfHeight += self.Padding.Top + self.Padding.Bottom
+ 531	return selfHeight
+ 532}
+ 533
+ 534func getMinWidth(n *element.Node, state *map[string]element.State) float32 {
+ 535	s := *state
+ 536	self := s[n.Properties.Id]
+ 537	selfWidth := float32(0)
+ 538
+ 539	if len(n.Children) > 0 {
+ 540		for _, v := range n.Children {
+ 541			selfWidth = utils.Max(selfWidth, getNodeWidth(&v, state))
+ 542		}
+ 543	} else {
+ 544		selfWidth = self.Width
+ 545	}
+ 546	if n.Style["min-width"] != "" {
+ 547		mw := utils.ConvertToPixels(n.Style["min-width"], self.EM, s[n.Parent.Properties.Id].Width)
+ 548		selfWidth = utils.Max(mw, selfWidth)
+ 549	}
+ 550
+ 551	selfWidth += self.Padding.Left + self.Padding.Right
+ 552	return selfWidth
+ 553}
+ 554func getMaxWidth(n *element.Node, state *map[string]element.State) float32 {
+ 555	s := *state
+ 556	self := s[n.Properties.Id]
+ 557	selfWidth := float32(0)
+ 558
+ 559	if len(n.Children) > 0 {
+ 560		var maxRowWidth, rowWidth float32
@@ -661,25 +661,25 @@
- 562	if len(n.Children) > 0 {
- 563		var maxRowWidth, rowWidth float32
- 564
- 565		for _, v := range n.Children {
- 566			rowWidth += getNodeWidth(&v, state)
- 567			if v.Style["display"] != "inline" {
- 568				maxRowWidth = utils.Max(rowWidth, maxRowWidth)
- 569				rowWidth = 0
- 570			}
- 571		}
- 572		selfWidth = utils.Max(rowWidth, maxRowWidth)
- 573	} else {
- 574		selfWidth = self.Width
- 575	}
- 576
- 577	selfWidth += self.Padding.Left + self.Padding.Right
- 578	return selfWidth
- 579}
- 580
- 581func getNodeWidth(n *element.Node, state *map[string]element.State) float32 {
- 582	s := *state
- 583	self := s[n.Properties.Id]
- 584	w := float32(0)
- 585	w += self.Padding.Left
- 586	w += self.Padding.Right
+ 562		for _, v := range n.Children {
+ 563			rowWidth += getNodeWidth(&v, state)
+ 564			if v.Style["display"] != "inline" {
+ 565				maxRowWidth = utils.Max(rowWidth, maxRowWidth)
+ 566				rowWidth = 0
+ 567			}
+ 568		}
+ 569		selfWidth = utils.Max(rowWidth, maxRowWidth)
+ 570	} else {
+ 571		selfWidth = self.Width
+ 572	}
+ 573
+ 574	selfWidth += self.Padding.Left + self.Padding.Right
+ 575	return selfWidth
+ 576}
+ 577
+ 578func getNodeWidth(n *element.Node, state *map[string]element.State) float32 {
+ 579	s := *state
+ 580	self := s[n.Properties.Id]
+ 581	w := float32(0)
+ 582	w += self.Padding.Left
+ 583	w += self.Padding.Right
+ 584
+ 585	w += self.Margin.Left
+ 586	w += self.Margin.Right
@@ -687,17 +687,17 @@
- 588	w += self.Margin.Left
- 589	w += self.Margin.Right
- 590
- 591	w += self.Width
- 592
- 593	w += self.Border.Width * 2
- 594
- 595	for _, v := range n.Children {
- 596		w = utils.Max(w, getNodeWidth(&v, state))
- 597	}
- 598
- 599	return w
- 600}
- 601func getMaxHeight(n *element.Node, state *map[string]element.State) float32 {
- 602	s := *state
- 603	self := s[n.Properties.Id]
- 604	selfHeight := float32(0)
+ 588	w += self.Width
+ 589
+ 590	w += self.Border.Width * 2
+ 591
+ 592	for _, v := range n.Children {
+ 593		w = utils.Max(w, getNodeWidth(&v, state))
+ 594	}
+ 595
+ 596	return w
+ 597}
+ 598func getMaxHeight(n *element.Node, state *map[string]element.State) float32 {
+ 599	s := *state
+ 600	self := s[n.Properties.Id]
+ 601	selfHeight := float32(0)
+ 602
+ 603	if len(n.Children) > 0 {
+ 604		var maxRowHeight, rowHeight float32
@@ -705,25 +705,25 @@
- 606	if len(n.Children) > 0 {
- 607		var maxRowHeight, rowHeight float32
- 608
- 609		for _, v := range n.Children {
- 610			rowHeight += getNodeHeight(&v, state)
- 611			if v.Style["display"] != "inline" {
- 612				maxRowHeight = utils.Max(rowHeight, maxRowHeight)
- 613				rowHeight = 0
- 614			}
- 615		}
- 616		selfHeight = utils.Max(rowHeight, maxRowHeight)
- 617	} else {
- 618		selfHeight = self.Height
- 619	}
- 620
- 621	selfHeight += self.Padding.Top + self.Padding.Bottom
- 622	return selfHeight
- 623}
- 624
- 625func getNodeHeight(n *element.Node, state *map[string]element.State) float32 {
- 626	s := *state
- 627	self := s[n.Properties.Id]
- 628	h := float32(0)
- 629	h += self.Padding.Top
- 630	h += self.Padding.Bottom
+ 606		for _, v := range n.Children {
+ 607			rowHeight += getNodeHeight(&v, state)
+ 608			if v.Style["display"] != "inline" {
+ 609				maxRowHeight = utils.Max(rowHeight, maxRowHeight)
+ 610				rowHeight = 0
+ 611			}
+ 612		}
+ 613		selfHeight = utils.Max(rowHeight, maxRowHeight)
+ 614	} else {
+ 615		selfHeight = self.Height
+ 616	}
+ 617
+ 618	selfHeight += self.Padding.Top + self.Padding.Bottom
+ 619	return selfHeight
+ 620}
+ 621
+ 622func getNodeHeight(n *element.Node, state *map[string]element.State) float32 {
+ 623	s := *state
+ 624	self := s[n.Properties.Id]
+ 625	h := float32(0)
+ 626	h += self.Padding.Top
+ 627	h += self.Padding.Bottom
+ 628
+ 629	h += self.Margin.Top
+ 630	h += self.Margin.Bottom
@@ -731,10 +731,10 @@
- 632	h += self.Margin.Top
- 633	h += self.Margin.Bottom
- 634
- 635	h += self.Height
- 636
- 637	h += self.Border.Width * 2
- 638
- 639	for _, v := range n.Children {
- 640		h = utils.Max(h, getNodeHeight(&v, state))
- 641	}
+ 632	h += self.Height
+ 633
+ 634	h += self.Border.Width * 2
+ 635
+ 636	for _, v := range n.Children {
+ 637		h = utils.Max(h, getNodeHeight(&v, state))
+ 638	}
+ 639
+ 640	return h
+ 641}
@@ -742,28 +742,28 @@
- 643	return h
- 644}
- 645
- 646func getInnerSize(n *element.Node, state *map[string]element.State) (float32, float32) {
- 647	s := *state
- 648	self := s[n.Properties.Id]
- 649
- 650	minx := float32(10e10)
- 651	maxw := float32(0)
- 652	miny := float32(10e10)
- 653	maxh := float32(0)
- 654	for _, v := range n.Children {
- 655		vState := s[v.Properties.Id]
- 656		minx = utils.Min(vState.X, minx)
- 657		miny = utils.Min(vState.Y-vState.Margin.Top, miny)
- 658		// Don't add the top or left because the x&y values already take that into account
- 659		hOffset := (vState.Border.Width * 2) + vState.Margin.Bottom
- 660		wOffset := (vState.Border.Width * 2) + vState.Margin.Right
- 661		maxw = utils.Max(vState.X+vState.Width+wOffset, maxw)
- 662		maxh = utils.Max(vState.Y+vState.Height+hOffset, maxh)
- 663	}
- 664	w := maxw - minx
- 665	h := maxh - miny
- 666
- 667	w += self.Padding.Left + self.Padding.Right
- 668	h += self.Padding.Top + self.Padding.Bottom
- 669	if n.Style["width"] != "" {
- 670		w = self.Width
+ 643func getInnerSize(n *element.Node, state *map[string]element.State) (float32, float32) {
+ 644	s := *state
+ 645	self := s[n.Properties.Id]
+ 646
+ 647	minx := float32(10e10)
+ 648	maxw := float32(0)
+ 649	miny := float32(10e10)
+ 650	maxh := float32(0)
+ 651	for _, v := range n.Children {
+ 652		vState := s[v.Properties.Id]
+ 653		minx = utils.Min(vState.X, minx)
+ 654		miny = utils.Min(vState.Y-vState.Margin.Top, miny)
+ 655		// Don't add the top or left because the x&y values already take that into account
+ 656		hOffset := (vState.Border.Width * 2) + vState.Margin.Bottom
+ 657		wOffset := (vState.Border.Width * 2) + vState.Margin.Right
+ 658		maxw = utils.Max(vState.X+vState.Width+wOffset, maxw)
+ 659		maxh = utils.Max(vState.Y+vState.Height+hOffset, maxh)
+ 660	}
+ 661	w := maxw - minx
+ 662	h := maxh - miny
+ 663
+ 664	w += self.Padding.Left + self.Padding.Right
+ 665	h += self.Padding.Top + self.Padding.Bottom
+ 666	if n.Style["width"] != "" {
+ 667		w = self.Width
+ 668	}
+ 669	if n.Style["height"] != "" {
+ 670		h = self.Height
@@ -771,3 +771,3 @@
- 672	if n.Style["height"] != "" {
- 673		h = self.Height
- 674	}
+ 672
+ 673	return w, h
+ 674}
@@ -775,15 +775,15 @@
- 676	return w, h
- 677}
- 678
- 679func add2d(arr [][]float32, index int) float32 {
- 680	var sum float32
- 681	if len(arr) == 0 {
- 682		return sum
- 683	}
- 684
- 685	for i := 0; i < len(arr); i++ {
- 686		if len(arr[i]) <= index {
- 687			return sum
- 688		}
- 689		sum += arr[i][index]
- 690	}
+ 676func add2d(arr [][]float32, index int) float32 {
+ 677	var sum float32
+ 678	if len(arr) == 0 {
+ 679		return sum
+ 680	}
+ 681
+ 682	for i := 0; i < len(arr); i++ {
+ 683		if len(arr[i]) <= index {
+ 684			return sum
+ 685		}
+ 686		sum += arr[i][index]
+ 687	}
+ 688
+ 689	return sum
+ 690}
@@ -791,8 +791,8 @@
- 692	return sum
- 693}
- 694
- 695func colReverse(cols [][]int, n *element.Node, state *map[string]element.State) {
- 696	s := *state
- 697	for _, col := range cols {
- 698		tempNodes := []element.Node{}
- 699		tempStates := []element.State{}
+ 692func colReverse(n *element.Node, state *map[string]element.State) {
+ 693	s := *state
+ 694	tempNodes := []element.Node{}
+ 695	tempStates := []element.State{}
+ 696	for i := len(n.Children) - 1; i >= 0; i-- {
+ 697		tempNodes = append(tempNodes, n.Children[i])
+ 698		tempStates = append(tempStates, s[n.Children[i].Properties.Id])
+ 699	}
@@ -800,121 +800,121 @@
- 701		for i := col[1]; i >= col[0]; i-- {
- 702			tempNodes = append(tempNodes, n.Children[i])
- 703			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
- 704		}
- 705
- 706		for i := 0; i < len(tempStates); i++ {
- 707			e := col[0] + i
- 708			vState := s[n.Children[e].Properties.Id]
- 709			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
- 710			vState.Y = tempStates[i].Y
- 711			(*state)[n.Children[e].Properties.Id] = vState
- 712		}
- 713		for i := 0; i < len(tempStates); i++ {
- 714			e := col[0] + i
- 715			n.Children[e] = tempNodes[i]
- 716		}
- 717
- 718		for i := col[1]; i >= col[0]; i-- {
- 719			vState := s[n.Children[i].Properties.Id]
- 720			var yChng float32
- 721			if i < col[1] {
- 722				sib := s[n.Children[i+1].Properties.Id]
- 723				yChng = sib.Y - (sib.Border.Width + sib.Margin.Top + vState.Margin.Bottom + vState.Border.Width + vState.Height)
- 724			} else {
- 725				parent := s[n.Properties.Id]
- 726				yChng = ((((parent.Y + parent.Height) - parent.Padding.Bottom) - vState.Height) - vState.Margin.Bottom) - (vState.Border.Width)
- 727			}
- 728			propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, yChng, state)
- 729			vState.Y = yChng
- 730			(*state)[n.Children[i].Properties.Id] = vState
- 731		}
- 732	}
- 733}
- 734
- 735func rowReverse(rows [][]int, n *element.Node, state *map[string]element.State) {
- 736	s := *state
- 737	for _, row := range rows {
- 738		tempNodes := []element.Node{}
- 739		tempStates := []element.State{}
- 740
- 741		for i := row[1] - 1; i >= row[0]; i-- {
- 742			tempNodes = append(tempNodes, n.Children[i])
- 743			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
- 744		}
- 745
- 746		for i := 0; i < len(tempStates); i++ {
- 747			e := row[0] + i
- 748			vState := s[n.Children[e].Properties.Id]
- 749			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
- 750			vState.X = tempStates[i].X
- 751			(*state)[n.Children[e].Properties.Id] = vState
- 752		}
- 753		for i := 0; i < len(tempStates); i++ {
- 754			e := row[0] + i
- 755			n.Children[e] = tempNodes[i]
- 756		}
- 757
- 758		for i := row[1] - 1; i >= row[0]; i-- {
- 759			vState := s[n.Children[i].Properties.Id]
- 760			var xChng float32
- 761			if i < row[1]-1 {
- 762				sib := s[n.Children[i+1].Properties.Id]
- 763				xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
- 764			} else {
- 765				parent := s[n.Properties.Id]
- 766				xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
- 767
- 768			}
- 769			propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
- 770			vState.X = xChng
- 771			(*state)[n.Children[i].Properties.Id] = vState
- 772		}
- 773	}
- 774}
- 775
- 776func justifyRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
- 777	s := *state
- 778	for _, row := range rows {
- 779
- 780		if (justify == "flex-end" || justify == "end" || justify == "right") && !reversed {
- 781			for i := row[1] - 1; i >= row[0]; i-- {
- 782				vState := s[n.Children[i].Properties.Id]
- 783				var xChng float32
- 784				if i < row[1]-1 {
- 785					sib := s[n.Children[i+1].Properties.Id]
- 786					xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
- 787				} else {
- 788					parent := s[n.Properties.Id]
- 789					xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
- 790
- 791				}
- 792				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
- 793				vState.X = xChng
- 794				(*state)[n.Children[i].Properties.Id] = vState
- 795			}
- 796		} else if (justify == "flex-end" || justify == "start" || justify == "left" || justify == "normal") && reversed {
- 797			for i := row[0]; i < row[1]; i++ {
- 798				vState := s[n.Children[i].Properties.Id]
- 799				var xChng float32
- 800				if i > row[0] {
- 801					sib := s[n.Children[i-1].Properties.Id]
- 802					xChng = sib.X + sib.Width + (sib.Border.Width * 2) + sib.Margin.Right + vState.Margin.Left + vState.Border.Width
- 803				} else {
- 804					parent := s[n.Properties.Id]
- 805					xChng = parent.X + parent.Padding.Right + vState.Margin.Left + vState.Border.Width + parent.Border.Width
- 806
- 807				}
- 808				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
- 809				vState.X = xChng
- 810				(*state)[n.Children[i].Properties.Id] = vState
- 811			}
- 812		} else if justify == "center" {
- 813			// get width of row then center (by getting last x + w + mr + b)
- 814			f := s[n.Children[row[0]].Properties.Id]
- 815			l := s[n.Children[row[1]-1].Properties.Id]
- 816			parent := s[n.Properties.Id]
- 817			po := parent.X + parent.Border.Width
- 818			offset := (parent.Width - ((f.X - po) + (l.X - po) + l.Width + f.Border.Width + l.Border.Width)) / 2
- 819
- 820			for i := row[0]; i < row[1]; i++ {
- 821				vState := s[n.Children[i].Properties.Id]
+ 701	for i := 0; i < len(tempStates); i++ {
+ 702		vState := s[n.Children[i].Properties.Id]
+ 703		propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, tempStates[i].Y, state)
+ 704		vState.Y = tempStates[i].Y
+ 705		(*state)[n.Children[i].Properties.Id] = vState
+ 706	}
+ 707
+ 708	n.Children = tempNodes
+ 709}
+ 710
+ 711func rowReverse(rows [][]int, n *element.Node, state *map[string]element.State) {
+ 712	s := *state
+ 713	for _, row := range rows {
+ 714		tempNodes := []element.Node{}
+ 715		tempStates := []element.State{}
+ 716
+ 717		for i := row[1] - 1; i >= row[0]; i-- {
+ 718			tempNodes = append(tempNodes, n.Children[i])
+ 719			tempStates = append(tempStates, s[n.Children[i].Properties.Id])
+ 720		}
+ 721
+ 722		for i := 0; i < len(tempStates); i++ {
+ 723			e := row[0] + i
+ 724			vState := s[n.Children[e].Properties.Id]
+ 725			propagateOffsets(&n.Children[e], vState.X, vState.Y, tempStates[i].X, tempStates[i].Y, state)
+ 726			vState.X = tempStates[i].X
+ 727			(*state)[n.Children[e].Properties.Id] = vState
+ 728		}
+ 729		for i := 0; i < len(tempStates); i++ {
+ 730			e := row[0] + i
+ 731			n.Children[e] = tempNodes[i]
+ 732		}
+ 733
+ 734		for i := row[1] - 1; i >= row[0]; i-- {
+ 735			vState := s[n.Children[i].Properties.Id]
+ 736			var xChng float32
+ 737			if i < row[1]-1 {
+ 738				sib := s[n.Children[i+1].Properties.Id]
+ 739				xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
+ 740			} else {
+ 741				parent := s[n.Properties.Id]
+ 742				xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
+ 743
+ 744			}
+ 745			propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+ 746			vState.X = xChng
+ 747			(*state)[n.Children[i].Properties.Id] = vState
+ 748		}
+ 749	}
+ 750}
+ 751
+ 752func justifyRow(rows [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
+ 753	s := *state
+ 754	for _, row := range rows {
+ 755
+ 756		if (justify == "flex-end" || justify == "end" || justify == "right") && !reversed {
+ 757			for i := row[1] - 1; i >= row[0]; i-- {
+ 758				vState := s[n.Children[i].Properties.Id]
+ 759				var xChng float32
+ 760				if i < row[1]-1 {
+ 761					sib := s[n.Children[i+1].Properties.Id]
+ 762					xChng = sib.X - (sib.Border.Width + sib.Margin.Left + vState.Margin.Right + vState.Border.Width + vState.Width)
+ 763				} else {
+ 764					parent := s[n.Properties.Id]
+ 765					xChng = ((((parent.X + parent.Width) - parent.Padding.Right) - vState.Width) - vState.Margin.Right) - (vState.Border.Width)
+ 766
+ 767				}
+ 768				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+ 769				vState.X = xChng
+ 770				(*state)[n.Children[i].Properties.Id] = vState
+ 771			}
+ 772		} else if (justify == "flex-end" || justify == "start" || justify == "left" || justify == "normal") && reversed {
+ 773			for i := row[0]; i < row[1]; i++ {
+ 774				vState := s[n.Children[i].Properties.Id]
+ 775				var xChng float32
+ 776				if i > row[0] {
+ 777					sib := s[n.Children[i-1].Properties.Id]
+ 778					xChng = sib.X + sib.Width + (sib.Border.Width * 2) + sib.Margin.Right + vState.Margin.Left + vState.Border.Width
+ 779				} else {
+ 780					parent := s[n.Properties.Id]
+ 781					xChng = parent.X + parent.Padding.Right + vState.Margin.Left + vState.Border.Width + parent.Border.Width
+ 782
+ 783				}
+ 784				propagateOffsets(&n.Children[i], vState.X, vState.Y, xChng, vState.Y, state)
+ 785				vState.X = xChng
+ 786				(*state)[n.Children[i].Properties.Id] = vState
+ 787			}
+ 788		} else if justify == "center" {
+ 789			// get width of row then center (by getting last x + w + mr + b)
+ 790			f := s[n.Children[row[0]].Properties.Id]
+ 791			l := s[n.Children[row[1]-1].Properties.Id]
+ 792			parent := s[n.Properties.Id]
+ 793			po := parent.X + parent.Border.Width
+ 794			offset := (parent.Width - ((f.X - po) + (l.X - po) + l.Width + f.Border.Width + l.Border.Width)) / 2
+ 795
+ 796			for i := row[0]; i < row[1]; i++ {
+ 797				vState := s[n.Children[i].Properties.Id]
+ 798
+ 799				if !reversed {
+ 800					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+ 801					vState.X += offset
+ 802				} else {
+ 803					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+ 804					vState.X -= offset
+ 805				}
+ 806				(*state)[n.Children[i].Properties.Id] = vState
+ 807			}
+ 808
+ 809		} else if justify == "space-between" {
+ 810			// get width of row then center (by getting last x + w + mr + b)
+ 811			f := s[n.Children[row[0]].Properties.Id]
+ 812			l := s[n.Children[row[1]-1].Properties.Id]
+ 813			parent := s[n.Properties.Id]
+ 814			po := parent.Border.Width + parent.Width
+ 815			po -= parent.Padding.Left + parent.Padding.Right
+ 816
+ 817			// make po repersent the total space between elements
+ 818			for i := row[0]; i < row[1]; i++ {
+ 819				vState := s[n.Children[i].Properties.Id]
+ 820				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 821			}
@@ -922,79 +922,79 @@
- 823				if !reversed {
- 824					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
- 825					vState.X += offset
- 826				} else {
- 827					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
- 828					vState.X -= offset
- 829				}
- 830				(*state)[n.Children[i].Properties.Id] = vState
- 831			}
- 832
- 833		} else if justify == "space-between" {
- 834			// get width of row then center (by getting last x + w + mr + b)
- 835			f := s[n.Children[row[0]].Properties.Id]
- 836			l := s[n.Children[row[1]-1].Properties.Id]
- 837			parent := s[n.Properties.Id]
- 838			po := parent.Border.Width + parent.Width
- 839			po -= parent.Padding.Left + parent.Padding.Right
- 840
- 841			// make po repersent the total space between elements
- 842			for i := row[0]; i < row[1]; i++ {
- 843				vState := s[n.Children[i].Properties.Id]
- 844				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 845			}
- 846
- 847			po /= float32(((row[1]) - row[0]) - 1)
- 848
- 849			if (row[1]-1)-row[0] > 0 {
- 850				for i := row[0]; i < row[1]; i++ {
- 851					vState := s[n.Children[i].Properties.Id]
- 852					var offset float32
- 853					if i == row[0] {
- 854						offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
- 855					} else if i == row[1]-1 {
- 856						offset = (parent.X + parent.Width) - (l.Margin.Right + l.Border.Width + l.Width + parent.Padding.Right)
- 857					} else {
- 858						if !reversed {
- 859							offset = vState.X + (po * float32(i-row[0]))
- 860						} else {
- 861							offset = vState.X - (po * float32(((row[1]-1)-row[0])-(i-row[0])))
- 862						}
- 863
- 864					}
- 865
- 866					propagateOffsets(&n.Children[i], vState.X, vState.Y, offset, vState.Y, state)
- 867					vState.X = offset
- 868					(*state)[n.Children[i].Properties.Id] = vState
- 869				}
- 870			}
- 871			//  else {
- 872
- 873			// this is/was causing issues, removed and it fixed its self
- 874
- 875			// if there is one element move left
- 876			// vState := s[n.Children[(row[1]-1)-row[0]].Properties.Id]
- 877			// var offset float32
- 878
- 879			// if !reversed {
- 880			// 	offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
- 881			// 	propagateOffsets(&n.Children[(row[1]-1)-row[0]], vState.X, vState.Y, offset, vState.Y, state)
- 882			// 	vState.X = offset
- 883
- 884			// 	(*state)[n.Children[(row[1]-1)-row[0]].Properties.Id] = vState
- 885			// }
- 886
- 887			// }
- 888
- 889		} else if justify == "space-evenly" {
- 890			// get width of row then center (by getting last x + w + mr + b)
- 891			parent := s[n.Properties.Id]
- 892			po := parent.Border.Width + parent.Width
- 893			po -= parent.Padding.Left + parent.Padding.Right
- 894
- 895			// make po repersent the total space between elements
- 896			for i := row[0]; i < row[1]; i++ {
- 897				vState := s[n.Children[i].Properties.Id]
- 898				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 899			}
- 900
- 901			po /= float32(((row[1]) - row[0]) + 1)
+ 823			po /= float32(((row[1]) - row[0]) - 1)
+ 824
+ 825			if (row[1]-1)-row[0] > 0 {
+ 826				for i := row[0]; i < row[1]; i++ {
+ 827					vState := s[n.Children[i].Properties.Id]
+ 828					var offset float32
+ 829					if i == row[0] {
+ 830						offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
+ 831					} else if i == row[1]-1 {
+ 832						offset = (parent.X + parent.Width) - (l.Margin.Right + l.Border.Width + l.Width + parent.Padding.Right)
+ 833					} else {
+ 834						if !reversed {
+ 835							offset = vState.X + (po * float32(i-row[0]))
+ 836						} else {
+ 837							offset = vState.X - (po * float32(((row[1]-1)-row[0])-(i-row[0])))
+ 838						}
+ 839
+ 840					}
+ 841
+ 842					propagateOffsets(&n.Children[i], vState.X, vState.Y, offset, vState.Y, state)
+ 843					vState.X = offset
+ 844					(*state)[n.Children[i].Properties.Id] = vState
+ 845				}
+ 846			}
+ 847			//  else {
+ 848
+ 849			// this is/was causing issues, removed and it fixed its self
+ 850
+ 851			// if there is one element move left
+ 852			// vState := s[n.Children[(row[1]-1)-row[0]].Properties.Id]
+ 853			// var offset float32
+ 854
+ 855			// if !reversed {
+ 856			// 	offset = parent.X + parent.Padding.Left + f.Margin.Left + f.Border.Width
+ 857			// 	propagateOffsets(&n.Children[(row[1]-1)-row[0]], vState.X, vState.Y, offset, vState.Y, state)
+ 858			// 	vState.X = offset
+ 859
+ 860			// 	(*state)[n.Children[(row[1]-1)-row[0]].Properties.Id] = vState
+ 861			// }
+ 862
+ 863			// }
+ 864
+ 865		} else if justify == "space-evenly" {
+ 866			// get width of row then center (by getting last x + w + mr + b)
+ 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			// get width of row then center (by getting last x + w + mr + b)
+ 880
+ 881			for i := row[0]; i < row[1]; i++ {
+ 882				vState := s[n.Children[i].Properties.Id]
+ 883
+ 884				if !reversed {
+ 885					offset := po * (float32(i-row[0]) + 1)
+ 886					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+ 887					vState.X += offset
+ 888				} else {
+ 889					offset := po * float32(((row[1]-1)-row[0])-((i-row[0])-1))
+ 890
+ 891					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+ 892					vState.X -= offset
+ 893				}
+ 894				(*state)[n.Children[i].Properties.Id] = vState
+ 895			}
+ 896
+ 897		} else if justify == "space-around" {
+ 898			// get width of row then center (by getting last x + w + mr + b)
+ 899			parent := s[n.Properties.Id]
+ 900			po := parent.Border.Width + parent.Width
+ 901			po -= parent.Padding.Left + parent.Padding.Right
@@ -1002,60 +1002,60 @@
- 903			// get width of row then center (by getting last x + w + mr + b)
- 904
- 905			for i := row[0]; i < row[1]; i++ {
- 906				vState := s[n.Children[i].Properties.Id]
- 907
- 908				if !reversed {
- 909					offset := po * (float32(i-row[0]) + 1)
- 910					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
- 911					vState.X += offset
- 912				} else {
- 913					offset := po * float32(((row[1]-1)-row[0])-((i-row[0])-1))
- 914
- 915					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
- 916					vState.X -= offset
- 917				}
- 918				(*state)[n.Children[i].Properties.Id] = vState
- 919			}
- 920
- 921		} else if justify == "space-around" {
- 922			// get width of row then center (by getting last x + w + mr + b)
- 923			parent := s[n.Properties.Id]
- 924			po := parent.Border.Width + parent.Width
- 925			po -= parent.Padding.Left + parent.Padding.Right
- 926
- 927			// make po repersent the total space between elements
- 928			for i := row[0]; i < row[1]; i++ {
- 929				vState := s[n.Children[i].Properties.Id]
- 930				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
- 931			}
- 932
- 933			po /= float32(((row[1]) - row[0]))
- 934
- 935			// get width of row then center (by getting last x + w + mr + b)
- 936
- 937			for i := row[0]; i < row[1]; i++ {
- 938				vState := s[n.Children[i].Properties.Id]
- 939
- 940				if !reversed {
- 941					m := (float32(i-row[0]) + 1)
- 942					if i-row[0] == 0 {
- 943						m = 0.5
- 944					} else {
- 945						m -= 0.5
- 946					}
- 947					offset := po * m
- 948					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
- 949					vState.X += offset
- 950				} else {
- 951					m := float32(((row[1] - 1) - row[0]) - ((i - row[0]) - 1))
- 952					m -= 0.5
- 953					offset := po * m
- 954
- 955					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
- 956					vState.X -= offset
- 957				}
- 958				(*state)[n.Children[i].Properties.Id] = vState
- 959			}
- 960
- 961		}
- 962
+ 903			// make po repersent the total space between elements
+ 904			for i := row[0]; i < row[1]; i++ {
+ 905				vState := s[n.Children[i].Properties.Id]
+ 906				po -= vState.Width + vState.Margin.Left + vState.Margin.Right + (vState.Border.Width * 2)
+ 907			}
+ 908
+ 909			po /= float32(((row[1]) - row[0]))
+ 910
+ 911			// get width of row then center (by getting last x + w + mr + b)
+ 912
+ 913			for i := row[0]; i < row[1]; i++ {
+ 914				vState := s[n.Children[i].Properties.Id]
+ 915
+ 916				if !reversed {
+ 917					m := (float32(i-row[0]) + 1)
+ 918					if i-row[0] == 0 {
+ 919						m = 0.5
+ 920					} else {
+ 921						m -= 0.5
+ 922					}
+ 923					offset := po * m
+ 924					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X+offset, vState.Y, state)
+ 925					vState.X += offset
+ 926				} else {
+ 927					m := float32(((row[1] - 1) - row[0]) - ((i - row[0]) - 1))
+ 928					m -= 0.5
+ 929					offset := po * m
+ 930
+ 931					propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X-offset, vState.Y, state)
+ 932					vState.X -= offset
+ 933				}
+ 934				(*state)[n.Children[i].Properties.Id] = vState
+ 935			}
+ 936
+ 937		}
+ 938
+ 939	}
+ 940}
+ 941
+ 942func alignRow(rows [][]int, n *element.Node, state *map[string]element.State, align, content string) {
+ 943	// !ISSUE: Baseline isn't properly impleamented
+ 944
+ 945	s := *state
+ 946	self := s[n.Properties.Id]
+ 947
+ 948	maxes := []float32{}
+ 949	var maxesTotal float32
+ 950	for _, row := range rows {
+ 951		var maxH float32
+ 952		for i := row[0]; i < row[1]; i++ {
+ 953			vState := s[n.Children[i].Properties.Id]
+ 954			_, h := getInnerSize(&n.Children[i], state)
+ 955			h = minHeight(n.Children[i], state, h)
+ 956			vState.Height = h
+ 957			h += vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
+ 958			maxH = utils.Max(maxH, h)
+ 959			(*state)[n.Children[i].Properties.Id] = vState
+ 960		}
+ 961		maxes = append(maxes, maxH)
+ 962		maxesTotal += maxH
@@ -1063,7 +1063,7 @@
- 964}
- 965
- 966func alignRow(rows [][]int, n *element.Node, state *map[string]element.State, align, content string) {
- 967	// !ISSUE: Baseline isn't properly impleamented
- 968
- 969	s := *state
- 970	self := s[n.Properties.Id]
+ 964
+ 965	os := ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
+ 966	if os < 0 || content != "normal" {
+ 967		os = 0
+ 968	}
+ 969
+ 970	var contentOffset float32
@@ -1071,15 +1071,15 @@
- 972	maxes := []float32{}
- 973	var maxesTotal float32
- 974	for _, row := range rows {
- 975		var maxH float32
- 976		for i := row[0]; i < row[1]; i++ {
- 977			vState := s[n.Children[i].Properties.Id]
- 978			_, h := getInnerSize(&n.Children[i], state)
- 979			h = minHeight(n.Children[i], state, h)
- 980			vState.Height = h
- 981			h += vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
- 982			maxH = utils.Max(maxH, h)
- 983			(*state)[n.Children[i].Properties.Id] = vState
- 984		}
- 985		maxes = append(maxes, maxH)
- 986		maxesTotal += maxH
+ 972	if content == "center" {
+ 973		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / 2
+ 974	} else if content == "end" || content == "flex-end" {
+ 975		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal)
+ 976	} else if content == "start" || content == "flex-start" || content == "baseline" {
+ 977		// This is redundent but it helps keep track
+ 978		contentOffset = 0
+ 979	} else if content == "space-between" {
+ 980		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)-1)
+ 981	} else if content == "space-around" {
+ 982		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
+ 983		contentOffset = os / 2
+ 984	} else if content == "space-evenly" {
+ 985		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)+1)
+ 986		contentOffset = os
@@ -1088,23 +1088,23 @@
- 989	os := ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
- 990	if os < 0 || content != "normal" {
- 991		os = 0
- 992	}
- 993
- 994	var contentOffset float32
- 995
- 996	if content == "center" {
- 997		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / 2
- 998	} else if content == "end" || content == "flex-end" {
- 999		contentOffset = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal)
-1000	} else if content == "start" || content == "flex-start" || content == "baseline" {
-1001		// This is redundent but it helps keep track
-1002		contentOffset = 0
-1003	} else if content == "space-between" {
-1004		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)-1)
-1005	} else if content == "space-around" {
-1006		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows))
-1007		contentOffset = os / 2
-1008	} else if content == "space-evenly" {
-1009		os = ((self.Height - (self.Padding.Top + self.Padding.Bottom + (self.Border.Width * 2))) - maxesTotal) / float32(len(rows)+1)
-1010		contentOffset = os
-1011	}
+ 989	for c, row := range rows {
+ 990		maxH := maxes[c]
+ 991		var sum float32
+ 992		for i := 0; i < c; i++ {
+ 993			sum += maxes[i]
+ 994		}
+ 995		if align == "start" || align == "flex-start" || align == "self-start" || align == "normal" {
+ 996			for i := row[0]; i < row[1]; i++ {
+ 997				vState := s[n.Children[i].Properties.Id]
+ 998
+ 999				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
+1000
+1001				if n.Style["height"] != "" || n.Style["min-height"] != "" {
+1002					offset += ((os) * float32(c))
+1003				}
+1004
+1005				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
+1006				vState.Y = offset
+1007				(*state)[n.Children[i].Properties.Id] = vState
+1008			}
+1009		} else if align == "center" {
+1010			for i := row[0]; i < row[1]; i++ {
+1011				vState := s[n.Children[i].Properties.Id]
@@ -1112,29 +1112,29 @@
-1013	for c, row := range rows {
-1014		maxH := maxes[c]
-1015		var sum float32
-1016		for i := 0; i < c; i++ {
-1017			sum += maxes[i]
-1018		}
-1019		if align == "start" || align == "flex-start" || align == "self-start" || align == "normal" {
-1020			for i := row[0]; i < row[1]; i++ {
-1021				vState := s[n.Children[i].Properties.Id]
-1022
-1023				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
-1024
-1025				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-1026					offset += ((os) * float32(c))
-1027				}
-1028
-1029				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-1030				vState.Y = offset
-1031				(*state)[n.Children[i].Properties.Id] = vState
-1032			}
-1033		} else if align == "center" {
-1034			for i := row[0]; i < row[1]; i++ {
-1035				vState := s[n.Children[i].Properties.Id]
-1036
-1037				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
-1038
-1039				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-1040					offset += (os * float32(c+1)) - (os / 2)
-1041				}
+1013				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
+1014
+1015				if n.Style["height"] != "" || n.Style["min-height"] != "" {
+1016					offset += (os * float32(c+1)) - (os / 2)
+1017				}
+1018
+1019				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
+1020					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))) / 2
+1021				}
+1022				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
+1023				vState.Y = offset
+1024				(*state)[n.Children[i].Properties.Id] = vState
+1025			}
+1026		} else if align == "end" || align == "flex-end" || align == "self-end" {
+1027			for i := row[0]; i < row[1]; i++ {
+1028				vState := s[n.Children[i].Properties.Id]
+1029
+1030				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
+1031
+1032				if n.Style["height"] != "" || n.Style["min-height"] != "" {
+1033					offset += os * float32(c+1)
+1034				}
+1035
+1036				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
+1037					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)))
+1038				}
+1039				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
+1040				vState.Y = offset
+1041				(*state)[n.Children[i].Properties.Id] = vState
@@ -1142,10 +1142,10 @@
-1043				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
-1044					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))) / 2
-1045				}
-1046				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-1047				vState.Y = offset
-1048				(*state)[n.Children[i].Properties.Id] = vState
-1049			}
-1050		} else if align == "end" || align == "flex-end" || align == "self-end" {
-1051			for i := row[0]; i < row[1]; i++ {
-1052				vState := s[n.Children[i].Properties.Id]
+1043			}
+1044		} else if align == "stretch" {
+1045			for i := row[0]; i < row[1]; i++ {
+1046				vState := s[n.Children[i].Properties.Id]
+1047
+1048				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top
+1049
+1050				if n.Style["height"] != "" || n.Style["min-height"] != "" {
+1051					offset += ((os) * float32(c))
+1052				}
@@ -1153,125 +1153,9 @@
-1054				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top + contentOffset
-1055
-1056				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-1057					offset += os * float32(c+1)
-1058				}
-1059
-1060				if vState.Height+vState.Margin.Top+vState.Margin.Bottom+(vState.Border.Width*2) < maxH {
-1061					offset += (maxH - (vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)))
-1062				}
-1063				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-1064				vState.Y = offset
-1065				(*state)[n.Children[i].Properties.Id] = vState
-1066
-1067			}
-1068		} else if align == "stretch" {
-1069			for i := row[0]; i < row[1]; i++ {
-1070				vState := s[n.Children[i].Properties.Id]
-1071
-1072				offset := sum + self.Y + self.Padding.Top + vState.Margin.Top
-1073
-1074				if n.Style["height"] != "" || n.Style["min-height"] != "" {
-1075					offset += ((os) * float32(c))
-1076				}
-1077
-1078				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
-1079				vState.Y = offset
-1080				vState.Height = maxH - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
-1081				(*state)[n.Children[i].Properties.Id] = vState
-1082
-1083			}
-1084		}
-1085	}
-1086}
-1087
-1088func justifyCols(cols [][]int, n *element.Node, state *map[string]element.State, justify string, reversed bool) {
-1089	s := *state
-1090	self := s[n.Properties.Id]
-1091
-1092	selfHeight := (self.Height) - (self.Padding.Top + self.Padding.Bottom)
-1093	for _, col := range cols {
-1094		yCollect := self.Y + self.Padding.Top
-1095		var colHeight float32
-1096		for i := col[0]; i <= col[1]; i++ {
-1097			v := n.Children[i]
-1098			vState := s[v.Properties.Id]
-1099			colHeight += vState.Height + vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2)
-1100		}
-1101
-1102		if justify == "center" {
-1103			offset := ((selfHeight - colHeight) / 2)
-1104			yCollect += offset
-1105			for i := col[0]; i <= col[1]; i++ {
-1106				v := n.Children[i]
-1107				vState := s[v.Properties.Id]
-1108				yStore := vState.Y
-1109				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
-1110				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
-1111				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1112				(*state)[v.Properties.Id] = vState
-1113			}
-1114		}
-1115
-1116		if justify == "end" || justify == "flex-end" {
-1117			offset := (selfHeight - colHeight)
-1118			yCollect += offset
-1119			for i := col[0]; i <= col[1]; i++ {
-1120				v := n.Children[i]
-1121				vState := s[v.Properties.Id]
-1122				yStore := vState.Y
-1123				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
-1124				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
-1125				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1126				(*state)[v.Properties.Id] = vState
-1127			}
-1128		}
-1129
-1130		if justify == "space-evenly" {
-1131			offset := (selfHeight - colHeight) / (float32(col[1]-col[0]) + 2)
-1132			for i := col[0]; i <= col[1]; i++ {
-1133				v := n.Children[i]
-1134				vState := s[v.Properties.Id]
-1135				yStore := vState.Y
-1136				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top + offset
-1137				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width + offset
-1138				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1139				(*state)[v.Properties.Id] = vState
-1140			}
-1141		}
-1142
-1143		if justify == "space-between" {
-1144			offset := (selfHeight - colHeight) / (float32(col[1] - col[0]))
-1145			for i := col[0]; i <= col[1]; i++ {
-1146				v := n.Children[i]
-1147				vState := s[v.Properties.Id]
-1148				yStore := vState.Y
-1149				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
-1150				if col[1]-col[0] != 0 {
-1151					vState.Y += offset * float32(i-col[0])
-1152				} else if reversed {
-1153					vState.Y += selfHeight - (vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width)
-1154				}
-1155				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
-1156				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1157				(*state)[v.Properties.Id] = vState
-1158			}
-1159		}
-1160		if justify == "space-around" {
-1161			offset := (selfHeight - colHeight) / (float32(col[1]-col[0]) + 1)
-1162			for i := col[0]; i <= col[1]; i++ {
-1163				v := n.Children[i]
-1164				vState := s[v.Properties.Id]
-1165				yStore := vState.Y
-1166				vState.Y = yCollect + vState.Border.Width + vState.Margin.Top
-1167				if col[1]-col[0] == 0 {
-1168					vState.Y += offset / 2
-1169				} else {
-1170					vState.Y += (offset * float32(i-col[0])) + (offset / 2)
-1171				}
-1172				yCollect += vState.Height + vState.Margin.Bottom + vState.Border.Width + vState.Margin.Top + vState.Border.Width
-1173				propagateOffsets(&n.Children[i], vState.X, yStore, vState.X, vState.Y, state)
-1174				(*state)[v.Properties.Id] = vState
-1175			}
-1176		}
-1177	}
-1178}
+1054				propagateOffsets(&n.Children[i], vState.X, vState.Y, vState.X, offset, state)
+1055				vState.Y = offset
+1056				vState.Height = maxH - (vState.Margin.Top + vState.Margin.Bottom + (vState.Border.Width * 2))
+1057				(*state)[n.Children[i].Properties.Id] = vState
+1058
+1059			}
+1060		}
+1061	}
+1062}


    
        
        
        
        
        GRIM UI 
        
        
        
        
    
    
        
        

Flexbox

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

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

# Flex Properties

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

# order?(go)

asd

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