module NanoUI.Frame.Paint.Types
( PaintEnv (..)
, buildPaintEnv
, popupPanelRect
) where
import Data.IORef (readIORef)
import Data.Primitive.PrimArray (PrimArray)
import NanoUI.Context (Context (..))
import NanoUI.Draw (DrawArena)
import NanoUI.Font (FontMetrics)
import NanoUI.Id (WidgetId (..))
import NanoUI.Layout.Arena
( NodeArena
, NodeIdx
, NodeType (..)
, getNodeType
, getParent
, getRect
)
import NanoUI.Style (Theme)
import NanoUI.Types (Rect (..))
data PaintEnv = PaintEnv
{ PaintEnv -> Context
peContext :: Context
, PaintEnv -> NodeArena
peNodeArena :: NodeArena
, PaintEnv -> DrawArena
peDrawArena :: DrawArena
, PaintEnv -> Theme
peTheme :: Theme
, PaintEnv -> NodeIdx
peScope :: Int
, PaintEnv -> FontMetrics
peFontMetrics :: FontMetrics
, PaintEnv -> PrimArray Float
peOccluders :: PrimArray Float
, PaintEnv -> WidgetId
peFocusRing :: WidgetId
}
{-# NOINLINE buildPaintEnv #-}
buildPaintEnv :: Context -> PrimArray Float -> IO PaintEnv
buildPaintEnv :: Context -> PrimArray Float -> IO PaintEnv
buildPaintEnv Context
ctx PrimArray Float
occluders = do
theme <- IORef Theme -> IO Theme
forall a. IORef a -> IO a
readIORef (Context -> IORef Theme
ctxTheme Context
ctx)
focus <- readIORef (ctxFocusId ctx)
focusVisible <- readIORef (ctxFocusVisible ctx)
pure PaintEnv
{ peContext = ctx
, peNodeArena = ctxNodeArena ctx
, peDrawArena = ctxDrawArena ctx
, peTheme = theme
, peScope = 0
, peFontMetrics = ctxFontMetrics ctx
, peOccluders = occluders
, peFocusRing = if focusVisible then focus else WidgetId 0
}
popupPanelRect :: Context -> NodeIdx -> IO (Maybe Rect)
Context
ctx = NodeIdx -> IO (Maybe Rect)
go
where
go :: NodeIdx -> IO (Maybe Rect)
go NodeIdx
i = do
p <- NodeArena -> NodeIdx -> IO NodeIdx
getParent (Context -> NodeArena
ctxNodeArena Context
ctx) NodeIdx
i
if p < 0
then pure Nothing
else do
nt <- getNodeType (ctxNodeArena ctx) p
if nt == NodePopup
then do
(px, py, pw, ph) <- getRect (ctxNodeArena ctx) p
pure (Just (Rect px py pw ph))
else go p