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

-- |
-- Module      : FULE.Container.Unreckoned
-- Description : The @Unreckoned@ Container.
-- Copyright   : (c) Paul Schnapp, 2023
-- License     : BSD3
-- Maintainer  : Paul Schnapp <paul.schnapp@gmail.com>
--
-- A 'FULE.Container.Container' to remove dimension info from content when it's
-- considered during the layout process.
--
-- To /add/ size to content, see the 'FULE.Container.Sized.Sized' container.
module FULE.Container.Unreckoned
 ( Unreckoned
 , unreckonedHoriz
 , unreckonedVert
 , unreckoned
 ) where

import Control.Monad.Trans.Class
import Data.Maybe

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


-- | A container complementary to 'FULE.Container.Sized.Sized': whereas @Sized@
--   specifies a size for content which may or may not already have one,
--   @Unreckoned@ /removes/ size associated with content as it is reckoned
--   in the layout. This allows for content to overflow its bounds as far as the
--   layout is concerned.
--
--   The 'FULE.Component.Bounds' in the 'FULE.Component.ComponentInfo' for a
--   'FULE.Component.Component' which is @Unreckoned@ will match the overflowing
--   size of the @Component@ even though the size was not taken into account
--   during the layout process itself.
data Unreckoned c = Unreckoned (Maybe Orientation) c

instance (Container c k m) => Container (Unreckoned c) k m where
  minWidth :: Unreckoned c -> Proxy k -> m (Maybe Int)
minWidth (Unreckoned Maybe Orientation
o c
c) Proxy k
proxy = case Maybe Orientation
o of
    Just Orientation
Vertical -> 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
    Maybe Orientation
_ -> Maybe Int -> m (Maybe Int)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Int
forall a. Maybe a
Nothing
  minHeight :: Unreckoned c -> Proxy k -> m (Maybe Int)
minHeight (Unreckoned Maybe Orientation
o c
c) Proxy k
proxy = case Maybe Orientation
o of
    Just Orientation
Horizontal -> 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
    Maybe Orientation
_ -> Maybe Int -> m (Maybe Int)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Int
forall a. Maybe a
Nothing
  addToLayout :: Unreckoned c -> Proxy k -> Bounds -> Maybe Int -> LayoutOp k m ()
addToLayout (Unreckoned Maybe Orientation
_ c
c) Proxy k
proxy Bounds
bounds Maybe Int
renderGroup = do
    Maybe Int
reqWidth <- WriterT [ComponentInfo k] m (Maybe Int)
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int)
forall (m :: * -> *) a. Monad m => m a -> StateT LayoutOpState m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (WriterT [ComponentInfo k] m (Maybe Int)
 -> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int))
-> (m (Maybe Int) -> WriterT [ComponentInfo k] m (Maybe Int))
-> m (Maybe Int)
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m (Maybe Int) -> WriterT [ComponentInfo k] m (Maybe Int)
forall (m :: * -> *) a.
Monad m =>
m a -> WriterT [ComponentInfo k] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe Int)
 -> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int))
-> m (Maybe Int)
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int)
forall a b. (a -> b) -> a -> 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
    Maybe Int
reqHeight <- WriterT [ComponentInfo k] m (Maybe Int)
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int)
forall (m :: * -> *) a. Monad m => m a -> StateT LayoutOpState m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (WriterT [ComponentInfo k] m (Maybe Int)
 -> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int))
-> (m (Maybe Int) -> WriterT [ComponentInfo k] m (Maybe Int))
-> m (Maybe Int)
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m (Maybe Int) -> WriterT [ComponentInfo k] m (Maybe Int)
forall (m :: * -> *) a.
Monad m =>
m a -> WriterT [ComponentInfo k] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Maybe Int)
 -> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int))
-> m (Maybe Int)
-> StateT LayoutOpState (WriterT [ComponentInfo k] m) (Maybe Int)
forall a b. (a -> b) -> a -> 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
    let Bounds GuideID
t GuideID
l GuideID
r GuideID
b Maybe Bounds
cl = Bounds
bounds
    GuideID
right <- GuideSpecification -> LayoutOp k m GuideID
forall (m :: * -> *) k.
Monad m =>
GuideSpecification -> LayoutOp k m GuideID
addGuideToLayout (GuideSpecification -> LayoutOp k m GuideID)
-> GuideSpecification -> LayoutOp k m GuideID
forall a b. (a -> b) -> a -> b
$ Int -> GuideID -> PlasticDependencyType -> GuideSpecification
Relative (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 Maybe Int
reqWidth) GuideID
l PlasticDependencyType
Asymmetric
    GuideID
bottom <- GuideSpecification -> LayoutOp k m GuideID
forall (m :: * -> *) k.
Monad m =>
GuideSpecification -> LayoutOp k m GuideID
addGuideToLayout (GuideSpecification -> LayoutOp k m GuideID)
-> GuideSpecification -> LayoutOp k m GuideID
forall a b. (a -> b) -> a -> b
$ Int -> GuideID -> PlasticDependencyType -> GuideSpecification
Relative (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 Maybe Int
reqHeight) GuideID
t PlasticDependencyType
Asymmetric
    let bounds :: Bounds
bounds = GuideID -> GuideID -> GuideID -> GuideID -> Maybe Bounds -> Bounds
Bounds GuideID
t GuideID
l GuideID
right GuideID
bottom 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

-- | Elide the horizontal size of the content.
unreckonedHoriz :: c -> Unreckoned c
unreckonedHoriz :: forall c. c -> Unreckoned c
unreckonedHoriz = Maybe Orientation -> c -> Unreckoned c
forall c. Maybe Orientation -> c -> Unreckoned c
Unreckoned (Orientation -> Maybe Orientation
forall a. a -> Maybe a
Just Orientation
Horizontal)

-- | Elide the verital size of the content.
unreckonedVert :: c -> Unreckoned c
unreckonedVert :: forall c. c -> Unreckoned c
unreckonedVert = Maybe Orientation -> c -> Unreckoned c
forall c. Maybe Orientation -> c -> Unreckoned c
Unreckoned (Orientation -> Maybe Orientation
forall a. a -> Maybe a
Just Orientation
Vertical)

-- | Elide all sizes associated with the content.
unreckoned :: c -> Unreckoned c
unreckoned :: forall c. c -> Unreckoned c
unreckoned = Maybe Orientation -> c -> Unreckoned c
forall c. Maybe Orientation -> c -> Unreckoned c
Unreckoned Maybe Orientation
forall a. Maybe a
Nothing