From a510075f8dc411044fd3a3d9f539c0a4c801e736 Mon Sep 17 00:00:00 2001 From: Adrian Cochrane Date: Tue, 11 Apr 2023 12:14:24 +1200 Subject: [PATCH] Reference-document the CSS Box Model datastructures. --- Graphics/Layout/Box.hs | 45 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/Graphics/Layout/Box.hs b/Graphics/Layout/Box.hs index 391f369..666ff3a 100644 --- a/Graphics/Layout/Box.hs +++ b/Graphics/Layout/Box.hs @@ -5,26 +5,45 @@ module Graphics.Layout.Box(Border(..), mapX, mapY, width, height, minWidth, minHeight, maxWidth, maxHeight, Length(..), mapAuto, lowerLength, Zero(..), CastDouble(..)) where +-- | Amount of space surrounding the box. data Border m n = Border { top :: m, bottom :: m, left :: n, right :: n } +-- | Convert horizontal spacing via given callback. mapX :: (n -> nn) -> Border m n -> Border m nn +-- | Convert vertical spacing via given callback. mapY :: (m -> mm) -> Border m n -> Border mm n mapX cb self = self { left = cb $ left self, right = cb $ right self } mapY cb self = self { top = cb $ top self, bottom = cb $ bottom self } +-- | 2D size of a box. Typically inline is width & block is height. +-- This may change as support for vertical layout is added. data Size m n = Size {inline :: n, block :: m} deriving (Eq, Show) +-- | Convert inline size via given callback +mapSizeY :: (m -> mm) -> Size m n -> Size mm n mapSizeY cb self = Size (inline self) (cb $ block self) +-- | Convert block size via given callback +mapSizeX :: (n -> nn) -> Size m n -> Size m nn mapSizeX cb self = Size (cb $ inline self) (block self) +-- | A box with min & max bounds & surrounding borders. The CSS Box Model. data PaddedBox m n = PaddedBox { + -- | The minimum amount of pixels this box should take. min :: Size m n, + -- | The maximum amount of pixels this box should take. max :: Size m n, + -- --| The ideal number of pixels this box should take. + -- nat :: Size Double Double, -- FIXME Use seperate field for natsize. + -- | The amount of pixels this box should take. size :: Size m n, + -- | The amount of space between the box & the border. padding :: Border m n, + -- | The amount of space for the border. border :: Border m n, + -- | The amount of space between the border & anything else. margin :: Border m n } +-- | An empty box, takes up nospace onscreen. zeroBox :: PaddedBox Double Double zeroBox = PaddedBox { min = Size 0 0, @@ -34,6 +53,8 @@ zeroBox = PaddedBox { border = Border 0 0 0 0, margin = Border 0 0 0 0 } +-- | A box which takes up all available space with no borders. +lengthBox :: PaddedBox Length Length lengthBox = PaddedBox { min = Size Auto Auto, max = Size Auto Auto, @@ -43,6 +64,7 @@ lengthBox = PaddedBox { margin = Border zero zero zero zero } +-- | Convert all sizes along the inline axis via given callback. mapX' :: (n -> nn) -> PaddedBox m n -> PaddedBox m nn mapX' cb PaddedBox {..} = PaddedBox { min = Size (cb $ inline min) (block min), @@ -52,6 +74,7 @@ mapX' cb PaddedBox {..} = PaddedBox { border = mapX cb border, margin = mapX cb margin } +-- | Convert all sizes along the block axis via given callback. mapY' :: (m -> mm) -> PaddedBox m n -> PaddedBox mm n mapY' cb PaddedBox {..} = PaddedBox { min = Size (inline min) (cb $ block min), @@ -62,32 +85,50 @@ mapY' cb PaddedBox {..} = PaddedBox { margin = mapY cb margin } +-- | The total size along the inline axis including borders, etc. width PaddedBox {..} = left margin + left border + left padding + inline size + right padding + right border + right margin +-- | The total size along the block axis, including borders, etc. height PaddedBox {..} = top margin + top border + top padding + block size + bottom padding + bottom border + bottom margin +-- | The total minimum size along the inline axis. minWidth PaddedBox {..} = left margin + left border + left padding + inline min + right padding + right border + right margin +-- | The total minimum size along the block axis. minHeight PaddedBox {..} = top margin + top border + top padding + block min + bottom padding + bottom border + bottom margin +-- | The total maximum size along the inline axis. maxWidth PaddedBox {..} = left margin + left border + left padding + inline max + right padding + right border + right margin +-- | The total maximum size along the block axis. maxHeight PaddedBox {..} = top margin + top border + top padding + block max + bottom padding + bottom border + bottom margin -data Length = Pixels Double | Percent Double | Auto | Preferred | Min deriving Eq +-- | A partially-computed length value. +data Length = Pixels Double -- ^ Absolute number of device pixels. + | Percent Double -- ^ Multiplier by container width. + | Auto -- ^ Use normal layout computations. + | Preferred -- ^ Use computed preferred width. + | Min -- ^ Use minimum legible width. + deriving Eq +-- | Convert a length given the container's width. Filling in 0 for keywords. +-- If you wish for keywords to be handled differently, callers need to compute +-- that themselves. lowerLength :: Double -> Length -> Double lowerLength _ (Pixels x) = x lowerLength outerwidth (Percent x) = x * outerwidth lowerLength _ _ = 0 +-- | Replace keywords with a given number of pixels. +-- Useful for avoiding messing up percentage calculations in later processing. mapAuto x Auto = Pixels x mapAuto x Preferred = Pixels x mapAuto x Min = Pixels x mapAuto _ x = x class Zero a where + -- | Return the empty (or zero) value for a CatTrap geometric type. zero :: a instance Zero Double where zero = 0 @@ -103,7 +144,9 @@ instance (Zero m, Zero n) => Zero (PaddedBox m n) where } class CastDouble a where + -- | Convert a double to a double or length. fromDouble :: Double -> a + -- | Convert a double or length to a double. toDouble :: a -> Double instance CastDouble Double where -- 2.30.2