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


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