~alcinnz/CatTrap

8b24d68f9fa25fea2ee9fa3f8730556c79737dba — Adrian Cochrane 1 year, 1 month ago 5c3e14a
Implement basic table layout.
2 files changed, 52 insertions(+), 48 deletions(-)

M Graphics/Layout/CSS.hs
M Graphics/Layout/CSS/Parse.hs
M Graphics/Layout/CSS.hs => Graphics/Layout/CSS.hs +48 -44
@@ 17,6 17,7 @@ import Graphics.Layout
import Graphics.Layout.CSS.Length
import Graphics.Layout.CSS.Font
import Graphics.Layout.Grid.CSS
import Graphics.Layout.Grid
import Graphics.Layout.Inline.CSS

import Data.Char (isSpace)


@@ 140,63 141,66 @@ finalizeBox self@CSSBox { cssBox = box } font_ =
    mapY' (flip finalizeLength font_) $ mapX' (flip finalizeLength font_) box

-- | (Unused, incomplete) Desugar a styletree of table elements to a grid layout.
finalizeTable root parent val childs = LayoutFlow val lengthBox [] -- Placeholder!
{-finalizeTable root parent val childs = LayoutGrid val grid $ zip cells' childs'
  where -- FIXME? How to handle non-table items in <table>?
    grid = Grid {
        rows = take width $ repeat ("", (0,"auto")),
        rowBounds = [],
        subgridRows = 0,
        columns = take height $ repeat ("", (0,"auto")),
        colBounds = [],
        subgridCols = 0,
        gap = Size (0,"px") (0,"px"), -- FIXME where to get this from?
        containerSize = Size Auto Auto, -- Proper size is set on parent.
        containerMin = Size Auto Auto,
        containerMax = Size Auto Auto
    }
    cells' = adjustWidths cells
finalizeTable root parent val childs = LayoutGrid val grid cells' childs'
  where
    grid = Track {
        cells = replicate width $ Left Auto,
        gap = Pixels 0, -- Allow styling this!
        trackMins = [], trackNats = []
      } `Size` Track {
        cells = replicate height $  Left Auto,
        gap = Pixels 0, -- Allow styling this!
        trackMins = [], trackNats = []
      }
    (cells', childs') = unzip cells

    (cells, width, height) = lowerCells childs
    lowerCells (StyleTree self@CSSBox { display = TableRow } cells:rest) =
        (row:rows, max rowwidth width', succ height)
    (cells, width, height) = lowerCells childs 0
    lowerCells (StyleTree self@CSSBox { display = TableRow } cells:rest) h =
        (row ++ rows, Prelude.max rowwidth width', height')
      where
        (row, rowwidth) = lowerRow cells 0 -- FIXME: How to dodge rowspans?
        (rows, width', height') = lowerCells rest
    lowerCells (StyleTree CSSBox { display = TableHeaderGroup } childs:rest) =
        (row, rowwidth) = lowerRow cells 0 h -- FIXME: How to dodge rowspans?
        (rows, width', height') = lowerCells rest $ succ h
    lowerCells (StyleTree CSSBox { display = TableHeaderGroup } childs:rest) h =
        -- Ignore table-header-group styles for now...
        -- Though it'd be nice for this to impact pagination...
        lowerCells (childs ++ rest)
    lowerCells (StyleTree CSSBox { display = TableFooterGroup } childs:rest) =
        lowerCells (childs ++ rest) -- As per TableHeaderGroup
    lowerCells (StyleTree CSSBox { display = TableRowGroup } childs:rest) =
        lowerCells (childs ++ rest) -- As per TableHeaderGroup
    lowerCells (StyleTree CSSBox { display = TableColumnGroup } _:rest) =
        lowerCells rest -- It'd be nice to allow styling based on this...
    lowerCells (StyleTree CSSBox { display = TableColumn } _:rest) =
        lowerCells rest -- As per TableColumnGroup, should be contained within it.
    lowerCells (StyleTree CSSBox { display = TableSummary } _:rest) =
        lowerCells rest -- Handled by callers!
    lowerCells [] = ([], 0, 0)
    lowerCells items = (row:rows, max rowwidth width', succ height)
        lowerCells (childs ++ rest) h
    lowerCells (StyleTree CSSBox { display = TableFooterGroup } childs:rest) h =
        lowerCells (childs ++ rest) h -- As per TableHeaderGroup
    lowerCells (StyleTree CSSBox { display = TableRowGroup } childs:rest) h =
        lowerCells (childs ++ rest) h -- As per TableHeaderGroup
    lowerCells (StyleTree CSSBox { display = TableColumnGroup } _:rest) h =
        lowerCells rest h -- It'd be nice to allow styling based on this...
    lowerCells (StyleTree CSSBox { display = TableColumn } _:rest) h =
        lowerCells rest h -- As per TableColumnGroup, should be contained within.
    lowerCells (StyleTree CSSBox { display = TableCaption } _:rest) h =
        lowerCells rest h -- Handled by callers!
    lowerCells [] h = ([], 0, h)
    lowerCells items h = (row ++ rows, Prelude.max rowwidth width', height')
      where
        (cells, rest) = break isRowGroup items
        (row, rowwidth) = lowerRow cells 0 -- FIXME: How to dodge rowspans?
        (rows, width', height') = lowerCells rest
        (row, rowwidth) = lowerRow cells 0 h -- FIXME: How to dodge rowspans?
        (rows, width', height') = lowerCells rest $ succ h
        isRowGroup (StyleTree CSSBox { display = TableRow } _) = True
        isRowGroup (StyleTree CSSBox { display = TableHeaderGroup } _) = True
        isRowGroup (StyleTree CSSBox { display = TableFooterGroup } _) = True
        isRowGroup (StyleTree CSSBox { display = TableRowGroup } _) = True
        isRowGroup (StyleTree CSSBox { display = TableCaption } _) = True
        isRowGroup _ = False

    lowerRow (StyleTree self'@CSSBox { display = TableCell } childs:rest) ix =
    lowerRow (StyleTree self'@CSSBox { display = TableCell } childs:rest) ix row =
        (cell:cells, width)
      where
        (cells, width) = lowerRow rest end
        (cells, width) = lowerRow rest end row
        end = ix + colspan self'
        cell = (GridItem' ix end _ _ _ `Size` _,
            finalizeCSS __ $ StyleTree self' { display = Block } childs)
    lowerRow (self:rest) ix = (cell:cells, width)
        -- TODO: Add alignment support!
        cell = (GridItem ix end Start 0 0
                `Size` GridItem row (row + rowspan self') Start 0 0,
            finalizeCSS root parent $ StyleTree self' { display = Block } childs)
    lowerRow (self:rest) ix row = (cell:cells, width)
      where
        (cells, width) = lowerRow rest $ succ ix
        cell = (GridItem' ix (succ ix) _ _ _ `Size` _, finalizeCSS __ self)-}
        (ix', row') = (fromEnum ix, fromEnum row)
        (cells, width) = lowerRow rest (succ ix) row
        cell = (GridItem ix' (succ ix') Start 0 0
                `Size` GridItem row' (succ row') Start 0 0,
            finalizeCSS root parent self)
    lowerRow [] ix _ = ([], ix)

M Graphics/Layout/CSS/Parse.hs => Graphics/Layout/CSS/Parse.hs +4 -4
@@ 54,9 54,9 @@ data CSSBox a = CSSBox {
    -- | Parsed text-alignment & other options which applies per-paragraph.
    paragraphOptions :: ParagraphOptions,
    -- | HTML rowspan attribute
    rowspan :: Integer,
    rowspan :: Int,
    -- | HTML colspan attribute
    colspan :: Integer
    colspan :: Int
}
-- | Accessor for inlineStyle's `textDirection` attribute.
direction CSSBox { inlineStyles = CSSInline _ opts _ } = textDirection opts


@@ 264,12 264,12 @@ instance PropertyParser a => PropertyParser (CSSBox a) where
    longhand _ self "-argo-rowspan" [String x]
        | Just y <- readMaybe $ unpack x, y >= 1 = Just self { rowspan = y }
    longhand _ self "-argo-rowspan" [Number _ (NVInteger x)]
        | x >= 1 = Just self { rowspan = x }
        | x >= 1 = Just self { rowspan = fromEnum x }
    longhand _ self "-argo-colspan" [Ident "initial"] = Just self { colspan = 1 }
    longhand _ self "-argo-colspan" [String x]
        | Just y <- readMaybe $ unpack x, y >= 1 = Just self { colspan = y }
    longhand _ self "-argo-colspan" [Number _ (NVInteger x)]
        | x >= 1 = Just self { colspan = x }
        | x >= 1 = Just self { colspan = fromEnum x }

    longhand _ self "caption-side" [Ident "top"] = Just self { captionBelow = False }
    longhand _ self "caption-side" [Ident "bottom"] = Just self { captionBelow = True }