content: {-# LANGUAGE NoImplicitPrelude #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE TypeSynonymInstances #-}
  module Graphics.Blank.Types.CSS where
  
  import           Data.String
  
  import           Graphics.Blank.JavaScript
  import           Graphics.Blank.Parser
  import           Graphics.Blank.Types
  import           Graphics.Blank.Instr
  
  import           Prelude.Compat
  
  import           Text.ParserCombinators.ReadP (choice)
  import           Text.ParserCombinators.ReadPrec (lift)
  import           Text.Read (Read(..), readListPrecDefault)
  
  import           TextShow (TextShow(..), FromTextShow(..))
  
  -- | Denotes CSS distance measurements, especially in the context of 'Font's.
  data Length = Em   { runLength :: Double } -- ^ The height of the current font.
              | Ex   { runLength :: Double } -- ^ The height of the character @x@ (x-height) in the current font.
              | Ch   { runLength :: Double } -- ^ The width of the character @0@ in the current font.
              | Rem  { runLength :: Double } -- ^ The height of the font relative to the root element.
              | Vh   { runLength :: Double } -- ^ One percent of the height of the viewport.
              | Vw   { runLength :: Double } -- ^ One percent of the width of the viewport.
              | Vmin { runLength :: Double } -- ^ One percent of the minimum of the viewport height and width.
              | Vmax { runLength :: Double } -- ^ One percent of the maximum of the viewport height and width.
              | Px   { runLength :: Double } -- ^ One device pixel (dot) of the display.
              | Mm   { runLength :: Double } -- ^ One millimeter.
              | Cm   { runLength :: Double } -- ^ One centimeter (10 millimeters).
              | In   { runLength :: Double } -- ^ One inch (~2.54 centimeters).
              | Pt   { runLength :: Double } -- ^ One point (1/72 inches).
              | Pc   { runLength :: Double } -- ^ One pica (12 points).
    deriving (Eq, Ord)
  
  -- | Designates CSS properties that can consist of a 'Length'.
  class LengthProperty a where
      -- Create a CSS property value from a 'Length'.
      fromLength :: Length -> a
  
  instance LengthProperty Length where
      fromLength = id
  
  -- | Constructs a 'LengthProperty' value with 'Em' units.
  em :: LengthProperty a => Double -> a
  em = fromLength . Em
  
  -- | Constructs a 'LengthProperty' value with 'Ex' units.
  ex :: LengthProperty a => Double -> a
  ex = fromLength . Ex
  
  -- | Constructs a 'LengthProperty' value with 'Ch' units.
  ch :: LengthProperty a => Double -> a
  ch = fromLength . Ch
  
  -- | Constructs a 'LengthProperty' value with 'Rem' units. 'rem_' has an underscore
  -- to distinguish it from 'rem'.
  rem_ :: LengthProperty a => Double -> a
  rem_ = fromLength . Rem
  
  -- | Constructs a 'LengthProperty' value with 'Vh' units.
  vh :: LengthProperty a => Double -> a
  vh = fromLength . Vh
  
  -- | Constructs a 'LengthProperty' value with 'Vw' units.
  vw :: LengthProperty a => Double -> a
  vw = fromLength . Vw
  
  -- | Constructs a 'LengthProperty' value with 'Em' units.
  vmin :: LengthProperty a => Double -> a
  vmin = fromLength . Vmin
  
  -- | Constructs a 'LengthProperty' value with 'Vmax' units.
  vmax :: LengthProperty a => Double -> a
  vmax = fromLength . Vmax
  
  -- | Constructs a 'LengthProperty' value with 'Px' units.
  px :: LengthProperty a => Double -> a
  px = fromLength . Px
  
  -- | Constructs a 'LengthProperty' value with 'Mm' units.
  mm :: LengthProperty a => Double -> a
  mm = fromLength . Mm
  
  -- | Constructs a 'LengthProperty' value with 'Cm' units.
  cm :: LengthProperty a => Double -> a
  cm = fromLength . Cm
  
  -- | Constructs a 'LengthProperty' value with 'Im' units. This function has an
  --   underscore to distinguish it from the Haskell keyword.
  in_ :: LengthProperty a => Double -> a
  in_ = fromLength . In
  
  -- | Constructs a 'LengthProperty' value with 'Pt' units.
  pt :: LengthProperty a => Double -> a
  pt = fromLength . Pt
  
  -- | Constructs a 'LengthProperty' value with 'Pc' units.
  pc :: LengthProperty a => Double -> a
  pc = fromLength . Pc
  
  instance IsString Length where
      fromString = read
  
  instance Read Length where
      readPrec = do
          d <- readPrec
          lift $ choice
              [ Em d   <$ stringCI "em"
              , Ex d   <$ stringCI "ex"
              , Ch d   <$ stringCI "ch"
              , Rem d  <$ stringCI "rem"
              , Vh d   <$ stringCI "vh"
              , Vw d   <$ stringCI "vw"
              , Vmin d <$ stringCI "vmin"
              , Vmax d <$ stringCI "vmax"
              , Px d   <$ stringCI "px"
              , Mm d   <$ stringCI "mm"
              , Cm d   <$ stringCI "cm"
              , In d   <$ stringCI "in"
              , Pt d   <$ stringCI "pt"
              , Pc d   <$ stringCI "pc"
              ]
      readListPrec = readListPrecDefault
  
  instance Show Length where
      showsPrec p = showsPrec p . FromTextShow
  
  instance TextShow Length where
      showb l = toBuilder (jsDouble (runLength l)) <> showbUnits l
        where
          showbUnits (Em   _) = "em"
          showbUnits (Ex   _) = "ex"
          showbUnits (Ch   _) = "ch"
          showbUnits (Rem  _) = "rem"
          showbUnits (Vh   _) = "vh"
          showbUnits (Vw   _) = "vw"
          showbUnits (Vmin _) = "vmin"
          showbUnits (Vmax _) = "vmax"
          showbUnits (Px   _) = "px"
          showbUnits (Mm   _) = "mm"
          showbUnits (Cm   _) = "cm"
          showbUnits (In   _) = "in"
          showbUnits (Pt   _) = "pt"
          showbUnits (Pc   _) = "pc"
  
  instance InstrShow Length
  
  -- | Designates CSS properties that can consist of a 'Percentage'.
  class PercentageProperty a where
      -- | Create a CSS property value from a 'Percentage'.
      percent :: Percentage -> a
  
  instance PercentageProperty Percentage where
      percent = id
  