{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

-- |
-- Module      : FULE.Container.Padded
-- Description : The @Padded@ Container.
-- Copyright   : (c) Paul Schnapp, 2023
-- License     : BSD3
-- Maintainer  : Paul Schnapp <paul.schnapp@gmail.com>
--
-- A 'FULE.Container.Container' to add padding around content.
module FULE.Container.Padded
 ( Padded
 , padded
 ) where

import FULE.Component
import FULE.Container
import FULE.Container.Config
import FULE.Layout
import FULE.LayoutOp


-- | A container with padding around the content.
data Padded c
  = Padded
    { forall c. Padded c -> Int
horizPaddingOf :: Int
    , forall c. Padded c -> Int
vertPaddingOf :: Int
    , forall c. Padded c -> c
contentsOf :: c
    }

instance (Container c k m) => Container (Padded c) k m where
  minWidth :: Padded c -> Proxy k -> m (Maybe Int)
minWidth (Padded Int
h Int
_ c
c) Proxy k
proxy = (Int -> Int) -> Maybe Int -> Maybe Int
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
h) (Maybe Int -> Maybe Int) -> m (Maybe Int) -> m (Maybe Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> c -> Proxy k -> m (Maybe Int)
forall c k (m :: * -> *).
Container c k m =>
c -> Proxy k -> m (Maybe Int)
minWidth c
c Proxy k
proxy
  minHeight :: Padded c -> Proxy k -> m (Maybe Int)
minHeight (Padded Int
_ Int
v c
c) Proxy k
proxy = (Int -> Int) -> Maybe Int -> Maybe Int
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
v) (Maybe Int -> Maybe Int) -> m (Maybe Int) -> m (Maybe Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> c -> Proxy k -> m (Maybe Int)
forall c k (m :: * -> *).
Container c k m =>
c -> Proxy k -> m (Maybe Int)
minHeight c
c Proxy k
proxy
  addToLayout :: Padded c -> Proxy k -> Bounds -> Maybe Int -> LayoutOp k m ()
addToLayout (Padded Int
h Int
v c
c) Proxy k
proxy Bounds
bounds Maybe Int
renderGroup = do
    let Bounds GuideID
t GuideID
l GuideID
r GuideID
b Maybe Bounds
cl = Bounds
bounds
    GuideID
t' <- if Int
v Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then GuideID
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall a. a -> StateT LayoutOpState (WriterT [ComponentInfo k] m) a
forall (m :: * -> *) a. Monad m => a -> m a
return GuideID
t else GuideSpecification
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall (m :: * -> *) k.
Monad m =>
GuideSpecification -> LayoutOp k m GuideID
addGuideToLayout (GuideSpecification
 -> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID)
-> GuideSpecification
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall a b. (a -> b) -> a -> b
$ Int -> GuideID -> PlasticDependencyType -> GuideSpecification
Relative Int
v GuideID
t PlasticDependencyType
Asymmetric
    GuideID
l' <- if Int
h Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then GuideID
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall a. a -> StateT LayoutOpState (WriterT [ComponentInfo k] m) a
forall (m :: * -> *) a. Monad m => a -> m a
return GuideID
l else GuideSpecification
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall (m :: * -> *) k.
Monad m =>
GuideSpecification -> LayoutOp k m GuideID
addGuideToLayout (GuideSpecification
 -> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID)
-> GuideSpecification
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall a b. (a -> b) -> a -> b
$ Int -> GuideID -> PlasticDependencyType -> GuideSpecification
Relative Int
h GuideID
l PlasticDependencyType
Asymmetric
    GuideID
r' <- if Int
h Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then GuideID
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall a. a -> StateT LayoutOpState (WriterT [ComponentInfo k] m) a
forall (m :: * -> *) a. Monad m => a -> m a
return GuideID
r else GuideSpecification
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall (m :: * -> *) k.
Monad m =>
GuideSpecification -> LayoutOp k m GuideID
addGuideToLayout (GuideSpecification
 -> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID)
-> GuideSpecification
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall a b. (a -> b) -> a -> b
$ Int -> GuideID -> PlasticDependencyType -> GuideSpecification
Relative (-Int
h) GuideID
r PlasticDependencyType
Asymmetric
    GuideID
b' <- if Int
v Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then GuideID
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall a. a -> StateT LayoutOpState (WriterT [ComponentInfo k] m) a
forall (m :: * -> *) a. Monad m => a -> m a
return GuideID
b else GuideSpecification
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall (m :: * -> *) k.
Monad m =>
GuideSpecification -> LayoutOp k m GuideID
addGuideToLayout (GuideSpecification
 -> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID)
-> GuideSpecification
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) GuideID
forall a b. (a -> b) -> a -> b
$ Int -> GuideID -> PlasticDependencyType -> GuideSpecification
Relative (-Int
v) GuideID
b PlasticDependencyType
Asymmetric
    let bounds' :: Bounds
bounds' = GuideID -> GuideID -> GuideID -> GuideID -> Maybe Bounds -> Bounds
Bounds GuideID
t' GuideID
l' GuideID
r' GuideID
b' Maybe Bounds
cl
    c -> Proxy k -> Bounds -> Maybe Int -> LayoutOp k m ()
forall c k (m :: * -> *).
Container c k m =>
c -> Proxy k -> Bounds -> Maybe Int -> LayoutOp k m ()
addToLayout c
c Proxy k
proxy Bounds
bounds' Maybe Int
renderGroup

-- | Create a container with padding around the content.
padded :: Padding -> c -> Padded c
padded :: forall c. Padding -> c -> Padded c
padded (Int
horiz, Int
vert) = Int -> Int -> c -> Padded c
forall c. Int -> Int -> c -> Padded c
Padded (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
horiz) (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
vert)