{-# LANGUAGE OverloadedStrings #-}
module Graphics.Layout.Grid.CSS where
import Graphics.Layout.CSS.Internal
import Stylist (PropertyParser(..))
import Data.CSS.Syntax.Tokens (Token(..), NumericValue(..))
import Data.Text (Text)
import qualified Data.Text as Txt
import Data.Char (isAlphaNum)
data CSSGrid = CSSGrid {
autoColumns :: Unitted,
autoFlow :: Axis,
autoFlowDense :: Bool,
autoRows :: Unitted,
templateAreas :: [[Text]],
templateColumns :: Either [([Text], Unitted)] [Text],
templateRows :: Either [([Text], Unitted)] [Text]
}
data Axis = Row | Col
data CSSCell = CSSCell {
columnStart :: Placement,
columnEnd :: Placement,
rowStart :: Placement,
rowEnd :: Placement
}
data Placement = Autoplace | Named Text | Numbered Int (Maybe Text) |
Span Int (Maybe Text)
instance PropertyParser CSSGrid where
temp = CSSGrid {
autoColumns = auto,
autoFlow = Row,
autoFlowDense = False,
autoRows = auto,
templateAreas = [],
templateColumns = Left [],
templateRows = Left []
}
inherit _ = temp
longhand _ s "grid-auto-columns" toks | Just x <- parseFR toks = Just s {autoColumns=x}
longhand _ s "grid-auto-rows" toks | Just x <- parseFR toks = Just s {autoColumns = x}
longhand _ self "grid-auto-flow" [Ident "row"] = Just self {
autoFlow = Row, autoFlowDense = False
}
longhand _ self "grid-auto-flow" [Ident "column"] = Just self {
autoFlow = Col, autoFlowDense = False
}
longhand _ self "grid-auto-flow" [Ident "row", Ident "dense"] = Just self {
autoFlow = Row, autoFlowDense = True
}
longhand _ self "grid-auto-flow" [Ident "column", Ident "dense"] = Just self {
autoFlow = Col, autoFlowDense = True
}
longhand _ self "grid-template-areas" [Ident "none"] = Just self {templateAreas = []}
longhand _ self "grid-template-areas" [Ident "initial"] = Just self {templateAreas=[]}
longhand _ self "grid-template-areas" toks
| all isString toks, validate [Txt.words x | String x <- toks] =
Just self { templateAreas = [Txt.words x | String x <- toks] }
where
isString (String _) = True
isString _ = False
validate grid@(row:rows) =
all isValidName (concat grid) && all (\x -> length row == length x) rows
validate [] = False
isValidName name = Txt.all (\c -> isAlphaNum c || c == '-') name
longhand _ self "grid-template-columns" toks | Just x <- parseTemplate toks =
Just self { templateColumns = x }
longhand _ self "grid-template-rows" toks | Just x <- parseTemplate toks =
Just self { templateRows = x}
longhand _ _ _ _ = Nothing
instance PropertyParser CSSCell where
temp = CSSCell {
columnStart = Autoplace,
columnEnd = Autoplace,
rowStart = Autoplace,
rowEnd = Autoplace
}
inherit _ = temp
longhand _ self "grid-column-start" toks | Just x <- placement toks =
Just self { columnStart = x}
longhand _ s "grid-column-end" toks | Just x <- placement toks = Just s {columnEnd=x}
longhand _ s "grid-row-start" toks | Just x <- placement toks = Just s {rowStart = x}
longhand _ s "grid-row-end" toks | Just x <- placement toks = Just s { rowEnd = x }
longhand _ _ _ _ = Nothing
{-finalizeGrid :: CSSBox -> LayoutItem Length-}
parseFR [Dimension _ x "fr"] = Just (n2f x,"fr")
parseFR toks = parseLength toks
parseFR' [Dimension _ x "fr"] = Just (n2f x,"fr")
parseFR' toks = parseLength' toks
placement [Ident "auto"] = Just $ Autoplace
placement [Ident x] = Just $ Named x
placement [Number _ (NVInteger x)] = Just $ Numbered (fromEnum x) Nothing
placement [Number _ (NVInteger x), Ident y] = Just $ Numbered (fromEnum x) (Just y)
placement [Ident "span", Number _ (NVInteger x)]
| x > 0 = Just $ Span (fromEnum x) Nothing
placement [Ident "span", Ident x] = Just $ Span 1 $ Just x
placement [Ident "span", Number _ (NVInteger x), Ident y]
| x > 0 = Just $ Span (fromEnum x) (Just y)
placement [Ident "span", Ident y, Number _ (NVInteger x)]
| x > 0 = Just $ Span (fromEnum x) (Just y)
placement _ = Nothing
parseTemplate [Ident "none"] = Just $ Left []
parseTemplate [Ident "initial"] = Just $ Left []
parseTemplate toks | (tracks@(_:_), []) <- parseTrack toks = Just $ Left tracks
parseTemplate (Ident "subgrid":toks)
| (names@(_:_), []) <- parseSubgrid toks = Just $ Right names
parseTemplate _ = Nothing
parseTrack (LeftSquareBracket:toks)
| Just (names', toks') <- parseNames toks,
((names,size):cells,toks) <- parseTrack toks' = ((names' ++ names,size):cells,toks)
| Just (names', toks') <- parseNames toks = ([(names',(0,"end"))],toks')
parseTrack (tok:toks) | Just x <- parseFR' [tok] =
(([], x):fst (parseTrack toks), snd $ parseTrack toks)
parseTrack (Function "repeat":Number _ (NVInteger x):Comma:toks)
| x > 0, (tracks@(_:_), RightParen:toks') <- parseTrack toks =
(concat $ replicate (fromEnum x) tracks, toks')
parseTrack toks = ([], toks)
parseSubgrid (LeftSquareBracket:toks)
| Just (names', toks') <- parseNames toks, (names,toks'') <- parseSubgrid toks' =
(names' ++ names, toks')
parseSubgrid (Function "repeat":Number _ (NVInteger x):Comma:toks)
| x > 0, (names@(_:_), RightParen:toks') <- parseSubgrid toks =
(concat $ replicate (fromEnum x) names, toks')
parseSubgrid toks = ([], toks)
parseNames (Ident x:toks)
| Just (names,toks') <- parseNames toks = Just (x:names,toks')
parseNames (RightSquareBracket:toks) = Just ([], toks)
parseNames _ = Nothing