-----------------------------------------------------------------------------
-- |
-- Module      :  GI.Cairo.Render.Connector
-- Copyright   :  (c) Kilian Kilger, Iñaki García Etxebarria 2018 
-- License     :  LGPL-2.1
--
-- Maintainer  :  kkilger@gmail.com
-- Stability   :  experimental
-- Portability :  portable
--
-- This library contains glue code to interconnect Haskell GI, i.e. the gi-cairo
-- library and gi-cairo-render, i.e. the hand written cairo bindings for Haskell.
----------------------------------------------------------------------------- 
module GI.Cairo.Render.Connector (
   renderWithContext, getContext, toRender
) where

import qualified GI.Cairo(Context(..)) 
import Data.GI.Base(ManagedPtr)
import GI.Cairo.Render(Render)
import GI.Cairo.Render.Internal(Cairo(..), unCairo, runRender)
import Control.Monad.Reader(MonadIO, runReaderT, asks)
import Control.Monad.IO.Class(liftIO)
import Data.Coerce(coerce)

-- | This function is used to call a function in the 'GI.Cairo.Render.Render' monad
-- from the draw function of GTK+. It takes a 'GI.Cairo.Structs.Context' (as it
-- appears in [gi-cairo](https://hackage.haskell.org/package/gi-cairo)) and a 
-- 'GI.Cairo.Render.Render' action (as it appears in gi-cairo-render)
-- and renders the `Render` context inside the given context.
renderWithContext :: MonadIO m => 
                         Render a                   -- ^ Render action
                      -> GI.Cairo.Context           -- ^ Context from gi-cairo 
                      -> m a                        -- ^ Result of the action
renderWithContext :: forall (m :: * -> *) a. MonadIO m => Render a -> Context -> m a
renderWithContext Render a
r (GI.Cairo.Context ManagedPtr Context
ctxt) = 
  let cairo :: ManagedPtr Cairo
cairo = ManagedPtr Context -> ManagedPtr Cairo
forall a b. Coercible a b => a -> b
coerce ManagedPtr Context
ctxt :: ManagedPtr Cairo
  in IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ ReaderT Cairo IO a -> Cairo -> IO a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (Render a -> ReaderT Cairo IO a
forall m. Render m -> ReaderT Cairo IO m
runRender Render a
r) (ManagedPtr Cairo -> Cairo
Cairo ManagedPtr Cairo
cairo)

-- | This function is used to call back to functions of GI.Pango or GI.PangoCairo
-- or other Haskell GI libraries from inside the `Cairo.Render` action. 
-- Example:
-- 
-- > draw :: Cairo.Render () 
-- > draw = do ...
-- >           context <- getContext
-- >           somePangoFunction context
-- 
getContext :: Render GI.Cairo.Context -- ^ Underlying GI.Cairo.Context 
getContext :: Render Context
getContext = do ManagedPtr Cairo
cairo <- (Cairo -> ManagedPtr Cairo) -> Render (ManagedPtr Cairo)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Cairo -> ManagedPtr Cairo
unCairo
                let ctxt :: ManagedPtr Context
ctxt = ManagedPtr Cairo -> ManagedPtr Context
forall a b. Coercible a b => a -> b
coerce ManagedPtr Cairo
cairo :: ManagedPtr GI.Cairo.Context
                Context -> Render Context
forall a. a -> Render a
forall (m :: * -> *) a. Monad m => a -> m a
return (Context -> Render Context) -> Context -> Render Context
forall a b. (a -> b) -> a -> b
$ ManagedPtr Context -> Context
GI.Cairo.Context ManagedPtr Context
ctxt
               
-- | This function is used to "lift" functions of GI.Pango or GI.PangoCairo
-- to the Render monad.
-- Example:
-- 
-- > draw :: Cairo.Render () 
-- > draw = do ...
-- >           toRender somePangoFunction
  
toRender :: (GI.Cairo.Context -> IO a) -> Render a
toRender :: forall a. (Context -> IO a) -> Render a
toRender Context -> IO a
fun = do Context
context <- Render Context
getContext
                  IO a -> Render a
forall a. IO a -> Render a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> Render a) -> IO a -> Render a
forall a b. (a -> b) -> a -> b
$ Context -> IO a
fun Context
context