M Graphics/Layout.hs => Graphics/Layout.hs +250 -11
@@ 1,21 1,260 @@
+{-# LANGUAGE OverloadedStrings, RecordWildCards #-}
module Graphics.Layout where
-import Graphics.Layout.Box
-import Graphics.Layout.Grid
+import Graphics.Layout.Box as B
+import Graphics.Layout.Grid as G
+import Graphics.Layout.Flow as F
+
+import Data.Maybe (fromMaybe)
data LayoutItem m n x =
LayoutFlow x (PaddedBox m n) [LayoutItem m n x]
| LayoutGrid x (Grid m n) [(GridItem m n, LayoutItem m n x)]
-- More to come...
-{-boxMinWidth :: Double -> LayoutItem y Length x -> (Double, LayoutItem y Length x)
-boxNatWidth :: Double -> LayoutItem y Length x -> (Double, LayoutItem y Length x)
-boxMaxWidth :: PaddedBox y Length -> LayoutItem y Length x -> (Double, LayoutItem y Length x)
-boxWidth :: PaddedBox y Length -> LayoutItem y Length x -> (Double, LayoutItem y Double x)
-boxNatHeight :: LayoutItem Length Double x -> (Double, LayoutItem Length Double x)
+layoutGetBox (LayoutFlow _ ret _) = ret
+layoutGetBox (LayoutGrid _ self _) = zero {
+ B.min = containerMin self,
+ B.size = containerSize self,
+ B.max = containerMax self
+}
+setCellBox' (child, cell) = cell { gridItemBox = layoutGetBox child }
+
+boxMinWidth :: Zero y => Maybe Double -> LayoutItem y Length x -> (Double, LayoutItem y Length x)
+boxMinWidth parent (LayoutFlow val self childs) = (min', LayoutFlow val self' childs')
+ where
+ self' = self {B.min = Size (Pixels min') (block $ B.min self) }
+ min' = flowMinWidth parent' self childs''
+ childs'' = map (mapX' $ lowerLength selfWidth) $ map layoutGetBox childs'
+ childs' = map snd $ map (boxMinWidth $ Just selfWidth) childs
+ selfWidth = width $ mapX' (lowerLength parent') self
+ parent' = fromMaybe 0 parent
+boxMinWidth parent (LayoutGrid val self childs) =
+ (min', LayoutGrid val self' $ zip cells' childs')
+ where
+ self' = self {
+ containerMin = Size (Pixels min') (block $ containerMin self),
+ colBounds = zip cells (map snd (colBounds self) ++ repeat 0)
+ }
+ (min', cells) = gridMinWidths parent' self cells''
+ cells'' = [ setCellBox (mapX' (lowerLength selfWidth) $ gridItemBox cell) cell
+ | cell <- cells']
+ cells' = map setCellBox' $ zip childs' $ map fst childs
+ childs'' = map (mapX' $ lowerLength selfWidth) $ map layoutGetBox childs'
+ childs' = map snd $ map (boxMinWidth $ Just selfWidth) $ map snd childs
+ selfWidth = lowerLength parent' $ inline $ containerSize self
+ parent' = fromMaybe (gridEstWidth self [
+ GridItem startRow endRow startCol endCol alignment zeroBox |
+ (GridItem {..}, _) <- childs]) parent
+ zeroBox :: PaddedBox Double Double
+ zeroBox = zero
+boxNatWidth :: Zero y => Maybe Double -> LayoutItem y Length x -> (Double, LayoutItem y Length x)
+boxNatWidth parent (LayoutFlow val self childs) = (size', LayoutFlow val self childs')
+ -- NOTE: Need to preserve auto/percentage in actual width calculation.
+ -- self' doesn't preserve this. CatTrap will need a decent refactor!
+ where
+ self' = self {size = Size (Pixels size') (block $ size self) }
+ size' = flowNatWidth parent' self childs''
+ childs'' = map (mapX' $ lowerLength selfWidth) $ map layoutGetBox childs'
+ childs' = map snd $ map (boxNatWidth $ Just selfWidth) childs
+ selfWidth = width $ mapX' (lowerLength parent') self
+ parent' = fromMaybe 0 parent
+boxNatWidth parent (LayoutGrid val self childs) =
+ (size', LayoutGrid val self' $ zip cells' childs')
+ where
+ self' = self {
+ containerSize = Size (Pixels size') (block $ containerSize self),
+ colBounds = zip (map fst (colBounds self) ++ repeat 0) cells
+ }
+ (size', cells) = gridNatWidths parent' self cells''
+ cells'' = [
+ cell { gridItemBox = mapX' (lowerLength selfWidth) $ gridItemBox cell }
+ | cell <- cells']
+ cells' = map setCellBox $ zip childs' $ map fst childs
+ setCellBox (child, cell) = cell { gridItemBox = layoutGetBox child }
+ childs'' = map (mapX' $ lowerLength selfWidth) $ map layoutGetBox childs'
+ childs' = map snd $ map (boxNatWidth $ Just selfWidth) $ map snd childs
+ selfWidth = lowerLength parent' $ inline $ containerSize self
+ parent' = fromMaybe (gridEstWidth self [
+ GridItem startRow endRow startCol endCol alignment zeroBox |
+ (GridItem {..}, _) <- childs]) parent
+ zeroBox :: PaddedBox Double Double
+ zeroBox = zero
+boxMaxWidth :: PaddedBox a Double -> LayoutItem y Length x -> (Double, LayoutItem y Length x)
+boxMaxWidth parent (LayoutFlow val self childs) = (max', LayoutFlow val self' childs)
+ where
+ self' = self { B.max = Size (Pixels max') (block $ B.max self) }
+ max' = flowMaxWidth parent self
+boxMaxWidth parent (LayoutGrid val self childs) =
+ (max', LayoutGrid val self' childs)
+ where
+ self' = self { containerMax = Size (Pixels max') (block $ containerMax self) }
+ (max', _) = gridMaxWidths parent self $ colBounds self
+boxWidth :: Zero y => PaddedBox b Double -> LayoutItem y Length x ->
+ (Double, LayoutItem y Double x)
+boxWidth parent (LayoutFlow val self childs) = (size', LayoutFlow val self' childs')
+ where
+ childs' = map (snd . boxWidth self') childs
+ self' = (mapX' (lowerLength $ inline $ size parent) self) {
+ size = Size size' $ block $ B.max self
+ }
+ size' = flowWidth parent self
+boxWidth parent (LayoutGrid val self childs) = (size', LayoutGrid val self' childs')
+ where
+ childs' = map recurse childs
+ recurse (cell, child) = (cell', child')
+ where
+ cell' = cell { gridItemBox = layoutGetBox child' }
+ (_, child') = boxWidth parent' child
+ parent' = zero {
+ B.min = containerMin self',
+ B.size = containerSize self',
+ B.max = containerMax self'
+ }
+ self' = Grid {
+ containerSize = Size size' $ block $ containerSize self,
+ containerMin = mapSizeX (lowerLength outerwidth) $ containerMin self,
+ containerMax = mapSizeX (lowerLength outerwidth) $ containerMax self,
+ gap = mapSizeX (lowerLength outerwidth) $ gap self,
+ columns = [("", Left width) | width <- widths],
+
+ rows = rows self,
+ rowBounds = rowBounds self,
+ colBounds = colBounds self
+ }
+ outerwidth = inline $ size parent
+ (size', widths) = gridWidths parent self $ colBounds self
+
+boxNatHeight :: Double -> LayoutItem Length Double x -> (Double, LayoutItem Length Double x)
+boxNatHeight parent (LayoutFlow val self childs) = (size', LayoutFlow val self' childs')
+ where
+ self' = self {
+ size = Size width (Pixels size')
+ }
+ size' = flowNatHeight parent self childs''
+ childs'' = map (mapY' (lowerLength parent)) $ map layoutGetBox childs'
+ childs' = map snd $ map (boxNatHeight width) childs
+ width = inline $ size self
+boxNatHeight parent (LayoutGrid val self childs) =
+ (size', LayoutGrid val self' $ zip cells childs')
+ where
+ self' = self {
+ containerSize = Size width $ Pixels size'
+ }
+ lowerGridUnit (Left length) = Left $ lowerLength width length
+ lowerGridUnit (Right x) = Right x
+ (size', heights) = gridNatHeights parent self cells'
+ cells' = [setCellBox (mapY' (lowerLength width) $ gridItemBox cell) cell | cell <- cells]
+ cells = map setCellBox' $ zip childs' $ map fst childs
+ childs' = map snd $ map (boxNatHeight width) $ map snd childs
+ width = inline $ containerSize self
boxMinHeight :: Double -> LayoutItem Length Double x -> (Double, LayoutItem Length Double x)
-boxMaxHeight :: Double -> LayoutItem Length Double x -> (Double, LayoutItem Length Double x)
-boxHeight :: Double -> LayoutItem Length Double x -> (Double, LayoutItem Length Length x)
-boxPosition :: LayoutItem Double Double x -> LayoutItem Double Double x
+boxMinHeight parent (LayoutFlow val self childs) = (min', LayoutFlow val self' childs')
+ where
+ childs' = map snd $ map (boxMinHeight $ inline $ size self) childs
+ self' = self {
+ B.min = Size (inline $ B.min self) (Pixels min')
+ }
+ min' = flowMinHeight parent self
+boxMinHeight parent (LayoutGrid val self childs) = (min', LayoutGrid val self' childs')
+ where
+ childs' = map recurse childs
+ recurse (cell, child) = (cell', child')
+ where
+ cell' = setCellBox (layoutGetBox child') cell
+ (_, child') = boxMinHeight width child
+ self' = self {
+ containerMin = Size width $ Pixels min',
+ rowBounds = zip heights (map snd (rowBounds self) ++ repeat 0)
+ }
+ (min', heights) = gridMinHeights width self childs0
+ childs0 = [ GridItem {
+ gridItemBox = mapY' (lowerLength width) $ gridItemBox cell,
+ startRow = startRow cell, endRow = endRow cell,
+ startCol = startCol cell, endCol = endCol cell, alignment = alignment cell
+ } | (cell, _) <- childs]
+ width = inline $ containerSize self
+boxMaxHeight :: PaddedBox Double Double -> LayoutItem Length Double x ->
+ (Double, LayoutItem Length Double x)
+boxMaxHeight parent (LayoutFlow val self childs) = (max', LayoutFlow val self' childs')
+ where
+ childs' = map snd $ map (boxMaxHeight $ mapY' (lowerLength width) self') childs
+ self' = self {
+ B.max = Size (inline $ B.max self) (Pixels max')
+ }
+ max' = flowMaxHeight (inline $ size parent) self
+ width = inline $ size self
+boxMaxHeight parent (LayoutGrid val self childs) = (max', LayoutGrid val self' childs')
+ where
+ childs' = map recurse childs
+ recurse (cell, child) = (cell', child')
+ where
+ cell' = setCellBox (layoutGetBox child') cell
+ (_, child') = boxMaxHeight parent' child
+ parent' :: PaddedBox Double Double
+ parent' = zero {
+ B.min = mapSizeY (lowerLength width) $ containerMin self,
+ B.size = mapSizeY (lowerLength width) $ containerSize self,
+ B.max = Size (inline $ containerMax self') max'
+ }
+ self' = self {
+ containerMax = Size (inline $ containerSize self) (Pixels max')
+ }
+ (max', heights) = gridMaxHeights parent self $ rowBounds self
+ width = inline $ size parent
+boxHeight :: PaddedBox Double Double -> LayoutItem Length Double x ->
+ (Double, LayoutItem Double Double x)
+boxHeight parent (LayoutFlow val self childs) = (size', LayoutFlow val self' childs')
+ where
+ childs' = map snd $ map (boxHeight self') childs
+ self' = (mapY' (lowerLength $ inline $ size parent) self) {
+ size = Size (inline $ size self) size'
+ }
+ size' = flowHeight parent self
+ width = inline $ size self
+boxHeight parent (LayoutGrid val self childs) = (size', LayoutGrid val self' childs')
+ where
+ childs' = map recurse childs
+ recurse (cell, child) = (cell', child')
+ where
+ cell' = setCellBox (layoutGetBox child') cell
+ (_, child') = boxHeight (layoutGetBox $ LayoutGrid val self' []) child
+ self' = Grid {
+ containerSize = Size (inline $ containerSize self) size',
+ containerMin = mapSizeY (lowerLength width) $ containerMin self,
+ containerMax = mapSizeY (lowerLength width) $ containerMax self,
+ gap = mapSizeY (lowerLength width) $ gap self,
+
+ rows = map lowerSize $ rows self, rowBounds = rowBounds self,
+ columns = columns self, colBounds = colBounds self
+ }
+ (size', heights) = gridHeights parent self $ rowBounds self
+ lowerSize (n, Left x) = (n, Left $ lowerLength width x)
+ lowerSize (n, Right x) = (n, Right x)
+ width = inline $ size parent
+
+boxPosition :: (Double, Double) -> LayoutItem Double Double x ->
+ LayoutItem Double Double ((Double, Double), x)
+boxPosition pos@(x, y) (LayoutFlow val self childs) = LayoutFlow (pos, val) self childs'
+ where
+ childs' = map recurse $ zip pos' childs
+ recurse ((Size x' y'), child) = boxPosition (x + x', y + y') child
+ pos' = positionFlow $ map layoutGetBox childs
+boxPosition pos@(x, y) (LayoutGrid val self childs) = LayoutGrid (pos, val) self childs'
+ where
+ childs' = map recurse $ zip pos' childs
+ recurse ((Size x' y'), (cell, child)) = (cell, boxPosition (x + x', y + y') child)
+ pos' = gridPosition self $ map fst childs
boxLayout :: PaddedBox Double Double -> LayoutItem Length Length x -> Bool ->
- LayoutItem Double Double x-}
+ LayoutItem Double Double ((Double, Double), x)
+boxLayout parent self paginate = self8
+ where
+ (_, self0) = boxMinWidth Nothing self
+ (_, self1) = boxNatWidth Nothing self0
+ (_, self2) = boxMaxWidth parent self1
+ (_, self3) = boxWidth parent self2
+ (natsize, self4) = boxNatHeight (inline $ size parent) self3
+ (_, self5) = boxMinHeight natsize self4
+ (_, self6) = boxMaxHeight parent self5
+ (_, self7) = boxHeight parent self6
+ self8 = boxPosition (0, 0) self7
M Graphics/Layout/Box.hs => Graphics/Layout/Box.hs +37 -1
@@ 10,6 10,8 @@ mapX cb self = self { left = cb $ left self, right = cb $ right self }
mapY cb self = self { top = cb $ top self, bottom = cb $ bottom self }
data Size m n = Size {inline :: n, block :: m} deriving (Eq, Show)
+mapSizeY cb self = Size (inline self) (cb $ block self)
+mapSizeX cb self = Size (cb $ inline self) (block self)
data PaddedBox m n = PaddedBox {
min :: Size m n,
@@ 35,7 37,26 @@ lengthBox = PaddedBox {
padding = Border zero zero zero zero,
border = Border zero zero zero zero,
margin = Border zero zero zero zero
- } where zero = Pixels 0
+ }
+
+mapX' :: (n -> nn) -> PaddedBox m n -> PaddedBox m nn
+mapX' cb PaddedBox {..} = PaddedBox {
+ min = Size (cb $ inline min) (block min),
+ size = Size (cb $ inline size) (block size),
+ max = Size (cb $ inline max) (block max),
+ padding = mapX cb padding,
+ border = mapX cb border,
+ margin = mapX cb margin
+ }
+mapY' :: (m -> mm) -> PaddedBox m n -> PaddedBox mm n
+mapY' cb PaddedBox {..} = PaddedBox {
+ min = Size (inline min) (cb $ block min),
+ size = Size (inline size) (cb $ block size),
+ max = Size (inline max) (cb $ block max),
+ padding = mapY cb padding,
+ border = mapY cb border,
+ margin = mapY cb margin
+ }
width PaddedBox {..} = left margin + left border + left padding +
inline size + right padding + right border + right margin
@@ 56,3 77,18 @@ lowerLength :: Double -> Length -> Double
lowerLength _ (Pixels x) = x
lowerLength outerwidth (Percent x) = x * outerwidth
lowerLength _ _ = 0
+
+class Zero a where
+ zero :: a
+
+instance Zero Double where zero = 0
+instance Zero Length where zero = Pixels 0
+instance (Zero m, Zero n) => Zero (PaddedBox m n) where
+ zero = PaddedBox {
+ min = Size zero zero,
+ max = Size zero zero,
+ size = Size zero zero,
+ padding = Border zero zero zero zero,
+ border = Border zero zero zero zero,
+ margin = Border zero zero zero zero
+ }
M Graphics/Layout/Grid.hs => Graphics/Layout/Grid.hs +17 -12
@@ 14,7 14,9 @@ data Grid m n = Grid {
columns :: [(Name, Either n Double)],
colBounds :: [(Double, Double)],
gap :: Size m n,
- containerSize :: Size m n -- wrap in a Flow box to get padding, etc.
+ containerSize :: Size m n, -- wrap in a Flow box to get padding, etc.
+ containerMin :: Size m n,
+ containerMax :: Size m n
}
data GridItem m n = GridItem {
startRow :: Int, endRow :: Int, startCol :: Int, endCol :: Int,
@@ 31,8 33,13 @@ buildGrid rows columns = Grid {
columns = zip (repeat "") columns,
colBounds = [],
gap = Size (Pixels 0) (Pixels 0),
- containerSize = Size Auto Auto
+ containerSize = Size Auto Auto,
+ containerMin = Size Auto Auto,
+ containerMax = Size Auto Auto
}
+-- Created to address typesystem issues with record syntax.
+setCellBox :: PaddedBox mm nn -> GridItem m n -> GridItem mm nn
+setCellBox box' GridItem {..} = GridItem startRow endRow startCol endCol alignment box'
cellsForCol :: [GridItem y x] -> Int -> [GridItem y x]
cellsForCol cells ix =
@@ 109,11 116,6 @@ gridWidths parent self subwidths =
colWidth' fr ((_, nat), Left Auto) = Prelude.min nat fr
colWidth' fr (_, Right x) = x*fr
-gridEstHeight :: Grid Length Double -> [GridItem Double Double] -> Double
-gridEstHeight self childs = fst $ gridMaxHeights zeroBox self $ zip mins nats
- where
- mins = snd $ gridMinHeights 0 self childs
- nats = snd $ gridNatHeights 0 self childs
gridNatHeights :: Double -> Grid Length Double -> [GridItem Double Double] -> (Double, [Double])
gridNatHeights parent self childs =
(sum $ intersperse (lowerLength parent $ block $ gap self) ret, ret)
@@ 202,21 204,24 @@ gridLayout parent self childs paginate = (self', zip positions childs)
columns = zip (map fst $ rows self) $ map Left cols',
colBounds = colBounds',
gap = Size (lowerLength width' gapX) (lowerLength width' gapY),
- containerSize = Size width' height'
+ containerSize = Size width' height',
+ containerMin = Size width' height',
+ containerMax = Size width' height'
}
Size gapX gapY = gap self
(height', rows') = gridHeights parent self0 rowBounds'
rowBounds' = zip rowMins rowNats
- (_, rowMins) = gridMinHeights estHeight self0 childs
- (_, rowNats) = gridNatHeights estHeight self0 childs
- estHeight = gridEstHeight self0 childs
+ (_, rowMins) = gridMinHeights width' self0 childs
+ (_, rowNats) = gridNatHeights width' self0 childs
self0 = self {
columns = zip (map fst $ columns self) $ map Left cols',
colBounds = colBounds',
gap = Size (lowerLength width' gapX) gapY,
- containerSize = let Size _ y = containerSize self in Size width' y
+ containerSize = let Size _ y = containerSize self in Size width' y,
+ containerMin = let Size _ y = containerSize self in Size width' y,
+ containerMax = let Size _ y = containerSize self in Size width' y
}
(width', cols') = gridWidths parent self colBounds'
colBounds' = zip colMins colNats
M test/Test.hs => test/Test.hs +146 -1
@@ 5,9 5,11 @@ import Test.Hspec
import Graphics.Layout.Arithmetic
import Data.CSS.Syntax.Tokens (tokenize, Token(..))
+
import Graphics.Layout.Box as B
import Graphics.Layout.Grid
import Graphics.Layout.Flow
+import Graphics.Layout
main :: IO ()
main = hspec spec
@@ 25,7 27,7 @@ spec = do
runMath "6 * (9 - 42)" `shouldBe` -198
runMath "6 * calc(9 - 42)" `shouldBe` -198
runMath "6 * abs(9 - 42)" `shouldBe` 198
- describe "Width sizing" $ do
+ describe "Flow sizing" $ do
-- Based on http://hixie.ch/tests/adhoc/css/box/block/
it "Can overflow parent" $ do
width (fst $ layoutFlow zeroBox {
@@ 62,6 64,13 @@ spec = do
margin = Border (Pixels 0) (Pixels 0) (Pixels 2) (Pixels 2),
size = Size Auto $ Pixels 1
} [] False) `shouldBe` 5
+ it "Fits children" $ do
+ let child = mapX' (lowerLength 100) $ lengthBox {
+ size = Size (Pixels 10) (Pixels 10)
+ }
+ height (fst $ layoutFlow zeroBox {
+ size = Size 100 100
+ } lengthBox [child, child] False) `shouldBe` 20
it "Collapses margins" $ do
let a :: PaddedBox Length Double
a = PaddedBox {
@@ 134,5 143,141 @@ spec = do
}] True
containerSize minGrid `shouldBe` Size 10 10
fst (head minCells) `shouldBe` Size 0 0
+ describe "Abstract layout" $ do
+ it "Can overflow parent" $ do
+ width (layoutGetBox $ boxLayout zeroBox {
+ size = Size 3 1
+ } (LayoutFlow () lengthBox {
+ border = Border (Pixels 0) (Pixels 0) (Pixels 2) (Pixels 2)
+ } []) False) `shouldBe` 4
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 3 1
+ } (LayoutFlow () lengthBox {
+ border = Border (Pixels 2) (Pixels 2) (Pixels 2) (Pixels 2)
+ } []) False) `shouldBe` 4
+ width (layoutGetBox $ boxLayout zeroBox {
+ size = Size 3 1
+ } (LayoutFlow () lengthBox {
+ padding = Border (Pixels 0) (Pixels 0) (Pixels 2) (Pixels 2)
+ } []) False) `shouldBe` 4
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 3 1
+ } (LayoutFlow () lengthBox {
+ padding = Border (Pixels 2) (Pixels 2) (Pixels 2) (Pixels 2)
+ } []) False) `shouldBe` 4
+ width (layoutGetBox $ boxLayout zeroBox {
+ size = Size 3 1
+ } (LayoutFlow () lengthBox {
+ margin = Border (Pixels 0) (Pixels 0) (Pixels 2) (Pixels 2)
+ } []) False) `shouldBe` 4
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 3 1
+ } (LayoutFlow () lengthBox {
+ margin = Border (Pixels 2) (Pixels 2) (Pixels 2) (Pixels 2)
+ } []) False) `shouldBe` 4
+ it "Fits to parent" $ do
+ width (layoutGetBox $ boxLayout zeroBox {
+ size = Size 5 1
+ } (LayoutFlow () lengthBox {
+ border = Border (Pixels 0) (Pixels 0) (Pixels 2) (Pixels 2),
+ size = Size Auto $ Pixels 1
+ } []) False) `shouldBe` 5
+ width (layoutGetBox $ boxLayout zeroBox {
+ size = Size 5 1
+ } (LayoutFlow () lengthBox {
+ padding = Border (Pixels 0) (Pixels 0) (Pixels 2) (Pixels 2),
+ size = Size Auto $ Pixels 1
+ } []) False) `shouldBe` 5
+ width (layoutGetBox $ boxLayout zeroBox {
+ size = Size 5 1
+ } (LayoutFlow () lengthBox {
+ margin = Border (Pixels 0) (Pixels 0) (Pixels 2) (Pixels 2),
+ size = Size Auto $ Pixels 1
+ } []) False) `shouldBe` 5
+ it "Fits children" $ do
+ let child = LayoutFlow () lengthBox {
+ size = Size (Pixels 10) (Pixels 10),
+ B.max = Size (Pixels 10) (Pixels 10)
+ } []
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 100 100
+ } child False) `shouldBe` 10
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutFlow () lengthBox [child, child]) False) `shouldBe` 20
+ it "Collapses margins" $ do
+ let a :: LayoutItem Length Length ()
+ a = LayoutFlow () PaddedBox {
+ B.min = Size Auto Auto,
+ size = Size Auto Auto,
+ B.max = Size Auto Auto,
+ padding = Border (Pixels 0) (Pixels 0) (Pixels 0) (Pixels 0),
+ border = Border (Pixels 0) (Pixels 0) (Pixels 0) (Pixels 0),
+ margin = Border (Pixels 5) (Pixels 10) (Pixels 0) (Pixels 0)
+ } []
+ b :: LayoutItem Length Length ()
+ b = LayoutFlow () PaddedBox {
+ B.min = Size Auto Auto,
+ size = Size Auto Auto,
+ B.max = Size Auto Auto,
+ padding = Border (Pixels 0) (Pixels 0) (Pixels 0) (Pixels 0),
+ border = Border (Pixels 0) (Pixels 0) (Pixels 0) (Pixels 0),
+ margin = Border (Pixels 10) (Pixels 5) (Pixels 0) (Pixels 0)
+ } []
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutFlow () lengthBox [a, a]) False) `shouldBe` 25
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutFlow () lengthBox [b, b]) False) `shouldBe` 25
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutFlow () lengthBox [a, b]) False) `shouldBe` 20
+ height (layoutGetBox $ boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutFlow () lengthBox [b, a]) False) `shouldBe` 25
+
+ it "computes single-columns widths/heights" $ do
+ let zeroCell = LayoutFlow () lengthBox []
+ let nonzeroCell = LayoutFlow () lengthBox {
+ B.min = Size (Pixels 10) (Pixels 10),
+ size = Size (Pixels 20) (Pixels 20)
+ } []
+
+ let LayoutGrid (_, _) pxGrid pxCells = boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutGrid () (buildGrid [Left $ Pixels 10] [Left $ Pixels 10])
+ [(GridItem 0 1 0 1 (Size Start Start) lengthBox, zeroCell)]) True
+ let LayoutFlow (pos, _) _ _ = snd $ head pxCells
+ containerSize pxGrid `shouldBe` Size 10 10
+ pos `shouldBe` (0, 0)
+ let LayoutGrid (_, _) pxGrid pxCells = boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutGrid () (buildGrid [Left $ Percent 0.5] [Left $ Percent 0.5])
+ [(GridItem 0 1 0 1 (Size Start Start) lengthBox, zeroCell)]) True
+ let LayoutFlow (pos, _) _ _ = snd $ head pxCells
+ containerSize pxGrid `shouldBe` Size 50 50
+ pos `shouldBe` (0, 0)
+ let LayoutGrid (_, _) pxGrid pxCells = boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutGrid () (buildGrid [Left Auto] [Left Auto])
+ [(GridItem 0 1 0 1 (Size Start Start) lengthBox, nonzeroCell)]) True
+ let LayoutFlow (pos, _) _ _ = snd $ head pxCells
+ containerSize pxGrid `shouldBe` Size 20 10 -- FIXME Is the 10 correct?
+ pos `shouldBe` (0, 0)
+ let LayoutGrid (_, _) pxGrid pxCells = boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutGrid () (buildGrid [Left Preferred] [Left Preferred])
+ [(GridItem 0 1 0 1 (Size Start Start) lengthBox, nonzeroCell)]) True
+ let LayoutFlow (pos, _) _ _ = snd $ head pxCells
+ containerSize pxGrid `shouldBe` Size 20 0 -- FIXME Is the 0 correct?
+ pos `shouldBe` (0, 0)
+ let LayoutGrid (_, _) pxGrid pxCells = boxLayout zeroBox {
+ size = Size 100 100
+ } (LayoutGrid () (buildGrid [Left Min] [Left Min])
+ [(GridItem 0 1 0 1 (Size Start Start) lengthBox, nonzeroCell)]) True
+ let LayoutFlow (pos, _) _ _ = snd $ head pxCells
+ containerSize pxGrid `shouldBe` Size 10 10
+ pos `shouldBe` (0, 0)
runMath = flip evalCalc [] . mapCalc fst . flip parseCalc [] . filter (/= Whitespace) . tokenize