{-# LANGUAGE BangPatterns #-}
module Brick.Widgets.Internal
  ( renderFinal
  , cropToContext
  , cropResultToContext
  , renderDynBorder
  , renderWidget
  )
where

import Lens.Micro ((^.), (&), (%~))
import Lens.Micro.Mtl ((%=))
import Control.Monad
import Control.Monad.State.Strict
import Control.Monad.Reader
import Data.Maybe (fromMaybe, mapMaybe)
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Graphics.Vty as V

import Brick.Types
import Brick.Types.Internal
import Brick.AttrMap
import Brick.Widgets.Border.Style
import Brick.BorderMap (BorderMap)
import qualified Brick.BorderMap as BM

renderFinal :: (Ord n)
            => AttrMap
            -> [Widget n]
            -> V.DisplayRegion
            -> ([CursorLocation n] -> Maybe (CursorLocation n))
            -> RenderState n
            -> (RenderState n, V.Picture, Maybe (CursorLocation n), [Extent n])
renderFinal :: forall n.
Ord n =>
AttrMap
-> [Widget n]
-> DisplayRegion
-> ([CursorLocation n] -> Maybe (CursorLocation n))
-> RenderState n
-> (RenderState n, Picture, Maybe (CursorLocation n), [Extent n])
renderFinal AttrMap
aMap [Widget n]
layerRenders (Int
w, Int
h) [CursorLocation n] -> Maybe (CursorLocation n)
chooseCursor RenderState n
rs =
    (RenderState n
newRS, Picture
picWithBg, Maybe (CursorLocation n)
theCursor, [[Extent n]] -> [Extent n]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Extent n]]
layerExtents)
    where
        ([Result n]
layerResults, !RenderState n
newRS) = (State (RenderState n) [Result n]
 -> RenderState n -> ([Result n], RenderState n))
-> RenderState n
-> State (RenderState n) [Result n]
-> ([Result n], RenderState n)
forall a b c. (a -> b -> c) -> b -> a -> c
flip State (RenderState n) [Result n]
-> RenderState n -> ([Result n], RenderState n)
forall s a. State s a -> s -> (a, s)
runState RenderState n
rs (State (RenderState n) [Result n] -> ([Result n], RenderState n))
-> State (RenderState n) [Result n] -> ([Result n], RenderState n)
forall a b. (a -> b) -> a -> b
$ [StateT (RenderState n) Identity (Result n)]
-> State (RenderState n) [Result n]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([StateT (RenderState n) Identity (Result n)]
 -> State (RenderState n) [Result n])
-> [StateT (RenderState n) Identity (Result n)]
-> State (RenderState n) [Result n]
forall a b. (a -> b) -> a -> b
$
            (\ReaderT (Context n) (StateT (RenderState n) Identity) (Result n)
p -> ReaderT (Context n) (StateT (RenderState n) Identity) (Result n)
-> Context n -> StateT (RenderState n) Identity (Result n)
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT (Context n) (StateT (RenderState n) Identity) (Result n)
p Context n
forall {n}. Context n
ctx) (ReaderT (Context n) (StateT (RenderState n) Identity) (Result n)
 -> StateT (RenderState n) Identity (Result n))
-> (Widget n
    -> ReaderT
         (Context n) (StateT (RenderState n) Identity) (Result n))
-> Widget n
-> StateT (RenderState n) Identity (Result n)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
            (\Widget n
layerWidget -> do
                Result n
result <- Widget n
-> ReaderT (Context n) (StateT (RenderState n) Identity) (Result n)
forall n. Widget n -> RenderM n (Result n)
render (Widget n
 -> ReaderT
      (Context n) (StateT (RenderState n) Identity) (Result n))
-> Widget n
-> ReaderT (Context n) (StateT (RenderState n) Identity) (Result n)
forall a b. (a -> b) -> a -> b
$ Widget n -> Widget n
forall n. Widget n -> Widget n
cropToContext Widget n
layerWidget
                [Extent n]
-> (Extent n
    -> ReaderT (Context n) (StateT (RenderState n) Identity) ())
-> ReaderT (Context n) (StateT (RenderState n) Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Result n
resultResult n -> Getting [Extent n] (Result n) [Extent n] -> [Extent n]
forall s a. s -> Getting a s a -> a
^.Getting [Extent n] (Result n) [Extent n]
forall n (f :: * -> *).
Functor f =>
([Extent n] -> f [Extent n]) -> Result n -> f (Result n)
extentsL) ((Extent n
  -> ReaderT (Context n) (StateT (RenderState n) Identity) ())
 -> ReaderT (Context n) (StateT (RenderState n) Identity) ())
-> (Extent n
    -> ReaderT (Context n) (StateT (RenderState n) Identity) ())
-> ReaderT (Context n) (StateT (RenderState n) Identity) ()
forall a b. (a -> b) -> a -> b
$ \Extent n
e ->
                    (Map n (Extent n) -> Identity (Map n (Extent n)))
-> RenderState n -> Identity (RenderState n)
forall n (f :: * -> *).
Functor f =>
(Map n (Extent n) -> f (Map n (Extent n)))
-> RenderState n -> f (RenderState n)
reportedExtentsL ((Map n (Extent n) -> Identity (Map n (Extent n)))
 -> RenderState n -> Identity (RenderState n))
-> (Map n (Extent n) -> Map n (Extent n))
-> ReaderT (Context n) (StateT (RenderState n) Identity) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= n -> Extent n -> Map n (Extent n) -> Map n (Extent n)
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert (Extent n -> n
forall n. Extent n -> n
extentName Extent n
e) Extent n
e
                Result n
-> ReaderT (Context n) (StateT (RenderState n) Identity) (Result n)
forall a.
a -> ReaderT (Context n) (StateT (RenderState n) Identity) a
forall (m :: * -> *) a. Monad m => a -> m a
return Result n
result
                ) (Widget n -> StateT (RenderState n) Identity (Result n))
-> [Widget n] -> [StateT (RenderState n) Identity (Result n)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Widget n] -> [Widget n]
forall a. [a] -> [a]
reverse [Widget n]
layerRenders

        ctx :: Context n
ctx = Context { ctxAttrName :: AttrName
ctxAttrName = AttrName
forall a. Monoid a => a
mempty
                      , availWidth :: Int
availWidth = Int
w
                      , availHeight :: Int
availHeight = Int
h
                      , windowWidth :: Int
windowWidth = Int
w
                      , windowHeight :: Int
windowHeight = Int
h
                      , ctxBorderStyle :: BorderStyle
ctxBorderStyle = BorderStyle
defaultBorderStyle
                      , ctxAttrMap :: AttrMap
ctxAttrMap = AttrMap
aMap
                      , ctxDynBorders :: Bool
ctxDynBorders = Bool
False
                      , ctxVScrollBarOrientation :: Maybe VScrollBarOrientation
ctxVScrollBarOrientation = Maybe VScrollBarOrientation
forall a. Maybe a
Nothing
                      , ctxVScrollBarRenderer :: Maybe (VScrollbarRenderer n)
ctxVScrollBarRenderer = Maybe (VScrollbarRenderer n)
forall a. Maybe a
Nothing
                      , ctxHScrollBarOrientation :: Maybe HScrollBarOrientation
ctxHScrollBarOrientation = Maybe HScrollBarOrientation
forall a. Maybe a
Nothing
                      , ctxHScrollBarRenderer :: Maybe (HScrollbarRenderer n)
ctxHScrollBarRenderer = Maybe (HScrollbarRenderer n)
forall a. Maybe a
Nothing
                      , ctxHScrollBarShowHandles :: Bool
ctxHScrollBarShowHandles = Bool
False
                      , ctxVScrollBarShowHandles :: Bool
ctxVScrollBarShowHandles = Bool
False
                      , ctxHScrollBarClickableConstr :: Maybe (ClickableScrollbarElement -> n -> n)
ctxHScrollBarClickableConstr = Maybe (ClickableScrollbarElement -> n -> n)
forall a. Maybe a
Nothing
                      , ctxVScrollBarClickableConstr :: Maybe (ClickableScrollbarElement -> n -> n)
ctxVScrollBarClickableConstr = Maybe (ClickableScrollbarElement -> n -> n)
forall a. Maybe a
Nothing
                      }

        layersTopmostFirst :: [Result n]
layersTopmostFirst = [Result n] -> [Result n]
forall a. [a] -> [a]
reverse [Result n]
layerResults
        pic :: Picture
pic = [Image] -> Picture
V.picForLayers ([Image] -> Picture) -> [Image] -> Picture
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Image -> Image
V.resize Int
w Int
h (Image -> Image) -> (Result n -> Image) -> Result n -> Image
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Result n -> Getting Image (Result n) Image -> Image
forall s a. s -> Getting a s a -> a
^.Getting Image (Result n) Image
forall n (f :: * -> *).
Functor f =>
(Image -> f Image) -> Result n -> f (Result n)
imageL) (Result n -> Image) -> [Result n] -> [Image]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Result n]
layersTopmostFirst

        -- picWithBg is a workaround for runaway attributes.
        -- See https://github.com/coreyoconnor/vty/issues/95
        picWithBg :: Picture
picWithBg = Picture
pic { V.picBackground = V.Background ' ' V.defAttr }

        layerCursors :: [[CursorLocation n]]
layerCursors = (Result n
-> Getting [CursorLocation n] (Result n) [CursorLocation n]
-> [CursorLocation n]
forall s a. s -> Getting a s a -> a
^.Getting [CursorLocation n] (Result n) [CursorLocation n]
forall n (f :: * -> *).
Functor f =>
([CursorLocation n] -> f [CursorLocation n])
-> Result n -> f (Result n)
cursorsL) (Result n -> [CursorLocation n])
-> [Result n] -> [[CursorLocation n]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Result n]
layersTopmostFirst
        layerExtents :: [[Extent n]]
layerExtents = [[Extent n]] -> [[Extent n]]
forall a. [a] -> [a]
reverse ([[Extent n]] -> [[Extent n]]) -> [[Extent n]] -> [[Extent n]]
forall a b. (a -> b) -> a -> b
$ (Result n -> Getting [Extent n] (Result n) [Extent n] -> [Extent n]
forall s a. s -> Getting a s a -> a
^.Getting [Extent n] (Result n) [Extent n]
forall n (f :: * -> *).
Functor f =>
([Extent n] -> f [Extent n]) -> Result n -> f (Result n)
extentsL) (Result n -> [Extent n]) -> [Result n] -> [[Extent n]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Result n]
layersTopmostFirst
        theCursor :: Maybe (CursorLocation n)
theCursor = [CursorLocation n] -> Maybe (CursorLocation n)
chooseCursor ([CursorLocation n] -> Maybe (CursorLocation n))
-> [CursorLocation n] -> Maybe (CursorLocation n)
forall a b. (a -> b) -> a -> b
$ [[CursorLocation n]] -> [CursorLocation n]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[CursorLocation n]]
layerCursors

-- | After rendering the specified widget, crop its result image to the
-- dimensions in the rendering context.
cropToContext :: Widget n -> Widget n
cropToContext :: forall n. Widget n -> Widget n
cropToContext Widget n
p =
    Size -> Size -> RenderM n (Result n) -> Widget n
forall n. Size -> Size -> RenderM n (Result n) -> Widget n
Widget (Widget n -> Size
forall n. Widget n -> Size
hSize Widget n
p) (Widget n -> Size
forall n. Widget n -> Size
vSize Widget n
p) (Widget n -> RenderM n (Result n)
forall n. Widget n -> RenderM n (Result n)
render Widget n
p RenderM n (Result n)
-> (Result n -> RenderM n (Result n)) -> RenderM n (Result n)
forall a b.
ReaderT (Context n) (State (RenderState n)) a
-> (a -> ReaderT (Context n) (State (RenderState n)) b)
-> ReaderT (Context n) (State (RenderState n)) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Result n -> RenderM n (Result n)
forall n. Result n -> RenderM n (Result n)
cropResultToContext)

cropResultToContext :: Result n -> RenderM n (Result n)
cropResultToContext :: forall n. Result n -> RenderM n (Result n)
cropResultToContext Result n
result = do
    Context n
c <- RenderM n (Context n)
forall n. RenderM n (Context n)
getContext
    Result n -> RenderM n (Result n)
forall a. a -> ReaderT (Context n) (State (RenderState n)) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result n -> RenderM n (Result n))
-> Result n -> RenderM n (Result n)
forall a b. (a -> b) -> a -> b
$ Result n
result Result n -> (Result n -> Result n) -> Result n
forall a b. a -> (a -> b) -> b
& (Image -> Identity Image) -> Result n -> Identity (Result n)
forall n (f :: * -> *).
Functor f =>
(Image -> f Image) -> Result n -> f (Result n)
imageL   ((Image -> Identity Image) -> Result n -> Identity (Result n))
-> (Image -> Image) -> Result n -> Result n
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Context n -> Image -> Image
forall n. Context n -> Image -> Image
cropImage   Context n
c
                    Result n -> (Result n -> Result n) -> Result n
forall a b. a -> (a -> b) -> b
& ([CursorLocation n] -> Identity [CursorLocation n])
-> Result n -> Identity (Result n)
forall n (f :: * -> *).
Functor f =>
([CursorLocation n] -> f [CursorLocation n])
-> Result n -> f (Result n)
cursorsL (([CursorLocation n] -> Identity [CursorLocation n])
 -> Result n -> Identity (Result n))
-> ([CursorLocation n] -> [CursorLocation n])
-> Result n
-> Result n
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Context n -> [CursorLocation n] -> [CursorLocation n]
forall n. Context n -> [CursorLocation n] -> [CursorLocation n]
cropCursors Context n
c
                    Result n -> (Result n -> Result n) -> Result n
forall a b. a -> (a -> b) -> b
& ([Extent n] -> Identity [Extent n])
-> Result n -> Identity (Result n)
forall n (f :: * -> *).
Functor f =>
([Extent n] -> f [Extent n]) -> Result n -> f (Result n)
extentsL (([Extent n] -> Identity [Extent n])
 -> Result n -> Identity (Result n))
-> ([Extent n] -> [Extent n]) -> Result n -> Result n
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Context n -> [Extent n] -> [Extent n]
forall n. Context n -> [Extent n] -> [Extent n]
cropExtents Context n
c
                    Result n -> (Result n -> Result n) -> Result n
forall a b. a -> (a -> b) -> b
& (BorderMap DynBorder -> Identity (BorderMap DynBorder))
-> Result n -> Identity (Result n)
forall n (f :: * -> *).
Functor f =>
(BorderMap DynBorder -> f (BorderMap DynBorder))
-> Result n -> f (Result n)
bordersL ((BorderMap DynBorder -> Identity (BorderMap DynBorder))
 -> Result n -> Identity (Result n))
-> (BorderMap DynBorder -> BorderMap DynBorder)
-> Result n
-> Result n
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Context n -> BorderMap DynBorder -> BorderMap DynBorder
forall n. Context n -> BorderMap DynBorder -> BorderMap DynBorder
cropBorders Context n
c

cropImage :: Context n -> V.Image -> V.Image
cropImage :: forall n. Context n -> Image -> Image
cropImage Context n
c = Int -> Int -> Image -> Image
V.crop (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Context n
cContext n -> Getting Int (Context n) Int -> Int
forall s a. s -> Getting a s a -> a
^.Getting Int (Context n) Int
forall n (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context n -> f (Context n)
availWidthL) (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Context n
cContext n -> Getting Int (Context n) Int -> Int
forall s a. s -> Getting a s a -> a
^.Getting Int (Context n) Int
forall n (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context n -> f (Context n)
availHeightL)

cropCursors :: Context n -> [CursorLocation n] -> [CursorLocation n]
cropCursors :: forall n. Context n -> [CursorLocation n] -> [CursorLocation n]
cropCursors Context n
ctx [CursorLocation n]
cs = (CursorLocation n -> Maybe (CursorLocation n))
-> [CursorLocation n] -> [CursorLocation n]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe CursorLocation n -> Maybe (CursorLocation n)
forall {n}. CursorLocation n -> Maybe (CursorLocation n)
cropCursor [CursorLocation n]
cs
    where
        -- A cursor location is removed if it is not within the region
        -- described by the context.
        cropCursor :: CursorLocation n -> Maybe (CursorLocation n)
cropCursor CursorLocation n
c | CursorLocation n -> Bool
forall {n}. CursorLocation n -> Bool
outOfContext CursorLocation n
c = Maybe (CursorLocation n)
forall a. Maybe a
Nothing
                     | Bool
otherwise      = CursorLocation n -> Maybe (CursorLocation n)
forall a. a -> Maybe a
Just CursorLocation n
c
        outOfContext :: CursorLocation n -> Bool
outOfContext CursorLocation n
c =
            [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or [ CursorLocation n
cCursorLocation n -> Getting Int (CursorLocation n) Int -> Int
forall s a. s -> Getting a s a -> a
^.(Location -> Const Int Location)
-> CursorLocation n -> Const Int (CursorLocation n)
forall n (f :: * -> *).
Functor f =>
(Location -> f Location)
-> CursorLocation n -> f (CursorLocation n)
cursorLocationL((Location -> Const Int Location)
 -> CursorLocation n -> Const Int (CursorLocation n))
-> ((Int -> Const Int Int) -> Location -> Const Int Location)
-> Getting Int (CursorLocation n) Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Int -> Const Int Int) -> Location -> Const Int Location
forall a. TerminalLocation a => Lens' a Int
Lens' Location Int
locationRowL    Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
               , CursorLocation n
cCursorLocation n -> Getting Int (CursorLocation n) Int -> Int
forall s a. s -> Getting a s a -> a
^.(Location -> Const Int Location)
-> CursorLocation n -> Const Int (CursorLocation n)
forall n (f :: * -> *).
Functor f =>
(Location -> f Location)
-> CursorLocation n -> f (CursorLocation n)
cursorLocationL((Location -> Const Int Location)
 -> CursorLocation n -> Const Int (CursorLocation n))
-> ((Int -> Const Int Int) -> Location -> Const Int Location)
-> Getting Int (CursorLocation n) Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Int -> Const Int Int) -> Location -> Const Int Location
forall a. TerminalLocation a => Lens' a Int
Lens' Location Int
locationColumnL Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
               , CursorLocation n
cCursorLocation n -> Getting Int (CursorLocation n) Int -> Int
forall s a. s -> Getting a s a -> a
^.(Location -> Const Int Location)
-> CursorLocation n -> Const Int (CursorLocation n)
forall n (f :: * -> *).
Functor f =>
(Location -> f Location)
-> CursorLocation n -> f (CursorLocation n)
cursorLocationL((Location -> Const Int Location)
 -> CursorLocation n -> Const Int (CursorLocation n))
-> ((Int -> Const Int Int) -> Location -> Const Int Location)
-> Getting Int (CursorLocation n) Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Int -> Const Int Int) -> Location -> Const Int Location
forall a. TerminalLocation a => Lens' a Int
Lens' Location Int
locationRowL    Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Context n
ctxContext n -> Getting Int (Context n) Int -> Int
forall s a. s -> Getting a s a -> a
^.Getting Int (Context n) Int
forall n (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context n -> f (Context n)
availHeightL
               , CursorLocation n
cCursorLocation n -> Getting Int (CursorLocation n) Int -> Int
forall s a. s -> Getting a s a -> a
^.(Location -> Const Int Location)
-> CursorLocation n -> Const Int (CursorLocation n)
forall n (f :: * -> *).
Functor f =>
(Location -> f Location)
-> CursorLocation n -> f (CursorLocation n)
cursorLocationL((Location -> Const Int Location)
 -> CursorLocation n -> Const Int (CursorLocation n))
-> ((Int -> Const Int Int) -> Location -> Const Int Location)
-> Getting Int (CursorLocation n) Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Int -> Const Int Int) -> Location -> Const Int Location
forall a. TerminalLocation a => Lens' a Int
Lens' Location Int
locationColumnL Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Context n
ctxContext n -> Getting Int (Context n) Int -> Int
forall s a. s -> Getting a s a -> a
^.Getting Int (Context n) Int
forall n (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context n -> f (Context n)
availWidthL
               ]

cropExtents :: Context n -> [Extent n] -> [Extent n]
cropExtents :: forall n. Context n -> [Extent n] -> [Extent n]
cropExtents Context n
ctx [Extent n]
es = (Extent n -> Maybe (Extent n)) -> [Extent n] -> [Extent n]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Extent n -> Maybe (Extent n)
forall {n}. Extent n -> Maybe (Extent n)
cropExtent [Extent n]
es
    where
        -- An extent is cropped in places where it is not within the
        -- region described by the context.
        --
        -- If its entirety is outside the context region, it is dropped.
        --
        -- Otherwise its size is adjusted so that it is contained within
        -- the context region.
        cropExtent :: Extent n -> Maybe (Extent n)
cropExtent (Extent n
n (Location (Int
c, Int
r)) (Int
w, Int
h)) =
            -- Determine the new lower-right corner
            let endCol :: Int
endCol = Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
w
                endRow :: Int
endRow = Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
h
                -- Then clamp the lower-right corner based on the
                -- context
                endCol' :: Int
endCol' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (Context n
ctxContext n -> Getting Int (Context n) Int -> Int
forall s a. s -> Getting a s a -> a
^.Getting Int (Context n) Int
forall n (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context n -> f (Context n)
availWidthL) Int
endCol
                endRow' :: Int
endRow' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (Context n
ctxContext n -> Getting Int (Context n) Int -> Int
forall s a. s -> Getting a s a -> a
^.Getting Int (Context n) Int
forall n (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context n -> f (Context n)
availHeightL) Int
endRow
                -- Then compute the new width and height from the
                -- clamped lower-right corner.
                w' :: Int
w' = Int
endCol' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
c
                h' :: Int
h' = Int
endRow' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
r
                e :: Extent n
e = n -> Location -> DisplayRegion -> Extent n
forall n. n -> Location -> DisplayRegion -> Extent n
Extent n
n (DisplayRegion -> Location
Location (Int
c, Int
r)) (Int
w', Int
h')
            in if Int
w' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
h' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
               then Maybe (Extent n)
forall a. Maybe a
Nothing
               else Extent n -> Maybe (Extent n)
forall a. a -> Maybe a
Just Extent n
e

cropBorders :: Context n -> BorderMap DynBorder -> BorderMap DynBorder
cropBorders :: forall n. Context n -> BorderMap DynBorder -> BorderMap DynBorder
cropBorders Context n
ctx = Edges Int -> BorderMap DynBorder -> BorderMap DynBorder
forall a. Edges Int -> BorderMap a -> BorderMap a
BM.crop Edges
    { eTop :: Int
eTop = Int
0
    , eBottom :: Int
eBottom = Context n -> Int
forall n. Context n -> Int
availHeight Context n
ctx Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    , eLeft :: Int
eLeft = Int
0
    , eRight :: Int
eRight = Context n -> Int
forall n. Context n -> Int
availWidth Context n
ctx Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    }

renderDynBorder :: DynBorder -> V.Image
renderDynBorder :: DynBorder -> Image
renderDynBorder DynBorder
db = Attr -> Char -> Image
V.char (DynBorder -> Attr
dbAttr DynBorder
db) (Char -> Image) -> Char -> Image
forall a b. (a -> b) -> a -> b
$ BorderStyle -> Char
getBorderChar (BorderStyle -> Char) -> BorderStyle -> Char
forall a b. (a -> b) -> a -> b
$ DynBorder -> BorderStyle
dbStyle DynBorder
db
    where
        getBorderChar :: BorderStyle -> Char
getBorderChar = case BorderSegment -> Bool
bsDraw (BorderSegment -> Bool) -> Edges BorderSegment -> Edges Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynBorder -> Edges BorderSegment
dbSegments DynBorder
db of
            --    top   bot   left  right
            Edges Bool
False Bool
False Bool
False Bool
False -> Char -> BorderStyle -> Char
forall a b. a -> b -> a
const Char
' '
            Edges Bool
False Bool
False Bool
_     Bool
_     -> BorderStyle -> Char
bsHorizontal
            Edges Bool
_     Bool
_     Bool
False Bool
False -> BorderStyle -> Char
bsVertical
            Edges Bool
False Bool
True  Bool
False Bool
True  -> BorderStyle -> Char
bsCornerTL
            Edges Bool
False Bool
True  Bool
True  Bool
False -> BorderStyle -> Char
bsCornerTR
            Edges Bool
True  Bool
False Bool
False Bool
True  -> BorderStyle -> Char
bsCornerBL
            Edges Bool
True  Bool
False Bool
True  Bool
False -> BorderStyle -> Char
bsCornerBR
            Edges Bool
False Bool
True  Bool
True  Bool
True  -> BorderStyle -> Char
bsIntersectT
            Edges Bool
True  Bool
False Bool
True  Bool
True  -> BorderStyle -> Char
bsIntersectB
            Edges Bool
True  Bool
True  Bool
False Bool
True  -> BorderStyle -> Char
bsIntersectL
            Edges Bool
True  Bool
True  Bool
True  Bool
False -> BorderStyle -> Char
bsIntersectR
            Edges Bool
True  Bool
True  Bool
True  Bool
True  -> BorderStyle -> Char
bsIntersectFull

-- | This function provides a simplified interface to rendering a list
-- of 'Widget's as a 'V.Picture' outside of the context of an 'App'.
-- This can be useful in a testing setting but isn't intended to be used
-- for normal application rendering. The API is deliberately narrower
-- than the main interactive API and is not yet stable. Use at your own
-- risk.
--
-- Consult the [Vty library documentation](https://hackage.haskell.org/package/vty)
-- for details on how to output the resulting 'V.Picture'.
renderWidget :: (Ord n)
             => Maybe AttrMap
             -- ^ Optional attribute map used to render. If omitted,
             -- an empty attribute map with the terminal's default
             -- attribute will be used.
             -> [Widget n]
             -- ^ The widget layers to render, topmost first.
             -> V.DisplayRegion
             -- ^ The size of the display region in which to render the
             -- layers.
             -> V.Picture
renderWidget :: forall n.
Ord n =>
Maybe AttrMap -> [Widget n] -> DisplayRegion -> Picture
renderWidget Maybe AttrMap
mAttrMap [Widget n]
layerRenders DisplayRegion
region = Picture
pic
    where
        initialRS :: RenderState n
initialRS = RS { viewportMap :: Map n Viewport
viewportMap = Map n Viewport
forall k a. Map k a
M.empty
                       , rsScrollRequests :: [(n, ScrollRequest)]
rsScrollRequests = []
                       , observedNames :: Set n
observedNames = Set n
forall a. Set a
S.empty
                       , renderCache :: Map n ([n], Result n)
renderCache = Map n ([n], Result n)
forall a. Monoid a => a
mempty
                       , clickableNames :: [n]
clickableNames = []
                       , requestedVisibleNames_ :: Set n
requestedVisibleNames_ = Set n
forall a. Set a
S.empty
                       , reportedExtents :: Map n (Extent n)
reportedExtents = Map n (Extent n)
forall a. Monoid a => a
mempty
                       }
        am :: AttrMap
am = AttrMap -> Maybe AttrMap -> AttrMap
forall a. a -> Maybe a -> a
fromMaybe (Attr -> [(AttrName, Attr)] -> AttrMap
attrMap Attr
V.defAttr []) Maybe AttrMap
mAttrMap
        (RenderState n
_, Picture
pic, Maybe (CursorLocation n)
_, [Extent n]
_) = AttrMap
-> [Widget n]
-> DisplayRegion
-> ([CursorLocation n] -> Maybe (CursorLocation n))
-> RenderState n
-> (RenderState n, Picture, Maybe (CursorLocation n), [Extent n])
forall n.
Ord n =>
AttrMap
-> [Widget n]
-> DisplayRegion
-> ([CursorLocation n] -> Maybe (CursorLocation n))
-> RenderState n
-> (RenderState n, Picture, Maybe (CursorLocation n), [Extent n])
renderFinal AttrMap
am [Widget n]
layerRenders DisplayRegion
region (Maybe (CursorLocation n)
-> [CursorLocation n] -> Maybe (CursorLocation n)
forall a b. a -> b -> a
const Maybe (CursorLocation n)
forall a. Maybe a
Nothing) RenderState n
initialRS