From 7301a4893d99b4a5bf016000097369b492f23aea Mon Sep 17 00:00:00 2001 From: Adrian Cochrane Date: Tue, 14 Nov 2023 12:32:39 +1300 Subject: [PATCH] Integrate flexbox CSS property parsing. --- Graphics/Layout.hs | 2 ++ Graphics/Layout/CSS.hs | 11 +++++++++++ Graphics/Layout/CSS/Parse.hs | 27 ++++++++++++++++++++++----- Graphics/Layout/Flex.hs | 10 ++++++---- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/Graphics/Layout.hs b/Graphics/Layout.hs index 7bdfcab..3083b76 100644 --- a/Graphics/Layout.hs +++ b/Graphics/Layout.hs @@ -23,6 +23,7 @@ import Graphics.Layout.Grid as G import Graphics.Layout.Flow as F import Graphics.Layout.Inline as I import Graphics.Layout.CSS.Font (Font'(..)) +import Graphics.Layout.Flex as Fl import Data.Maybe (fromMaybe) @@ -57,6 +58,7 @@ data LayoutItem m n x = | LayoutConst x (PaddedBox m n) [LayoutItem m n x] -- | Children of a `LayoutInline` or `LayoutInline'`. | LayoutSpan (FragmentTree (UserData m n x)) + | LayoutFlex x (PaddedBox m n) (FlexParent (LayoutItem m n x) m) deriving (Show, Eq) -- | An empty box. nullLayout :: (PropertyParser x, Zero m, Zero n) => LayoutItem m n x diff --git a/Graphics/Layout/CSS.hs b/Graphics/Layout/CSS.hs index 7ba62ed..e405b1f 100644 --- a/Graphics/Layout/CSS.hs +++ b/Graphics/Layout/CSS.hs @@ -20,6 +20,7 @@ import Graphics.Layout.Grid.CSS import Graphics.Layout.Grid import Graphics.Layout.Grid.Table import Graphics.Layout.Inline.CSS +import Graphics.Layout.Flex.CSS import Data.Char (isSpace) import Graphics.Layout.CSS.Parse @@ -69,6 +70,16 @@ finalizeCSS root parent self@StyleTree { | child@StyleTree { style = child'@CSSBox { display = TableCaption } } <- childs]) where font_ = pattern2font (font self') (font' self') parent root +finalizeCSS root parent self@StyleTree { + style = self'@CSSBox { display = Flex, flexOptions = flex }, + children = childs + } = LayoutFlex (inner' font_ self' ) (finalizeBox self' font_) $ + lowerFlex flex font_ (map flexOptions childs') + (flip map childs $ finalizeCSS root font_) (map style2font childs') + where + font_ = style2font self' + style2font style = pattern2font (font style) (font' style) parent root + childs' = map style childs finalizeCSS root parent self@StyleTree { style = self', children = childs } = LayoutFlow (inner' font_ self') (finalizeBox self' font_) diff --git a/Graphics/Layout/CSS/Parse.hs b/Graphics/Layout/CSS/Parse.hs index 0456efc..54d95b1 100644 --- a/Graphics/Layout/CSS/Parse.hs +++ b/Graphics/Layout/CSS/Parse.hs @@ -16,6 +16,7 @@ import Graphics.Layout.CSS.Font (CSSFont) import Graphics.Layout.Grid.CSS (CSSGrid(..), CSSCell(..), Placement(..)) import Graphics.Layout.Grid.Table (TableOptions) import Graphics.Layout.Inline.CSS (CSSInline(..)) +import Graphics.Layout.Flex.CSS (CSSFlex(..)) import Data.Maybe (isJust, fromMaybe) import Text.Read (readMaybe) @@ -54,8 +55,12 @@ data CSSBox a = CSSBox { paragraphOptions :: ParagraphOptions, -- | (Semi-)parsed CSS properties & HTML attributes relating to laying out -- HTML table elements. - tableOptions :: TableOptions + tableOptions :: TableOptions, + -- | Semi-parsed CSS properties relating to FlexBox layouts. + flexOptions :: CSSFlex } +-- | FlexOptions getter with `textLTR` set +flexOpts' self@CSSBox { flexOptions = ret } = ret { textRTL = direction self == DirRTL } -- | Accessor for inlineStyle's `textDirection` attribute. direction CSSBox { inlineStyles = CSSInline _ opts _ } = textDirection opts -- | Accessor for inlineStyle's options. @@ -68,7 +73,7 @@ noborder = Border (0,"px") (0,"px") (0,"px") (0,"px") -- | Possibly values for CSS display property. data Display = Block | Grid | Inline | Table | None | TableRow | TableHeaderGroup | TableRowGroup | TableFooterGroup | TableCell | - TableColumn | TableColumnGroup | TableCaption deriving Eq + TableColumn | TableColumnGroup | TableCaption | Flex deriving Eq -- | Can the display value contain table-rows? rowContainer CSSBox { display = d } = d `elem` [Table, TableHeaderGroup, TableRowGroup, TableFooterGroup] @@ -99,7 +104,8 @@ instance PropertyParser a => PropertyParser (CSSBox a) where paragraphOptions = defaultParagraphOptions { paragraphAlignment = AlignStart }, - tableOptions = temp + tableOptions = temp, + flexOptions = temp } inherit parent = CSSBox { boxSizing = boxSizing parent, @@ -115,9 +121,11 @@ instance PropertyParser a => PropertyParser (CSSBox a) where inlineStyles = inherit $ inlineStyles parent, pageOptions = pageOptions parent, paragraphOptions = paragraphOptions parent, - tableOptions = inherit $ tableOptions parent + tableOptions = inherit $ tableOptions parent, + flexOptions = inherit $ flexOptions parent } - priority self = concat [x font, x font', x gridStyles, x cellStyles, x inner] + priority self = concat [x inlineStyles, x font, x font', x gridStyles, + x cellStyles, x flexOptions, x inner] where x getter = priority $ getter self -- Wasn't sure how to implement in FontConfig-Pure @@ -254,6 +262,7 @@ instance PropertyParser a => PropertyParser (CSSBox a) where longhand CSSBox { display = Table } self "display" [Ident "table-caption"] = Just self { display=TableCaption } longhand _ self "display" [Ident "inline"] = Just self { display = Inline } + longhand _ self "display" [Ident "flex"] = Just self { display = Flex } longhand _ self "display" [Ident "initial"] = Just self { display = Inline } longhand _ self "orphans" [Number _ (NVInteger x)] = @@ -294,12 +303,20 @@ instance PropertyParser a => PropertyParser (CSSBox a) where } longhand a b c d | Just inline' <- longhand (inlineStyles a) (inlineStyles b) c d = Just b { inlineStyles = inline' } + longhand a b c d | Just grid' <- longhand (gridStyles a) (gridStyles b) c d, + Just flex' <- longhand (flexOpts' a) (flexOpts' b) c d = + Just b { gridStyles = grid', flexOptions = flex' } + longhand a b c d | Just cell' <- longhand (cellStyles a) (cellStyles b) c d, + Just flex' <- longhand (flexOpts' a) (flexOpts' b) c d = + Just b { cellStyles = cell', flexOptions = flex' } longhand a b c d | Just grid' <- longhand (gridStyles a) (gridStyles b) c d = Just b { gridStyles = grid' } longhand a b c d | Just cell' <- longhand (cellStyles a) (cellStyles b) c d = Just b { cellStyles = cell' } longhand a b c d | Just table'<-longhand (tableOptions a) (tableOptions b) c d = Just b { tableOptions = table' } + longhand a b c d | Just flex' <- longhand (flexOpts' a) (flexOpts' b) c d = + Just b { flexOptions = flex' } longhand a b c d | (d', _:_)<-testLengthProp d, Just _<-longhand (inner a) (inner b) c d' = Just b { diff --git a/Graphics/Layout/Flex.hs b/Graphics/Layout/Flex.hs index 327698f..74cc479 100644 --- a/Graphics/Layout/Flex.hs +++ b/Graphics/Layout/Flex.hs @@ -15,19 +15,21 @@ data FlexParent a b = FlexParent { baseGap :: b, crossGap :: b, children :: [[FlexChild a b]] -- 2D list to store lines once split. -} +} deriving (Eq, Show, Read) data FlexChild a b = FlexChild { grow :: Double, shrink :: Double, basis :: b, alignment :: Alignment, flexInner :: a -} +} deriving (Eq, Show, Read) -data Direction = Row | Column -data FlexWrapping = NoWrap | Wrap | WrapReverse +data Direction = Row | Column deriving (Eq, Show, Read) +data FlexWrapping = NoWrap | Wrap | WrapReverse deriving (Eq, Show, Read) data Justification = JStart | JEnd | JCenter | JSpaceBetween | JSpaceAround | JSpaceEvenly + deriving (Eq, Show, Read) data Alignment = AlStretch | AlStart | AlEnd | AlCenter | AlBaseline + deriving (Eq, Show, Read) flexMaxBasis :: FlexParent a Length -> Double -> Double flexMaxBasis self outersize = maximum [lowerLength outersize $ basis child | -- 2.30.2