@@ 0,0 1,83 @@
+module Graphics.Layout.Flex(FlexParent(..), FlexChild(..),
+ Direction(..), FlexWrapping(..), Justification(..), Alignment(..),
+ flexMaxBasis, flexSumBasis, flexWrap) where
+
+import Graphics.Layout.Box (Length, lowerLength)
+import Data.List (intersperse)
+
+data FlexParent a b = FlexParent {
+ direction :: Direction,
+ reverseRows :: Bool,
+ wrap :: FlexWrapping,
+ justify :: Justification,
+ alignLines :: Maybe Justification, -- `Nothing` is "stretch"
+ baseGap :: b,
+ crossGap :: b,
+ children :: [[FlexChild a b]] -- 2D list to store lines once split.
+}
+data FlexChild a b = FlexChild {
+ grow :: Double,
+ shrink :: Double,
+ basis :: b,
+ alignment :: Alignment,
+ flexInner :: a
+}
+
+data Direction = Row | Column
+data FlexWrapping = NoWrap | Wrap | WrapReverse
+data Justification = JLeft | JRight | JCenter | JSpaceBetween | JSpaceAround | JSpaceEvenly
+data Alignment = AlStretch | AlStart | AlEnd | AlCenter | AlBaseline
+
+flexMaxBasis :: FlexParent a Length -> Double -> Double
+flexMaxBasis self outersize = maximum [lowerLength outersize $ basis child |
+ row <- children self, child <- row]
+flexSumBasis :: FlexParent a Length -> Double -> Double
+flexSumBasis self size = maximum [Prelude.sum $ map (lowerLength size) $
+ intersperse (baseGap self) $ map basis row | row <- children self]
+
+flexWrap :: FlexParent a Length -> Double -> FlexParent a Double
+flexWrap self size
+ | NoWrap <- wrap self = post self'
+ | Wrap <- wrap self = post wrapped
+ | WrapReverse <- wrap self = post wrapped {children=reverse$children wrapped}
+ where
+ self' = FlexParent {
+ direction = direction self,
+ reverseRows = reverseRows self,
+ wrap = wrap self,
+ justify = justify self,
+ alignLines = alignLines self,
+ baseGap = lowerLength size $ baseGap self,
+ crossGap = lowerLength size $ crossGap self,
+ children = map (map $ child' size) $ children self
+ }
+ child' size x = FlexChild {
+ grow = grow x, shrink = shrink x,
+ basis = lowerLength size $ basis x,
+ alignment = alignment x, flexInner = flexInner x
+ }
+ wrapped = self' {
+ children = concatMap wrapRow $ children self'
+ }
+ wrapRow :: [FlexChild a Double] -> [[FlexChild a Double]]
+ wrapRow [] = []
+ wrapRow kids@(kid:_) = let (row, rest) = splitRow kids $ basis kid
+ in (row):wrapRow rest
+ splitRow (kid:kids) end
+ | end > size = ([], kid:kids)
+ | otherwise = let (kids', rest) = splitRow kids (end + baseGap self' + basis kid)
+ in (kid:kids', rest)
+ splitRow [] _ = ([], [])
+
+ post flex
+ | reverseRows self = post' flex { children = map reverse $ children flex }
+ | otherwise = post' flex
+ post' flex = flex { children = map resizeRow $ children flex }
+ resizeRow row
+ | rowSize > size = [kid { basis = basis kid - shrink kid * sfr } | kid <- row]
+ | rowSize < size = [kid { basis = basis kid + grow kid * gfr } | kid <- row]
+ | otherwise = row
+ where
+ rowSize = Prelude.sum $ intersperse (baseGap self') $ map basis row
+ sfr = (rowSize - size)/(Prelude.sum $ map shrink row)
+ gfr = (size - rowSize)/(Prelude.sum $ map grow row)
@@ 27,7 27,7 @@ library
Graphics.Layout.Box, Graphics.Layout.Arithmetic,
Graphics.Layout.CSS.Length, Graphics.Layout.CSS.Font,
Graphics.Layout.Inline, Graphics.Layout.Inline.CSS,
- Graphics.Layout.Grid.Table
+ Graphics.Layout.Grid.Table, Graphics.Layout.Flex
other-modules: Graphics.Layout.CSS.Parse
-- other-extensions:
build-depends: base >=4.12 && <5, containers >= 0.6 && < 1, parallel >= 3 && <4,